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}