Skip to main content

appcore_ops/
metrics.rs

1// =============================================================================
2//        #######
3//     ###       ###     F: metrics.rs
4//    ##   ## ##   ##    P: AppCore-Runtime
5//         ## ##
6//                       C: 2026/06/02 17:10:40 by dnettoRaw
7//    ##   ## ##   ##    U: 2026/07/23 23:50:45 by dnettoRaw
8//      ###########      S: 1.0.1-rc.8
9// =============================================================================
10
11//! Minimal in-memory counters for local runtime diagnostics.
12
13use parking_lot::Mutex;
14use serde::{Deserialize, Serialize};
15use std::collections::BTreeMap;
16
17/// Named monotonic counter snapshot.
18#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
19pub struct MetricCounter {
20    /// Stable metric name.
21    pub name: String,
22    /// Current counter value.
23    pub value: u64,
24}
25
26/// Process-local monotonic counter registry.
27#[derive(Debug, Default)]
28pub struct InMemoryMetrics {
29    counters: Mutex<BTreeMap<String, u64>>,
30}
31
32impl InMemoryMetrics {
33    /// Creates an empty counter registry.
34    pub fn new() -> Self {
35        Self::default()
36    }
37
38    /// Saturating-increments a named counter and returns its new value.
39    pub fn increment(&self, name: &str) -> u64 {
40        let mut counters = self.counters.lock();
41        let value = counters.entry(name.to_string()).or_insert(0);
42        *value = value.saturating_add(1);
43        *value
44    }
45
46    /// Returns counters ordered by name.
47    pub fn snapshot(&self) -> Vec<MetricCounter> {
48        let counters = self.counters.lock();
49        counters
50            .iter()
51            .map(|(name, value)| MetricCounter {
52                name: name.clone(),
53                value: *value,
54            })
55            .collect()
56    }
57}
58
59#[cfg(test)]
60#[path = "metrics_tests.rs"]
61mod tests;