photon_telemetry/lib.rs
1//! Operations telemetry port for Photon.
2//!
3//! Hosts install a process-wide [`OpsLog`] via [`install_ops_log`] or
4//! [`PhotonBuilder::ops_log`](https://docs.rs/uf-photon/latest/photon/struct.PhotonBuilder.html#method.ops_log).
5//! Backend instrumentation (publish counters, DLQ rows, checkpoint failures) calls [`ops_log`].
6//!
7//! ## Entry points
8//!
9//! - [`OpsLog`] — counter / gauge / event trait
10//! - [`install_ops_log`] / [`ops_log`] / [`ops_log_from_env`] — process-wide adapter
11//! - [`ConsoleOpsLog`] / [`NoOpsLog`] — shipped adapters
12//!
13//! Runnable: `cargo run -p uf-photon --example telemetry_ops_log --features runtime,mem`.
14
15#![cfg_attr(test, allow(clippy::unwrap_used, clippy::expect_used))]
16
17mod console;
18mod global;
19mod noop;
20
21#[cfg(feature = "recording")]
22mod recording;
23
24pub use console::ConsoleOpsLog;
25pub use global::{install_ops_log, ops_log, ops_log_from_env};
26pub use noop::NoOpsLog;
27
28#[cfg(feature = "recording")]
29pub use recording::{RecordedCounter, RecordedEvent, RecordedGauge, RecordingOpsLog};
30
31/// Structured ops metrics/events for publish, drain, DLQ, checkpoints.
32///
33/// Install before or during [`PhotonBuilder::build`](https://docs.rs/uf-photon/latest/photon/struct.PhotonBuilder.html#method.build)
34/// via [`PhotonBuilder::ops_log`](https://docs.rs/uf-photon/latest/photon/struct.PhotonBuilder.html#method.ops_log)
35/// (or [`install_ops_log`]). Photon calls this trait from backend instrumentation — it is not the
36/// application event bus.
37///
38/// # Example
39///
40/// ```rust,ignore
41/// use photon_runtime::Photon;
42/// use photon_telemetry::ConsoleOpsLog;
43///
44/// let _photon = Photon::builder()
45/// .ops_log(ConsoleOpsLog)
46/// .auto_registry()
47/// .build()?;
48/// ```
49pub trait OpsLog: Send + Sync {
50 /// Increment a counter with optional labels.
51 fn record_counter(&self, name: &str, labels: &[(&str, &str)], value: f64);
52
53 /// Set a gauge with optional labels.
54 fn record_gauge(&self, name: &str, labels: &[(&str, &str)], value: f64);
55
56 /// Emit a structured diagnostic event.
57 fn log_event(&self, name: &str, payload: &serde_json::Value);
58}
59
60#[cfg(test)]
61mod tests {
62 use super::{ConsoleOpsLog, NoOpsLog, OpsLog};
63
64 #[test]
65 fn noop_ops_log_is_silent() {
66 let log = NoOpsLog;
67 log.record_counter("c", &[], 1.0);
68 log.record_gauge("g", &[], 2.0);
69 log.log_event("e", &serde_json::json!({}));
70 }
71
72 #[test]
73 fn console_ops_log_does_not_panic() {
74 let log = ConsoleOpsLog;
75 log.record_counter("photon_publishes", &[("topic", "t")], 1.0);
76 }
77}