Skip to main content

ralph_workflow/json_parser/health/
monitor.rs

1// Health monitor implementation.
2//
3// Contains the HealthMonitor struct for tracking parser health.
4
5/// A wrapper that monitors parser health and provides graceful degradation
6///
7/// This wraps any parser function to track how many events are being ignored
8/// and emit warnings when the parser seems to be misconfigured.
9pub struct HealthMonitor {
10    health: Cell<ParserHealth>,
11    parser_name: &'static str,
12    threshold_warned: Cell<bool>,
13}
14
15impl HealthMonitor {
16    /// Create a new health monitor for a parser
17    pub fn new(parser_name: &'static str) -> Self {
18        Self {
19            health: Cell::new(ParserHealth::new()),
20            parser_name,
21            threshold_warned: Cell::new(false),
22        }
23    }
24
25    /// Record that an event was parsed successfully
26    pub fn record_parsed(&self) {
27        let mut h = self.health.get();
28        h.record_parsed();
29        self.health.set(h);
30    }
31
32    /// Record that an event was ignored
33    pub fn record_ignored(&self) {
34        let mut h = self.health.get();
35        h.record_ignored();
36        self.health.set(h);
37    }
38
39    /// Record an unknown event type (valid JSON but unhandled)
40    pub fn record_unknown_event(&self) {
41        let mut h = self.health.get();
42        h.record_unknown_event();
43        self.health.set(h);
44    }
45
46    /// Record a parse error (malformed JSON)
47    pub fn record_parse_error(&self) {
48        let mut h = self.health.get();
49        h.record_parse_error();
50        self.health.set(h);
51    }
52
53    /// Record a control event (state management with no user-facing output)
54    pub fn record_control_event(&self) {
55        let mut h = self.health.get();
56        h.record_control_event();
57        self.health.set(h);
58    }
59
60    /// Record a partial/delta event (streaming content displayed incrementally)
61    ///
62    /// Partial events represent streaming content that is shown to the user
63    /// in real-time as deltas. These are NOT errors and should not trigger
64    /// health warnings.
65    pub fn record_partial_event(&self) {
66        let mut h = self.health.get();
67        h.record_partial_event();
68        self.health.set(h);
69    }
70
71    /// Check if we should warn about parser health (only warn once)
72    pub fn check_and_warn(&self, colors: Colors) -> Option<String> {
73        if self.threshold_warned.get() {
74            return None;
75        }
76
77        let health = self.health.get();
78        let warning = health.warning(self.parser_name, colors);
79        if warning.is_some() {
80            self.threshold_warned.set(true);
81        }
82        warning
83    }
84}