use tracing::{Span, info_span};
use tracing_subscriber::EnvFilter;
#[derive(Debug, Clone, Copy)]
pub enum SpanType {
Default,
Llm,
Tool,
}
impl SpanType {
pub fn as_str(&self) -> &'static str {
match self {
SpanType::Default => "DEFAULT",
SpanType::Llm => "LLM",
SpanType::Tool => "TOOL",
}
}
}
pub trait SpanExt {
fn set_output(&self, output: &str);
fn set_error(&self, error: &str);
}
impl SpanExt for Span {
fn set_output(&self, output: &str) {
self.record("output", output);
}
fn set_error(&self, error: &str) {
self.record("error", true);
self.record("error.message", error);
}
}
pub fn is_tracing_enabled() -> bool {
tracing::dispatcher::has_been_set()
}
pub fn get_observability_status() -> ObservabilityStatus {
ObservabilityStatus {
tracing_enabled: is_tracing_enabled(),
}
}
#[derive(Debug, Clone)]
pub struct ObservabilityStatus {
pub tracing_enabled: bool,
}
#[macro_export]
macro_rules! observe {
(name = $name:expr, $item:item) => {
#[tracing::instrument(skip_all, name = $name)]
$item
};
($item:item) => {
#[tracing::instrument(skip_all)]
$item
};
}
#[macro_export]
macro_rules! observe_debug {
(name = $name:expr, $item:item) => {
#[cfg(debug_assertions)]
#[tracing::instrument(skip_all, name = $name)]
$item
#[cfg(not(debug_assertions))]
$item
};
($item:item) => {
#[cfg(debug_assertions)]
#[tracing::instrument(skip_all)]
$item
#[cfg(not(debug_assertions))]
$item
};
}
pub fn init_default_subscriber() {
let _ = tracing_subscriber::fmt()
.with_env_filter(
EnvFilter::try_from_default_env().unwrap_or_else(|_| EnvFilter::new("info")),
)
.with_target(false)
.try_init();
}
pub fn llm_span(model: &str, provider: &str) -> Span {
info_span!(
target: "agent_io::llm",
"llm_invoke",
model = %model,
provider = %provider
)
}
pub fn tool_span(name: &str) -> Span {
info_span!(
target: "agent_io::tool",
"tool_execute",
tool_name = %name
)
}
pub fn agent_span(step: usize) -> Span {
info_span!(
target: "agent_io::agent",
"agent_step",
step = step
)
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_span_types() {
assert_eq!(SpanType::Default.as_str(), "DEFAULT");
assert_eq!(SpanType::Llm.as_str(), "LLM");
assert_eq!(SpanType::Tool.as_str(), "TOOL");
}
}