use oxi_sdk::ModelRegistry;
pub use oxi_sdk::{
AuditEntry, AuditFilter, AuditLog, CostBreakdown, CostSnapshot, CostTracker, CostTrackerConfig,
GlobalCostSnapshot, Span, SpanContext, SpanGuard, SpanId, SpanKind, SpanStatus, TokenUsage,
TraceId, Tracer,
};
use std::sync::Arc;
static TRACER: std::sync::OnceLock<Tracer> = std::sync::OnceLock::new();
static COST_TRACKER: std::sync::OnceLock<CostTracker> = std::sync::OnceLock::new();
static AUDIT_LOG: std::sync::OnceLock<AuditLog> = std::sync::OnceLock::new();
pub fn tracer() -> &'static Tracer {
TRACER.get_or_init(Tracer::new)
}
pub fn cost_tracker() -> &'static CostTracker {
COST_TRACKER.get_or_init(|| {
let registry = Arc::new(ModelRegistry::from_static());
CostTracker::new(registry, CostTrackerConfig::default())
})
}
pub fn audit_log() -> &'static AuditLog {
AUDIT_LOG.get_or_init(|| AuditLog::new(1024))
}
pub fn init() {
let _ = tracer();
let _ = cost_tracker();
let _ = audit_log();
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_tracer_smoke() {
let t = tracer();
let _guard = t.start("test-span", SpanKind::Agent);
drop(_guard);
}
#[test]
fn test_cost_tracker_smoke() {
let ct = cost_tracker();
let model = oxi_sdk::Model::new(
"test/model",
"Test",
oxi_sdk::Api::OpenAiCompletions,
"test",
"https://test.com",
);
ct.record(
"test-agent",
&model,
TokenUsage {
input: 100,
output: 50,
cache_read: 0,
cache_write: 0,
},
);
let snap = ct.snapshot("test-agent");
assert!(snap.is_some());
}
#[test]
fn test_audit_log_smoke() {
let al = audit_log();
al.log(AuditEntry::lifecycle("test-agent".into(), "started".into()));
let entries = al.query(AuditFilter {
agent_id: Some("test-agent".to_string()),
entry_type: None,
after_ms: None,
});
assert!(!entries.is_empty());
}
#[test]
fn test_init_idempotent() {
init();
init(); }
}