Skip to main content

ralph_workflow/monitoring/memory_metrics/
backends.rs

1// Telemetry backend trait and built-in implementations.
2
3use std::rc::Rc;
4
5use super::snapshot::MemorySnapshot;
6
7/// Pluggable backend for telemetry integration.
8///
9/// Implement this trait to integrate with external monitoring systems
10/// (Prometheus, `DataDog`, `CloudWatch`, etc.)
11pub trait TelemetryBackend {
12    /// Emit a memory snapshot to the telemetry system.
13    fn emit_snapshot(&self, snapshot: &MemorySnapshot);
14
15    /// Emit a warning when memory usage approaches threshold.
16    fn emit_warning(&self, message: &str);
17
18    /// Flush any buffered metrics.
19    fn flush(&self);
20}
21
22/// No-op telemetry backend for testing.
23#[derive(Debug, Default)]
24pub struct NoOpBackend;
25
26impl TelemetryBackend for NoOpBackend {
27    fn emit_snapshot(&self, _snapshot: &MemorySnapshot) {}
28    fn emit_warning(&self, _message: &str) {}
29    fn flush(&self) {}
30}
31
32/// Logging-based telemetry backend.
33///
34/// Routes metrics through the project's logger implementation.
35pub struct LoggingBackend {
36    warn_threshold_bytes: usize,
37    logger: Rc<dyn crate::logger::Loggable>,
38}
39
40impl LoggingBackend {
41    /// Create a logging backend that writes via the provided logger.
42    pub fn with_logger(
43        warn_threshold_bytes: usize,
44        logger: Rc<dyn crate::logger::Loggable>,
45    ) -> Self {
46        Self {
47            warn_threshold_bytes,
48            logger,
49        }
50    }
51}
52
53impl TelemetryBackend for LoggingBackend {
54    fn emit_snapshot(&self, snapshot: &MemorySnapshot) {
55        self.logger.info(&format!(
56            "[METRICS] iteration={} history_len={} heap_bytes={} checkpoint_count={}",
57            snapshot.iteration,
58            snapshot.execution_history_len,
59            snapshot.execution_history_heap_bytes,
60            snapshot.checkpoint_count
61        ));
62
63        if snapshot.execution_history_heap_bytes > self.warn_threshold_bytes {
64            self.emit_warning(&format!(
65                "Execution history heap size {} bytes exceeds warning threshold {} bytes",
66                snapshot.execution_history_heap_bytes, self.warn_threshold_bytes
67            ));
68        }
69    }
70
71    fn emit_warning(&self, message: &str) {
72        self.logger.warn(&format!("[METRICS WARNING] {message}"));
73    }
74
75    fn flush(&self) {
76        // Logging backend doesn't buffer
77    }
78}