agent_io/
observability.rs1use tracing::{Span, info_span};
21use tracing_subscriber::EnvFilter;
22
23#[derive(Debug, Clone, Copy)]
25pub enum SpanType {
26 Default,
27 Llm,
28 Tool,
29}
30
31impl SpanType {
32 pub fn as_str(&self) -> &'static str {
33 match self {
34 SpanType::Default => "DEFAULT",
35 SpanType::Llm => "LLM",
36 SpanType::Tool => "TOOL",
37 }
38 }
39}
40
41pub trait SpanExt {
43 fn set_output(&self, output: &str);
45
46 fn set_error(&self, error: &str);
48}
49
50impl SpanExt for Span {
51 fn set_output(&self, output: &str) {
52 self.record("output", output);
53 }
54
55 fn set_error(&self, error: &str) {
56 self.record("error", true);
57 self.record("error.message", error);
58 }
59}
60
61pub fn is_tracing_enabled() -> bool {
63 tracing::dispatcher::has_been_set()
64}
65
66pub fn get_observability_status() -> ObservabilityStatus {
68 ObservabilityStatus {
69 tracing_enabled: is_tracing_enabled(),
70 }
71}
72
73#[derive(Debug, Clone)]
75pub struct ObservabilityStatus {
76 pub tracing_enabled: bool,
77}
78
79#[macro_export]
91macro_rules! observe {
92 (name = $name:expr, $item:item) => {
93 #[tracing::instrument(skip_all, name = $name)]
94 $item
95 };
96 ($item:item) => {
97 #[tracing::instrument(skip_all)]
98 $item
99 };
100}
101
102#[macro_export]
104macro_rules! observe_debug {
105 (name = $name:expr, $item:item) => {
106 #[cfg(debug_assertions)]
107 #[tracing::instrument(skip_all, name = $name)]
108 $item
109 #[cfg(not(debug_assertions))]
110 $item
111 };
112 ($item:item) => {
113 #[cfg(debug_assertions)]
114 #[tracing::instrument(skip_all)]
115 $item
116 #[cfg(not(debug_assertions))]
117 $item
118 };
119}
120
121pub fn init_default_subscriber() {
123 let _ = tracing_subscriber::fmt()
124 .with_env_filter(
125 EnvFilter::try_from_default_env().unwrap_or_else(|_| EnvFilter::new("info")),
126 )
127 .with_target(false)
128 .try_init();
129}
130
131pub fn llm_span(model: &str, provider: &str) -> Span {
133 info_span!(
134 target: "agent_io::llm",
135 "llm_invoke",
136 model = %model,
137 provider = %provider
138 )
139}
140
141pub fn tool_span(name: &str) -> Span {
143 info_span!(
144 target: "agent_io::tool",
145 "tool_execute",
146 tool_name = %name
147 )
148}
149
150pub fn agent_span(step: usize) -> Span {
152 info_span!(
153 target: "agent_io::agent",
154 "agent_step",
155 step = step
156 )
157}
158
159#[cfg(test)]
160mod tests {
161 use super::*;
162
163 #[test]
164 fn test_span_types() {
165 assert_eq!(SpanType::Default.as_str(), "DEFAULT");
166 assert_eq!(SpanType::Llm.as_str(), "LLM");
167 assert_eq!(SpanType::Tool.as_str(), "TOOL");
168 }
169}