pub trait AuthnMetrics: Send + Sync + 'static {
fn auth_attempt(&self) {}
fn auth_success(&self) {}
fn auth_failure(&self) {}
fn factor_attempt(&self) {}
fn factor_success(&self) {}
fn factor_failure(&self) {}
fn factor_counter_store_outage(&self) {}
fn audit_store_outage(&self) {}
fn audit_event_shed(&self) {}
fn account_locked(&self) {}
fn session_created(&self) {}
fn session_invalidated(&self) {}
fn session_binding_mismatch(&self) {}
fn rate_limit_allowed(&self) {}
fn rate_limit_rejected(&self) {}
fn authz_cache_hit(&self) {}
fn authz_cache_miss(&self) {}
fn authz_cache_eviction(&self) {}
fn authz_cache_invalidation(&self) {}
fn authz_cache_hits(&self, count: u64) {
for _ in 0..count {
self.authz_cache_hit();
}
}
fn authz_cache_misses(&self, count: u64) {
for _ in 0..count {
self.authz_cache_miss();
}
}
fn authz_cache_evictions(&self, count: u64) {
for _ in 0..count {
self.authz_cache_eviction();
}
}
fn authz_cache_invalidations(&self, count: u64) {
for _ in 0..count {
self.authz_cache_invalidation();
}
}
}
#[derive(Debug, Clone, Default)]
pub struct NoopMetrics;
impl AuthnMetrics for NoopMetrics {}
#[cfg(test)]
mod tests {
use super::*;
use std::sync::atomic::{AtomicU32, Ordering};
struct CountingMetrics {
attempts: AtomicU32,
successes: AtomicU32,
failures: AtomicU32,
}
impl CountingMetrics {
fn new() -> Self {
Self {
attempts: AtomicU32::new(0),
successes: AtomicU32::new(0),
failures: AtomicU32::new(0),
}
}
}
impl AuthnMetrics for CountingMetrics {
fn auth_attempt(&self) {
self.attempts.fetch_add(1, Ordering::Relaxed);
}
fn auth_success(&self) {
self.successes.fetch_add(1, Ordering::Relaxed);
}
fn auth_failure(&self) {
self.failures.fetch_add(1, Ordering::Relaxed);
}
}
#[test]
fn noop_metrics_compiles() {
let m = NoopMetrics;
m.auth_attempt();
m.auth_success();
m.auth_failure();
m.factor_attempt();
m.session_created();
m.rate_limit_allowed();
m.rate_limit_rejected();
}
#[test]
fn counting_metrics_increments() {
let m = CountingMetrics::new();
m.auth_attempt();
m.auth_attempt();
m.auth_success();
m.auth_failure();
assert_eq!(m.attempts.load(Ordering::Relaxed), 2);
assert_eq!(m.successes.load(Ordering::Relaxed), 1);
assert_eq!(m.failures.load(Ordering::Relaxed), 1);
}
}