Skip to main content

auth_framework/monitoring/
collectors.rs

1//! Metrics collectors for various authentication framework components
2//!
3//! This module provides atomic counters that can be incremented from anywhere in the
4//! framework, and collector structs that read from those counters to produce metrics.
5
6use std::sync::atomic::{AtomicU64, Ordering};
7use std::time::Instant;
8
9// ── Global atomic counters ──────────────────────────────────────────────────
10
11/// Total authentication requests processed.
12pub static AUTH_TOTAL_REQUESTS: AtomicU64 = AtomicU64::new(0);
13/// Successful authentication requests.
14pub static AUTH_SUCCESSFUL_REQUESTS: AtomicU64 = AtomicU64::new(0);
15/// Failed authentication requests.
16pub static AUTH_FAILED_REQUESTS: AtomicU64 = AtomicU64::new(0);
17
18/// Currently active sessions.
19pub static SESSION_ACTIVE_COUNT: AtomicU64 = AtomicU64::new(0);
20/// Sessions that have expired.
21pub static SESSION_EXPIRED_COUNT: AtomicU64 = AtomicU64::new(0);
22/// Cumulative sessions created (used to derive creation rate).
23pub static SESSION_CREATED_TOTAL: AtomicU64 = AtomicU64::new(0);
24
25/// Tokens created.
26pub static TOKEN_CREATION_COUNT: AtomicU64 = AtomicU64::new(0);
27/// Tokens validated.
28pub static TOKEN_VALIDATION_COUNT: AtomicU64 = AtomicU64::new(0);
29/// Tokens expired.
30pub static TOKEN_EXPIRATION_COUNT: AtomicU64 = AtomicU64::new(0);
31
32// ── Collector structs ───────────────────────────────────────────────────────
33
34/// Collector for authentication metrics.
35pub struct AuthMetricsCollector;
36
37/// Collector for session metrics.
38///
39/// Tracks the last snapshot of `SESSION_CREATED_TOTAL` and the timestamp so
40/// that `session_creation_rate` can be reported as creations-per-second.
41pub struct SessionMetricsCollector {
42    last_created_snapshot: AtomicU64,
43    last_snapshot_time: std::sync::Mutex<Instant>,
44}
45
46/// Collector for token metrics.
47pub struct TokenMetricsCollector;
48
49impl AuthMetricsCollector {
50    /// Collect authentication-related metrics from the global atomic counters.
51    pub async fn collect(&self) -> std::collections::HashMap<String, f64> {
52        let mut metrics = std::collections::HashMap::new();
53        metrics.insert(
54            "auth_total_requests".to_string(),
55            AUTH_TOTAL_REQUESTS.load(Ordering::Relaxed) as f64,
56        );
57        metrics.insert(
58            "auth_successful_requests".to_string(),
59            AUTH_SUCCESSFUL_REQUESTS.load(Ordering::Relaxed) as f64,
60        );
61        metrics.insert(
62            "auth_failed_requests".to_string(),
63            AUTH_FAILED_REQUESTS.load(Ordering::Relaxed) as f64,
64        );
65        metrics
66    }
67}
68
69impl Default for SessionMetricsCollector {
70    fn default() -> Self {
71        Self {
72            last_created_snapshot: AtomicU64::new(0),
73            last_snapshot_time: std::sync::Mutex::new(Instant::now()),
74        }
75    }
76}
77
78impl SessionMetricsCollector {
79    /// Create a new session metrics collector.
80    pub fn new() -> Self {
81        Self::default()
82    }
83
84    /// Collect session-related metrics from the global atomic counters.
85    ///
86    /// `session_creation_rate` is computed as the delta in
87    /// `SESSION_CREATED_TOTAL` divided by the elapsed seconds since the
88    /// previous call.
89    pub async fn collect(&self) -> std::collections::HashMap<String, f64> {
90        let mut metrics = std::collections::HashMap::new();
91        metrics.insert(
92            "session_active_count".to_string(),
93            SESSION_ACTIVE_COUNT.load(Ordering::Relaxed) as f64,
94        );
95        metrics.insert(
96            "session_expired_count".to_string(),
97            SESSION_EXPIRED_COUNT.load(Ordering::Relaxed) as f64,
98        );
99
100        // Compute creation rate from delta.
101        let current_total = SESSION_CREATED_TOTAL.load(Ordering::Relaxed);
102        let previous = self
103            .last_created_snapshot
104            .swap(current_total, Ordering::Relaxed);
105        let delta = current_total.saturating_sub(previous);
106
107        let rate = {
108            let mut last_time = match self.last_snapshot_time.lock() {
109                Ok(guard) => guard,
110                Err(poisoned) => poisoned.into_inner(),
111            };
112            let elapsed = last_time.elapsed().as_secs_f64();
113            *last_time = Instant::now();
114            if elapsed > 0.0 {
115                delta as f64 / elapsed
116            } else {
117                0.0
118            }
119        };
120        metrics.insert("session_creation_rate".to_string(), rate);
121
122        metrics
123    }
124}
125
126impl TokenMetricsCollector {
127    /// Collect token-related metrics from the global atomic counters.
128    pub async fn collect(&self) -> std::collections::HashMap<String, f64> {
129        let mut metrics = std::collections::HashMap::new();
130        metrics.insert(
131            "token_creation_count".to_string(),
132            TOKEN_CREATION_COUNT.load(Ordering::Relaxed) as f64,
133        );
134        metrics.insert(
135            "token_validation_count".to_string(),
136            TOKEN_VALIDATION_COUNT.load(Ordering::Relaxed) as f64,
137        );
138        metrics.insert(
139            "token_expiration_count".to_string(),
140            TOKEN_EXPIRATION_COUNT.load(Ordering::Relaxed) as f64,
141        );
142        metrics
143    }
144}