use std::sync::Arc;
use prometheus_client::{
encoding::EncodeLabelSet,
metrics::{counter::Counter, family::Family, histogram::Histogram},
registry::Registry,
};
#[derive(Clone, Debug, Hash, PartialEq, Eq, EncodeLabelSet)]
struct PoolLabels {
pool: &'static str,
}
#[derive(Clone, Debug, Hash, PartialEq, Eq, EncodeLabelSet)]
struct OperationLabels {
operation: &'static str,
}
#[derive(Clone, Debug, Hash, PartialEq, Eq, EncodeLabelSet)]
struct RequestLabels {
request_kind: &'static str,
}
#[derive(Debug)]
pub struct AuthPrometheusMetrics {
lock_wait_seconds: Family<PoolLabels, Histogram, fn() -> Histogram>,
transaction_duration_seconds:
Family<OperationLabels, Histogram, fn() -> Histogram>,
blocking_queue_wait_seconds:
Family<OperationLabels, Histogram, fn() -> Histogram>,
blocking_task_duration_seconds:
Family<OperationLabels, Histogram, fn() -> Histogram>,
blocking_task_rejections_total: Family<OperationLabels, Counter>,
request_db_duration_seconds:
Family<RequestLabels, Histogram, fn() -> Histogram>,
request_db_ops_total: Family<RequestLabels, Counter>,
request_total: Family<RequestLabels, Counter>,
}
impl AuthPrometheusMetrics {
pub fn new() -> Self {
Self {
lock_wait_seconds: Family::new_with_constructor(|| {
Histogram::new(vec![
0.0005, 0.001, 0.005, 0.01, 0.025, 0.05, 0.1, 0.25, 0.5,
1.0, 2.0, 5.0,
])
}),
transaction_duration_seconds: Family::new_with_constructor(|| {
Histogram::new(vec![
0.001, 0.005, 0.01, 0.025, 0.05, 0.1, 0.25, 0.5, 1.0, 2.0,
5.0, 10.0,
])
}),
blocking_queue_wait_seconds: Family::new_with_constructor(|| {
Histogram::new(vec![
0.0005, 0.001, 0.005, 0.01, 0.025, 0.05, 0.1, 0.25, 0.5,
1.0, 2.0, 5.0,
])
}),
blocking_task_duration_seconds: Family::new_with_constructor(
|| {
Histogram::new(vec![
0.001, 0.005, 0.01, 0.025, 0.05, 0.1, 0.25, 0.5, 1.0,
2.0, 5.0, 10.0,
])
},
),
blocking_task_rejections_total: Family::default(),
request_db_duration_seconds: Family::new_with_constructor(|| {
Histogram::new(vec![
0.001, 0.005, 0.01, 0.025, 0.05, 0.1, 0.25, 0.5, 1.0, 2.0,
5.0, 10.0,
])
}),
request_db_ops_total: Family::default(),
request_total: Family::default(),
}
}
pub fn register_into(&self, registry: &mut Registry) {
registry.register(
"auth_db_lock_wait_seconds",
"Time spent waiting for an auth SQLite connection, labeled by pool.",
self.lock_wait_seconds.clone(),
);
registry.register(
"auth_db_transaction_seconds",
"Duration of auth SQLite transactions, labeled by operation.",
self.transaction_duration_seconds.clone(),
);
registry.register(
"auth_db_blocking_queue_wait_seconds",
"Time spent waiting for auth blocking execution capacity, labeled by operation.",
self.blocking_queue_wait_seconds.clone(),
);
registry.register(
"auth_db_blocking_task_seconds",
"Duration of auth blocking tasks dispatched through spawn_blocking, labeled by operation.",
self.blocking_task_duration_seconds.clone(),
);
registry.register(
"auth_db_blocking_rejections_total",
"Total auth blocking tasks rejected due to backpressure timeout, labeled by operation.",
self.blocking_task_rejections_total.clone(),
);
registry.register(
"auth_db_request_seconds",
"End-to-end database time consumed by auth-facing requests, labeled by request kind.",
self.request_db_duration_seconds.clone(),
);
registry.register(
"auth_db_request_ops_total",
"Total auth database operations attributed to requests, labeled by request kind.",
self.request_db_ops_total.clone(),
);
registry.register(
"auth_db_requests_total",
"Total auth requests that recorded database metrics, labeled by request kind.",
self.request_total.clone(),
);
}
pub fn observe_lock_wait(&self, pool: &'static str, seconds: f64) {
self.lock_wait_seconds
.get_or_create(&PoolLabels { pool })
.observe(seconds);
}
pub fn observe_transaction_duration(
&self,
operation: &'static str,
seconds: f64,
) {
self.transaction_duration_seconds
.get_or_create(&OperationLabels { operation })
.observe(seconds);
}
pub fn observe_blocking_queue_wait(
&self,
operation: &'static str,
seconds: f64,
) {
self.blocking_queue_wait_seconds
.get_or_create(&OperationLabels { operation })
.observe(seconds);
}
pub fn inc_blocking_task_rejection(&self, operation: &'static str) {
self.blocking_task_rejections_total
.get_or_create(&OperationLabels { operation })
.inc();
}
pub fn observe_blocking_task_duration(
&self,
operation: &'static str,
seconds: f64,
) {
self.blocking_task_duration_seconds
.get_or_create(&OperationLabels { operation })
.observe(seconds);
}
pub fn observe_request_metrics(
&self,
request_kind: &'static str,
db_operations: u64,
elapsed_seconds: f64,
) {
let labels = RequestLabels { request_kind };
self.request_total.get_or_create(&labels).inc();
self.request_db_ops_total
.get_or_create(&labels)
.inc_by(db_operations);
self.request_db_duration_seconds
.get_or_create(&labels)
.observe(elapsed_seconds);
}
}
pub type SharedAuthPrometheusMetrics = Arc<AuthPrometheusMetrics>;