Skip to main content

boson_telemetry/
lib.rs

1//! Operations telemetry for Boson workers.
2//!
3//! Install an [`OpsLog`] adapter at worker boot via [`BosonBuilder::ops_log`](https://docs.rs/boson-runtime/latest/boson_runtime/struct.BosonBuilder.html#method.ops_log).
4//!
5//! ## Entry points
6//!
7//! - [`OpsLog`] — counters, gauges, structured events (see trait for emitted names)
8//! - [`install_ops_log`] — process-wide install at boot
9//! - [`NoOpsLog`] / [`ConsoleOpsLog`] — built-in adapters
10//! - [`ops_log_from_env`] — select adapter via `BOSON_TELEMETRY`
11
12mod console;
13mod global;
14mod noop;
15
16pub use console::ConsoleOpsLog;
17pub use global::{install_ops_log, ops_log, ops_log_from_env};
18pub use noop::NoOpsLog;
19
20/// Structured ops metrics and events for enqueue, runs, leases, and runtime health.
21///
22/// The runtime emits the following by default (labels vary by call site):
23///
24/// **Counters**
25///
26/// | Name | When |
27/// |------|------|
28/// | `boson_tasks_enqueued` | Job enqueued (`task_name`, `runtime` labels) |
29/// | `boson_tasks_completed` | Handler succeeded (`task_name` label) |
30/// | `boson_task_duration_ms` | Handler succeeded — duration as counter value |
31/// | `boson_tasks_failed` | Handler failed (`task_name` label) |
32///
33/// **Events** (`log_event` name → payload highlights)
34///
35/// | Name | When |
36/// |------|------|
37/// | `boson_task_log` | Run started or completed (`event`, `task_name`, `job_id`, `run_id`, …) |
38/// | `boson_handler_error` | Handler error (`task_name`, `job_id`, `message`, optional `will_retry`) |
39/// | `boson_runtime_log` | Runtime ready or lease reclaim (`event`, `runtime`, …) |
40///
41/// Install a custom adapter with [`install_ops_log`] to forward these to your metrics stack.
42/// Use [`ConsoleOpsLog`], [`NoOpsLog`], or a custom [`OpsLog`] implementation.
43pub trait OpsLog: Send + Sync {
44    /// Increment a counter with optional labels.
45    fn record_counter(&self, name: &str, labels: &[(&str, &str)], value: f64);
46
47    /// Set a gauge with optional labels.
48    fn record_gauge(&self, name: &str, labels: &[(&str, &str)], value: f64);
49
50    /// Emit a structured diagnostic event (see trait-level table for runtime event names).
51    fn log_event(&self, name: &str, payload: &serde_json::Value);
52}
53
54#[cfg(test)]
55mod tests {
56    use super::{ConsoleOpsLog, NoOpsLog, OpsLog};
57
58    #[test]
59    fn noop_ops_log_is_silent() {
60        let log = NoOpsLog;
61        log.record_counter("c", &[], 1.0);
62        log.record_gauge("g", &[], 2.0);
63        log.log_event("e", &serde_json::json!({}));
64    }
65
66    #[test]
67    fn console_ops_log_does_not_panic() {
68        let log = ConsoleOpsLog;
69        log.record_counter("boson_tasks_enqueued", &[("task_name", "t")], 1.0);
70    }
71}