fedimint_metrics/
lib.rs

1#![deny(clippy::pedantic)]
2#![allow(clippy::missing_errors_doc)]
3
4use std::sync::LazyLock;
5use std::time::SystemTime;
6
7use prometheus::Registry;
8pub use prometheus::{
9    self, Encoder, Gauge, GaugeVec, Histogram, HistogramVec, IntCounter, IntCounterVec,
10    TextEncoder, histogram_opts, opts, register_histogram_with_registry,
11    register_int_counter_vec_with_registry,
12};
13
14/// A wasm-safe histogram timer that uses `fedimint_core::time::now` instead of
15/// `std::time::Instant`, which is not available on wasm targets.
16pub struct HistogramTimerExt {
17    histogram: Histogram,
18    start: SystemTime,
19}
20
21impl HistogramTimerExt {
22    /// Records the elapsed duration in seconds to the histogram.
23    pub fn observe_duration(self) {
24        let elapsed = fedimint_core::time::now()
25            .duration_since(self.start)
26            .unwrap_or_default();
27        self.histogram.observe(elapsed.as_secs_f64());
28    }
29}
30
31/// Extension trait for [`Histogram`] that provides a wasm-safe timer.
32pub trait HistogramExt {
33    /// Starts a wasm-safe timer that records duration on
34    /// [`HistogramTimerExt::observe_duration`].
35    fn start_timer_ext(&self) -> HistogramTimerExt;
36}
37
38impl HistogramExt for Histogram {
39    fn start_timer_ext(&self) -> HistogramTimerExt {
40        HistogramTimerExt {
41            histogram: self.clone(),
42            start: fedimint_core::time::now(),
43        }
44    }
45}
46
47// The server module depends on `axum` and `tokio` networking, which are not
48// available on wasm targets. Core metrics functionality (REGISTRY, get_metrics,
49// metric registration) remains available on all platforms.
50#[cfg(not(target_family = "wasm"))]
51mod server;
52#[cfg(not(target_family = "wasm"))]
53pub use server::spawn_api_server;
54
55pub static REGISTRY: LazyLock<Registry> =
56    LazyLock::new(|| Registry::new_custom(Some("fm".into()), None).unwrap());
57
58pub static AMOUNTS_BUCKETS_SATS: LazyLock<Vec<f64>> = LazyLock::new(|| {
59    vec![
60        0.0,
61        0.1,
62        1.0,
63        10.0,
64        100.0,
65        1000.0,
66        10000.0,
67        100_000.0,
68        1_000_000.0,
69        10_000_000.0,
70        100_000_000.0,
71    ]
72});
73
74/// Returns all registered metrics encoded in Prometheus text format.
75pub fn get_metrics() -> anyhow::Result<String> {
76    let metric_families = REGISTRY.gather();
77    let mut buffer = Vec::new();
78    let encoder = TextEncoder::new();
79    encoder.encode(&metric_families, &mut buffer)?;
80    Ok(String::from_utf8(buffer)?)
81}