Skip to main content

asjeeves_telemetry/
database_metrics.rs

1use std::fmt::Display;
2use std::sync::{Arc, OnceLock};
3use std::time::Instant;
4
5#[cfg(feature = "bb8")]
6use metrics::gauge;
7use metrics::histogram;
8
9static DB_CONFIG: OnceLock<DbConfig> = OnceLock::new();
10
11pub fn db_metrics_setup(name: impl Into<Arc<str>>, system: impl Into<Arc<str>>) {
12    let name: Arc<str> = name.into();
13    let system: Arc<str> = system.into();
14
15    let config = DbConfig { name, system };
16
17    let _ = DB_CONFIG.set(config);
18}
19
20pub async fn time_async_query<Closure, Fut, RetVal>(
21    query_name: impl Display,
22    query: Closure,
23) -> RetVal
24where
25    Closure: FnOnce() -> Fut,
26    Fut: Future<Output = RetVal>,
27{
28    let timer = Instant::now();
29
30    let result = query().await;
31
32    let system_name: &str = match DB_CONFIG.get() {
33        Some(config) => &config.system,
34        None => "",
35    };
36
37    let histogram = histogram!(
38        description: "Query execution time",
39        unit: metrics::Unit::Seconds,
40        "db.client.operation.duration",
41        "db.query.summary" => query_name.to_string(),
42        "db.system.name" => system_name
43    );
44
45    histogram.record(timer.elapsed().as_secs_f64());
46
47    result
48}
49
50#[cfg(feature = "bb8")]
51pub fn track_database_metrics(dbstate: bb8::State, pool_size: u32) {
52    let Some(config) = DB_CONFIG.get() else {
53        return;
54    };
55
56    let stats: bb8::Statistics = dbstate.statistics;
57
58    let active_connections: u32 = dbstate.connections - dbstate.idle_connections;
59
60    let pool_name: &str = &config.name;
61
62    let conn_count = gauge!(
63        description: "Active Connections",
64        unit: metrics::Unit::Count,
65        "db.client.connection.count",
66        "db.client.connetion.pool.name" => pool_name,
67        "db.client.connection.state" => "used",
68    );
69
70    let idle_count = gauge!(
71        description: "Idle Connections",
72        unit: metrics::Unit::Count,
73        "db.client.connection.count",
74        "db.client.connetion.pool.name" => pool_name,
75        "db.client.connection.state" => "idle",
76    );
77
78    let max_conn = gauge!(
79        description: "Pool Size",
80        unit: metrics::Unit::Count,
81        "db.client.connection.idle.max",
82        "db.client.connection.pool.name" => pool_name
83    );
84
85    let conn_get = gauge!(
86        description: "Connection aquisition duration",
87        unit: metrics::Unit::Seconds,
88        "db.client.connection.create_time",
89        "db.client.connection.pool.name" => pool_name
90    );
91
92    conn_count.set(active_connections as f64);
93    idle_count.set(dbstate.idle_connections as f64);
94    max_conn.set(pool_size as f64);
95    conn_get.set(stats.get_wait_time.as_secs_f64());
96}
97
98#[allow(dead_code)]
99struct DbConfig {
100    name: Arc<str>,
101    system: Arc<str>,
102}