Skip to main content

molo_core/
observability.rs

1//! Lightweight observability record types.
2//!
3//! These types are data shapes, not a telemetry backend. They let framework
4//! events expose redacted, serializable summaries for logs, devtools, tests,
5//! and metrics adapters while keeping raw prompt/model/tool content out of
6//! default records.
7
8use serde::{Deserialize, Serialize};
9use std::time::SystemTime;
10
11/// Current schema version for [`AgentEventRecord`].
12pub const AGENT_EVENT_RECORD_SCHEMA_VERSION: u16 = 1;
13
14/// A redaction that was applied to an exported record or text field.
15#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
16pub struct RedactionRecord {
17    /// Field where redaction occurred.
18    pub field: String,
19    /// Human-readable redaction reason.
20    pub reason: String,
21}
22
23/// Severity for a serializable agent event record.
24#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
25#[non_exhaustive]
26pub enum EventSeverity {
27    /// Very detailed diagnostic event.
28    Trace,
29    /// Debug diagnostic event.
30    Debug,
31    /// Informational lifecycle event.
32    Info,
33    /// Warning event.
34    Warn,
35    /// Error event.
36    Error,
37}
38
39/// Serializable, redacted event record for out-of-process observers.
40///
41/// `AgentEventRecord` complements the low-cost `Arc<dyn AgentEvent>` channel:
42/// framework-owned events can expose sanitized JSON summaries, while custom
43/// events may keep returning `None` from `AgentEvent::to_record`.
44#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
45pub struct AgentEventRecord {
46    /// Record schema version. Starts at 1; payload additions should be
47    /// backward-compatible.
48    pub schema_version: u16,
49    /// Run id when the event has one.
50    pub run_id: Option<String>,
51    /// Optional producer-local sequence number.
52    pub sequence: Option<u64>,
53    /// Record creation timestamp.
54    pub timestamp: SystemTime,
55    /// Event name.
56    pub name: String,
57    /// Event severity.
58    pub severity: EventSeverity,
59    /// Redacted, event-specific summary payload.
60    pub payload: serde_json::Value,
61    /// Redactions or omitted raw-content fields.
62    pub redactions: Vec<RedactionRecord>,
63}
64
65impl AgentEventRecord {
66    /// Constructs a record with the current schema version and timestamp.
67    pub fn new(
68        name: impl Into<String>,
69        severity: EventSeverity,
70        payload: serde_json::Value,
71    ) -> Self {
72        Self {
73            schema_version: AGENT_EVENT_RECORD_SCHEMA_VERSION,
74            run_id: None,
75            sequence: None,
76            timestamp: SystemTime::now(),
77            name: name.into(),
78            severity,
79            payload,
80            redactions: Vec::new(),
81        }
82    }
83
84    /// Sets the run id.
85    pub fn with_run_id(mut self, run_id: impl Into<String>) -> Self {
86        self.run_id = Some(run_id.into());
87        self
88    }
89
90    /// Sets the optional sequence number.
91    pub fn with_sequence(mut self, sequence: u64) -> Self {
92        self.sequence = Some(sequence);
93        self
94    }
95
96    /// Sets redaction records.
97    pub fn with_redactions(mut self, redactions: Vec<RedactionRecord>) -> Self {
98        self.redactions = redactions;
99        self
100    }
101}