rrag_graph/
observability.rs

1//! # Observability
2//!
3//! Monitoring and observability for graph execution.
4
5use crate::core::{ExecutionContext, NodeId};
6// Future use for observability features
7use async_trait::async_trait;
8use std::time::Duration;
9
10#[cfg(feature = "serde")]
11use serde::{Deserialize, Serialize};
12
13/// Graph execution observer
14#[async_trait]
15pub trait GraphObserver: Send + Sync {
16    /// Called when graph execution starts
17    async fn on_execution_start(&self, graph_id: &str, context: &ExecutionContext);
18
19    /// Called when graph execution ends
20    async fn on_execution_end(&self, graph_id: &str, success: bool, duration: Duration);
21
22    /// Called when node execution starts
23    async fn on_node_start(&self, node_id: &NodeId, context: &ExecutionContext);
24
25    /// Called when node execution ends
26    async fn on_node_end(&self, node_id: &NodeId, success: bool, duration: Duration);
27
28    /// Called when state changes
29    async fn on_state_change(&self, key: &str, old_value: Option<&str>, new_value: &str);
30}
31
32/// Basic logging observer
33pub struct LoggingObserver;
34
35#[async_trait]
36impl GraphObserver for LoggingObserver {
37    async fn on_execution_start(&self, graph_id: &str, _context: &ExecutionContext) {
38        #[cfg(feature = "observability")]
39        tracing::info!("Graph execution started: {}", graph_id);
40        #[cfg(not(feature = "observability"))]
41        {
42            let _ = (graph_id, _context);
43            eprintln!("Graph execution started: {}", graph_id);
44        }
45    }
46
47    async fn on_execution_end(&self, graph_id: &str, success: bool, duration: Duration) {
48        #[cfg(feature = "observability")]
49        tracing::info!(
50            "Graph execution ended: {} (success: {}, duration: {:?})",
51            graph_id,
52            success,
53            duration
54        );
55        #[cfg(not(feature = "observability"))]
56        eprintln!(
57            "Graph execution ended: {} (success: {}, duration: {:?})",
58            graph_id, success, duration
59        );
60    }
61
62    async fn on_node_start(&self, node_id: &NodeId, _context: &ExecutionContext) {
63        #[cfg(feature = "observability")]
64        tracing::debug!("Node execution started: {}", node_id.as_str());
65        #[cfg(not(feature = "observability"))]
66        {
67            let _ = _context;
68            eprintln!("Node execution started: {}", node_id.as_str());
69        }
70    }
71
72    async fn on_node_end(&self, node_id: &NodeId, success: bool, duration: Duration) {
73        #[cfg(feature = "observability")]
74        tracing::debug!(
75            "Node execution ended: {} (success: {}, duration: {:?})",
76            node_id.as_str(),
77            success,
78            duration
79        );
80        #[cfg(not(feature = "observability"))]
81        eprintln!(
82            "Node execution ended: {} (success: {}, duration: {:?})",
83            node_id.as_str(),
84            success,
85            duration
86        );
87    }
88
89    async fn on_state_change(&self, key: &str, old_value: Option<&str>, new_value: &str) {
90        #[cfg(feature = "observability")]
91        tracing::trace!(
92            "State change: {} = {} (was: {:?})",
93            key,
94            new_value,
95            old_value
96        );
97        #[cfg(not(feature = "observability"))]
98        eprintln!(
99            "State change: {} = {} (was: {:?})",
100            key, new_value, old_value
101        );
102    }
103}
104
105/// Execution metrics
106#[derive(Debug, Clone, Default)]
107#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
108pub struct ExecutionMetrics {
109    pub nodes_executed: usize,
110    pub total_duration: Duration,
111    pub node_metrics: Vec<NodeMetrics>,
112}
113
114/// Node-specific metrics
115#[derive(Debug, Clone)]
116#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
117pub struct NodeMetrics {
118    pub node_id: String,
119    pub execution_count: usize,
120    pub total_duration: Duration,
121    pub average_duration: Duration,
122    pub success_rate: f32,
123}
124
125/// Observability configuration
126#[derive(Debug, Clone)]
127#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
128pub struct ObservabilityConfig {
129    pub enable_logging: bool,
130    pub enable_metrics: bool,
131    pub enable_tracing: bool,
132    pub log_level: String,
133}