use parking_lot::Mutex;
use std::collections::HashMap;
use std::sync::atomic::{AtomicU64, Ordering};
#[derive(Debug, Clone, Default, PartialEq)]
pub struct MetricsSnapshot {
pub tasks_started: u64,
pub tasks_completed: u64,
pub tasks_failed: u64,
pub tasks_dead_lettered: u64,
pub retries: u64,
pub tasks_skipped: u64,
pub durations_ms: HashMap<String, u64>,
}
impl MetricsSnapshot {
pub fn success_rate(&self) -> f64 {
let finished = self.tasks_completed + self.tasks_failed + self.tasks_dead_lettered;
if finished == 0 {
return 1.0;
}
self.tasks_completed as f64 / finished as f64
}
pub fn mean_duration_ms(&self) -> Option<f64> {
if self.durations_ms.is_empty() {
return None;
}
let sum: u64 = self.durations_ms.values().sum();
Some(sum as f64 / self.durations_ms.len() as f64)
}
}
#[derive(Default)]
pub struct MetricsCollector {
started: AtomicU64,
completed: AtomicU64,
failed: AtomicU64,
dead_lettered: AtomicU64,
retries: AtomicU64,
skipped: AtomicU64,
durations: Mutex<HashMap<String, u64>>,
}
impl MetricsCollector {
pub fn new() -> Self {
Self::default()
}
pub fn task_started(&self) {
self.started.fetch_add(1, Ordering::Relaxed);
}
pub fn task_completed(&self, id: &str, duration_ms: u64) {
self.completed.fetch_add(1, Ordering::Relaxed);
self.durations.lock().insert(id.to_string(), duration_ms);
}
pub fn task_failed(&self) {
self.failed.fetch_add(1, Ordering::Relaxed);
}
pub fn task_dead_lettered(&self) {
self.dead_lettered.fetch_add(1, Ordering::Relaxed);
}
pub fn retry(&self) {
self.retries.fetch_add(1, Ordering::Relaxed);
}
pub fn task_skipped(&self) {
self.skipped.fetch_add(1, Ordering::Relaxed);
}
pub fn snapshot(&self) -> MetricsSnapshot {
MetricsSnapshot {
tasks_started: self.started.load(Ordering::Relaxed),
tasks_completed: self.completed.load(Ordering::Relaxed),
tasks_failed: self.failed.load(Ordering::Relaxed),
tasks_dead_lettered: self.dead_lettered.load(Ordering::Relaxed),
retries: self.retries.load(Ordering::Relaxed),
tasks_skipped: self.skipped.load(Ordering::Relaxed),
durations_ms: self.durations.lock().clone(),
}
}
}