Skip to main content

azoth_core/
observe.rs

1//! Optional metrics instrumentation for Azoth.
2//!
3//! When the `observe` feature is enabled, key operations emit counters,
4//! histograms, and gauges via the [`metrics`] crate. A downstream
5//! application must install a metrics recorder (e.g. `metrics-exporter-prometheus`)
6//! to collect the data.
7//!
8//! When the feature is **not** enabled every function in this module is a
9//! zero-cost no-op.
10
11/// Record a transaction commit (counter + latency histogram).
12///
13/// - `azoth.transaction.commits_total` – incremented on every commit
14/// - `azoth.transaction.commit_duration_seconds` – histogram of commit latency
15#[inline]
16pub fn record_commit(duration: std::time::Duration) {
17    #[cfg(feature = "observe")]
18    {
19        metrics::counter!("azoth.transaction.commits_total").increment(1);
20        metrics::histogram!("azoth.transaction.commit_duration_seconds")
21            .record(duration.as_secs_f64());
22    }
23    #[cfg(not(feature = "observe"))]
24    {
25        let _ = duration;
26    }
27}
28
29/// Record a preflight validation (counter + duration).
30///
31/// - `azoth.preflight.total` – counter
32/// - `azoth.preflight.duration_seconds` – histogram
33#[inline]
34pub fn record_preflight(duration: std::time::Duration, success: bool) {
35    #[cfg(feature = "observe")]
36    {
37        let outcome = if success { "ok" } else { "fail" };
38        metrics::counter!("azoth.preflight.total", "outcome" => outcome).increment(1);
39        metrics::histogram!("azoth.preflight.duration_seconds").record(duration.as_secs_f64());
40    }
41    #[cfg(not(feature = "observe"))]
42    {
43        let _ = (duration, success);
44    }
45}
46
47/// Record a preflight cache hit or miss.
48///
49/// - `azoth.preflight_cache.lookups_total` – counter with `result` label (`hit` / `miss`)
50#[inline]
51pub fn record_cache_lookup(hit: bool) {
52    #[cfg(feature = "observe")]
53    {
54        let result = if hit { "hit" } else { "miss" };
55        metrics::counter!("azoth.preflight_cache.lookups_total", "result" => result).increment(1);
56    }
57    #[cfg(not(feature = "observe"))]
58    {
59        let _ = hit;
60    }
61}
62
63/// Set the current preflight cache size gauge.
64///
65/// - `azoth.preflight_cache.size` – gauge
66#[inline]
67pub fn set_cache_size(size: usize) {
68    #[cfg(feature = "observe")]
69    {
70        metrics::gauge!("azoth.preflight_cache.size").set(size as f64);
71    }
72    #[cfg(not(feature = "observe"))]
73    {
74        let _ = size;
75    }
76}
77
78/// Record a projector run (counter + duration + events processed).
79///
80/// - `azoth.projector.runs_total` – counter
81/// - `azoth.projector.run_duration_seconds` – histogram
82/// - `azoth.projector.events_processed_total` – counter
83#[inline]
84pub fn record_projector_run(duration: std::time::Duration, events_processed: u64) {
85    #[cfg(feature = "observe")]
86    {
87        metrics::counter!("azoth.projector.runs_total").increment(1);
88        metrics::histogram!("azoth.projector.run_duration_seconds").record(duration.as_secs_f64());
89        metrics::counter!("azoth.projector.events_processed_total").increment(events_processed);
90    }
91    #[cfg(not(feature = "observe"))]
92    {
93        let _ = (duration, events_processed);
94    }
95}
96
97/// Record a lock acquisition wait time.
98///
99/// - `azoth.lock.wait_duration_seconds` – histogram
100#[inline]
101pub fn record_lock_wait(duration: std::time::Duration) {
102    #[cfg(feature = "observe")]
103    {
104        metrics::histogram!("azoth.lock.wait_duration_seconds").record(duration.as_secs_f64());
105    }
106    #[cfg(not(feature = "observe"))]
107    {
108        let _ = duration;
109    }
110}
111
112/// Record a backup operation.
113///
114/// - `azoth.backup.total` – counter with `outcome` label
115/// - `azoth.backup.duration_seconds` – histogram
116#[inline]
117pub fn record_backup(duration: std::time::Duration, success: bool) {
118    #[cfg(feature = "observe")]
119    {
120        let outcome = if success { "ok" } else { "fail" };
121        metrics::counter!("azoth.backup.total", "outcome" => outcome).increment(1);
122        metrics::histogram!("azoth.backup.duration_seconds").record(duration.as_secs_f64());
123    }
124    #[cfg(not(feature = "observe"))]
125    {
126        let _ = (duration, success);
127    }
128}