1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
//! Module: ops::runtime::metrics::lifecycle
//!
//! Responsibility: record and snapshot low-cardinality runtime metrics for the lifecycle family.
//! Does not own: workflow decisions, persisted records, or endpoint DTOs.
//! Boundary: ops-layer metrics consumed by workflow metrics projection.
use std::{cell::RefCell, collections::BTreeMap};
pub use crate::domain::metrics::{
LifecycleMetricOutcome, LifecycleMetricPhase, LifecycleMetricRole, LifecycleMetricStage,
};
thread_local! {
static LIFECYCLE_METRICS: RefCell<BTreeMap<LifecycleMetricKey, u64>> =
const { RefCell::new(BTreeMap::new()) };
}
///
/// LifecycleMetricKey
///
/// Composite key for one low-cardinality lifecycle counter.
///
#[derive(Clone, Copy, Eq, Hash, Ord, PartialEq, PartialOrd)]
pub struct LifecycleMetricKey {
pub phase: LifecycleMetricPhase,
pub role: LifecycleMetricRole,
pub stage: LifecycleMetricStage,
pub outcome: LifecycleMetricOutcome,
}
///
/// LifecycleMetrics
///
/// Operations-layer recorder for lifecycle runtime counters.
///
pub struct LifecycleMetrics;
impl LifecycleMetrics {
/// Read a deterministic bounded prefix for optional public sampling.
pub(crate) fn bounded_snapshot(limit: usize) -> Vec<(LifecycleMetricKey, u64)> {
LIFECYCLE_METRICS.with_borrow(|counts| {
counts
.iter()
.take(limit)
.map(|(key, count)| (*key, *count))
.collect()
})
}
/// Record one lifecycle stage event.
pub fn record(
phase: LifecycleMetricPhase,
role: LifecycleMetricRole,
stage: LifecycleMetricStage,
outcome: LifecycleMetricOutcome,
) {
LIFECYCLE_METRICS.with_borrow_mut(|counts| {
let key = LifecycleMetricKey {
phase,
role,
stage,
outcome,
};
let entry = counts.entry(key).or_insert(0);
*entry = entry.saturating_add(1);
});
}
/// Snapshot the current lifecycle metric table as stable rows.
#[must_use]
pub fn snapshot() -> Vec<(LifecycleMetricKey, u64)> {
LIFECYCLE_METRICS
.with_borrow(std::clone::Clone::clone)
.into_iter()
.collect()
}
/// Test-only helper: clear all lifecycle metrics.
#[cfg(test)]
pub fn reset() {
LIFECYCLE_METRICS.with_borrow_mut(BTreeMap::clear);
}
}