valence_telemetry/lib.rs
1//! Valence self-telemetry port.
2//!
3//! **Audience:** integrators installing metrics at boot and adapter authors
4//! implementing custom sinks.
5
6#![deny(missing_docs)]
7
8mod console;
9mod dispatch;
10mod noop;
11mod recording;
12
13pub use console::ConsoleSink;
14pub use dispatch::{
15 install_telemetry_sink, json_value_to_fields, telemetry_sink, try_log_event,
16 try_log_event_value, try_record_counter, try_record_gauge,
17};
18pub use noop::NoOpSink;
19pub use recording::{RecordedCounter, RecordedEvent, RecordedGauge, RecordingSink};
20
21/// Host-injectable telemetry sink for Valence ORM metrics and events.
22///
23/// Install with `ValenceBuilder::telemetry_sink` on the facade / `valence-core`.
24/// Instrumentation calls [`try_record_counter`], [`try_record_gauge`], and
25/// [`try_log_event_value`] — never a product SDK from upstream code.
26///
27/// Reference impls: [`NoOpSink`] (default), [`ConsoleSink`] (facade `telemetry-console`
28/// feature). Custom sinks belong in host crates.
29///
30/// # Examples
31///
32/// ```
33/// use valence_telemetry::{ConsoleSink, TelemetrySink};
34///
35/// let sink = ConsoleSink;
36/// sink.record_counter("valence_queries", &[("backend", "mem")], 1);
37/// sink.record_gauge("valence_active_connections", &[], 0.0);
38/// sink.log_event("valence.boot", &[("phase", "ready")]);
39/// ```
40pub trait TelemetrySink: Send + Sync {
41 /// Increment a counter metric by `delta` with optional label dimensions.
42 fn record_counter(&self, name: &str, labels: &[(&str, &str)], delta: u64);
43
44 /// Record a gauge sample with optional label dimensions.
45 fn record_gauge(&self, name: &str, labels: &[(&str, &str)], value: f64);
46
47 /// Emit a structured log event from flat field tuples.
48 fn log_event(&self, schema: &str, fields: &[(&str, &str)]);
49
50 /// Structured event with JSON payload (default flattens top-level object keys).
51 fn log_event_value(&self, schema: &str, payload: &serde_json::Value) {
52 let owned = json_value_to_fields(payload);
53 let refs: Vec<(&str, &str)> = owned
54 .iter()
55 .map(|(k, v)| (k.as_str(), v.as_str()))
56 .collect();
57 self.log_event(schema, &refs);
58 }
59}
60
61#[cfg(test)]
62mod tests {
63 use super::*;
64
65 #[test]
66 fn noop_sink_accepts_metrics() {
67 let sink = NoOpSink;
68 sink.record_counter("valence_queries", &[("backend", "mem")], 1);
69 sink.record_gauge("valence_active_connections", &[], 0.0);
70 sink.log_event("valence.record.created", &[("table", "user")]);
71 }
72
73 #[test]
74 fn console_sink_accepts_metrics() {
75 let sink = ConsoleSink;
76 sink.record_counter("valence_queries", &[], 1);
77 }
78}