Skip to main content

maple_runtime/telemetry/
mod.rs

1//! Telemetry and observability for MAPLE Resonance Runtime
2
3use crate::config::TelemetryConfig;
4use crate::runtime_core::ResonatorHandle;
5use std::sync::RwLock;
6
7/// Runtime telemetry system
8///
9/// Uses `RwLock` for thread-safe interior mutability, enabling
10/// the runtime to be shared across async tasks (Send + Sync).
11pub struct RuntimeTelemetry {
12    config: TelemetryConfig,
13    metrics: RwLock<MetricsCollector>,
14}
15
16impl RuntimeTelemetry {
17    pub fn new(config: &TelemetryConfig) -> Self {
18        Self {
19            config: config.clone(),
20            metrics: RwLock::new(MetricsCollector::new()),
21        }
22    }
23
24    /// Record Resonator registration
25    pub fn resonator_registered(&self, handle: &ResonatorHandle) {
26        if !self.config.metrics_enabled {
27            return;
28        }
29
30        tracing::info!("Resonator registered: {}", handle.id);
31        self.metrics
32            .write()
33            .unwrap()
34            .increment("resonator_registrations");
35    }
36
37    /// Record Resonator resume
38    pub fn resonator_resumed(&self, handle: &ResonatorHandle) {
39        if !self.config.metrics_enabled {
40            return;
41        }
42
43        tracing::info!("Resonator resumed: {}", handle.id);
44        self.metrics.write().unwrap().increment("resonator_resumes");
45    }
46
47    /// Flush telemetry data
48    pub async fn flush(&self) {
49        if !self.config.enabled {
50            return;
51        }
52
53        tracing::debug!("Flushing telemetry");
54        self.metrics.read().unwrap().flush();
55    }
56
57    /// Record coupling establishment
58    pub fn coupling_established(&self, source: &str, target: &str, strength: f64) {
59        if !self.config.metrics_enabled {
60            return;
61        }
62
63        tracing::debug!(
64            "Coupling established: {} -> {} (strength: {})",
65            source,
66            target,
67            strength
68        );
69        self.metrics
70            .write()
71            .unwrap()
72            .increment("coupling_establishments");
73    }
74
75    /// Record attention allocation
76    pub fn attention_allocated(&self, resonator: &str, amount: u64) {
77        if !self.config.detailed_metrics {
78            return;
79        }
80
81        tracing::trace!("Attention allocated: {} (amount: {})", resonator, amount);
82        self.metrics
83            .write()
84            .unwrap()
85            .record_gauge("attention_allocated", amount as f64);
86    }
87
88    /// Record invariant violation
89    pub fn invariant_violated(&self, invariant: &str) {
90        if !self.config.metrics_enabled {
91            return;
92        }
93
94        tracing::error!("Invariant violated: {}", invariant);
95        self.metrics
96            .write()
97            .unwrap()
98            .increment("invariant_violations");
99    }
100}
101
102/// Metrics collector
103struct MetricsCollector {
104    counters: std::collections::HashMap<String, u64>,
105    gauges: std::collections::HashMap<String, f64>,
106}
107
108impl MetricsCollector {
109    fn new() -> Self {
110        Self {
111            counters: std::collections::HashMap::new(),
112            gauges: std::collections::HashMap::new(),
113        }
114    }
115
116    fn increment(&mut self, metric: &str) {
117        *self.counters.entry(metric.to_string()).or_insert(0) += 1;
118    }
119
120    fn record_gauge(&mut self, metric: &str, value: f64) {
121        self.gauges.insert(metric.to_string(), value);
122    }
123
124    fn flush(&self) {
125        // In real implementation, would flush to metrics backend
126        tracing::trace!("Metrics flushed (placeholder)");
127    }
128}