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 names —
navigation_latency_msnotlat1 - 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
- ROS2 Integration — Use Bot Pulse with ROS2 nodes
- API Reference — Full Python API documentation