Skip to main content

Metrics

Metrics are numeric measurements emitted over time. Bot Pulse lets you track anything — latency, resource usage, custom counters — and visualize them per robot or across your fleet.

Emitting a metric

main.py
import botpulse
import time

pulse = botpulse.init(
service_name="navigation-node",
robot_id="robot-01",
)

# Simple metric
pulse.metric("navigation_latency_ms", 142.3)

Metric types

Bot Pulse supports three metric types:

Counter

A value that only goes up. Useful for counting events.

main.py
import botpulse

pulse = botpulse.init(service_name="perception", robot_id="robot-01")

# Count objects detected
pulse.counter("objects_detected", value=3)
pulse.counter("objects_detected", value=1) # adds 1 more

Gauge

A value that goes up and down. Useful for current state.

main.py
import botpulse

pulse = botpulse.init(service_name="battery-monitor", robot_id="robot-01")

# Battery state of charge
pulse.gauge("battery_soc_percent", value=82.5)
pulse.gauge("battery_soc_percent", value=79.1) # updated

Histogram

A distribution of values. Useful for latency, size, etc.

main.py
import botpulse

pulse = botpulse.init(service_name="planning", robot_id="robot-01")

# Record planning duration
pulse.histogram("planning_duration_ms", value=45.2)
pulse.histogram("planning_duration_ms", value=38.7)

Adding attributes to metrics

Attach dimensions to slice and filter your metrics:

main.py
import botpulse

pulse = botpulse.init(service_name="motor-driver", robot_id="robot-01")

pulse.metric(
"motor_speed_rpm",
value=1200,
attributes={
"motor_id": "left_front",
"direction": "forward",
},
)

pulse.metric(
"motor_speed_rpm",
value=1195,
attributes={
"motor_id": "right_front",
"direction": "forward",
},
)

Combining traces and metrics

The most powerful pattern is emitting metrics inside traces, giving you both distributed tracing and aggregate statistics:

main.py
import botpulse
import time

pulse = botpulse.init(service_name="perception", robot_id="robot-01")

with pulse.trace("detect_objects") as span:
start = time.monotonic()

results = run_detection(camera_frame)

latency_ms = (time.monotonic() - start) * 1000
pulse.metric("detection_latency_ms", latency_ms)
pulse.counter("objects_detected", value=len(results))
pulse.gauge("active_object_count", value=len(results))

span.set_attribute("objects_found", len(results))
span.set_attribute("latency_ms", latency_ms)

Now you can:

  • See the full trace for every detection run
  • View a latency histogram across all runs
  • Track the average number of detected objects over time

Emitting metrics from callbacks

A common pattern in robot applications is periodic publishing:

main.py
import botpulse

pulse = botpulse.init(service_name="system-monitor", robot_id="robot-01")

def on_timer_callback():
"""Called every 1 second by your robot framework."""
cpu_usage = read_cpu_usage()
mem_usage = read_memory_usage()

pulse.gauge("cpu_usage_percent", value=cpu_usage)
pulse.gauge("memory_usage_mb", value=mem_usage)

Best practices

  • Use descriptive namesnavigation_latency_ms not lat1
  • Include units in the name_ms, _bytes, _percent, _rpm
  • Keep attribute cardinality low — don't use IDs or timestamps as metric attributes
  • Emit metrics at steady intervals — this makes time-series data meaningful

Next steps