darkwing/server/utils/
metrics.rs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
use anyhow::Context as _;
use metrics_exporter_prometheus::{PrometheusBuilder, PrometheusHandle};

const QUANTILES: &[f64] =
  &[0.0, 0.1, 0.3, 0.5, 0.6, 0.8, 0.9, 0.95, 0.99, 0.999, 1.0];

/// Measures the execution time of a code block and records it as a histogram
/// metric.
///
/// # Arguments
///
/// * `$name` - The name of the metric to record the timing under
/// * `$body` - The code block or expression to measure
///
/// # Example
///
/// ```
/// let result = measure_time!("my_operation", db.fetch_user(id));
/// ```
/// Or:
/// ```
/// let result = measure_time!("my_operation", {
///      db.fetch_user(id)
/// });
/// ```
///
/// This will record the execution time of the code block under the metric name
/// `darkwing_time_my_operation_duration_seconds` as a histogram in seconds.
#[macro_export]
macro_rules! measure_time {
  ($name:expr, $body:expr) => {{
    let name = format!("darkwing_time_{}_duration_seconds", $name);
    let start = std::time::Instant::now();
    let result = $body;
    let duration = start.elapsed();
    metrics::histogram!(name).record(duration.as_secs_f64());
    result
  }};
}

/// Builds and installs a Prometheus metrics recorder with custom histogram
/// buckets.
///
/// Configures buckets for:
/// * HTTP request durations (exponential)
/// * Diff and data directory sizes (size-based)
/// * Size reduction ratios
/// * All duration metrics (exponential)
///
/// # Errors
/// Returns an error if bucket configuration or recorder installation fails
pub fn build_recorder() -> anyhow::Result<PrometheusHandle> {
  PrometheusBuilder::new()
    .set_quantiles(QUANTILES)?
    .install_recorder()
    .context("could not install metrics recorder")
}