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    #[must_use] 
18    pub fn new(parser_name: &'static str) -> Self {
19        Self {
20            health: Cell::new(ParserHealth::new()),
21            parser_name,
22            threshold_warned: Cell::new(false),
23        }
24    }
25
26    /// Record that an event was parsed successfully
27    pub fn record_parsed(&self) {
28        let mut h = self.health.get();
29        h.record_parsed();
30        self.health.set(h);
31    }
32
33    /// Record that an event was ignored
34    pub fn record_ignored(&self) {
35        let mut h = self.health.get();
36        h.record_ignored();
37        self.health.set(h);
38    }
39
40    /// Record an unknown event type (valid JSON but unhandled)
41    pub fn record_unknown_event(&self) {
42        let mut h = self.health.get();
43        h.record_unknown_event();
44        self.health.set(h);
45    }
46
47    /// Record a parse error (malformed JSON)
48    pub fn record_parse_error(&self) {
49        let mut h = self.health.get();
50        h.record_parse_error();
51        self.health.set(h);
52    }
53
54    /// Record a control event (state management with no user-facing output)
55    pub fn record_control_event(&self) {
56        let mut h = self.health.get();
57        h.record_control_event();
58        self.health.set(h);
59    }
60
61    /// Record a partial/delta event (streaming content displayed incrementally)
62    ///
63    /// Partial events represent streaming content that is shown to the user
64    /// in real-time as deltas. These are NOT errors and should not trigger
65    /// health warnings.
66    pub fn record_partial_event(&self) {
67        let mut h = self.health.get();
68        h.record_partial_event();
69        self.health.set(h);
70    }
71
72    /// Check if we should warn about parser health (only warn once)
73    pub fn check_and_warn(&self, colors: Colors) -> Option<String> {
74        if self.threshold_warned.get() {
75            return None;
76        }
77
78        let health = self.health.get();
79        let warning = health.warning(self.parser_name, colors);
80        if warning.is_some() {
81            self.threshold_warned.set(true);
82        }
83        warning
84    }
85}