use anyhow::Result;
use opentelemetry::{global, trace::TracerProvider as _, KeyValue};
use opentelemetry_otlp::WithExportConfig;
use opentelemetry_sdk::{runtime::Tokio, trace::TracerProvider, Resource};
use tracing_subscriber::{layer::SubscriberExt, util::SubscriberInitExt, EnvFilter};
pub struct TelemetryGuard {
tracer_provider: Option<TracerProvider>,
}
impl Drop for TelemetryGuard {
fn drop(&mut self) {
if let Some(provider) = self.tracer_provider.take() {
let _ = provider.shutdown();
}
}
}
pub fn init() -> Result<TelemetryGuard> {
let env_filter = EnvFilter::try_from_default_env()
.unwrap_or_else(|_| EnvFilter::new("info,warmplane=debug"));
let fmt_layer = tracing_subscriber::fmt::layer()
.json()
.with_current_span(true)
.with_span_list(true)
.with_target(true)
.with_file(false)
.with_line_number(false)
.with_thread_ids(false)
.with_thread_names(false);
let otel_enabled = std::env::var("WARMPLANE_OTEL_ENABLED")
.map(|v| matches!(v.as_str(), "1" | "true" | "TRUE" | "yes" | "YES"))
.unwrap_or(false);
if !otel_enabled {
tracing_subscriber::registry()
.with(env_filter)
.with(fmt_layer)
.init();
return Ok(TelemetryGuard {
tracer_provider: None,
});
}
let service_name =
std::env::var("WARMPLANE_SERVICE_NAME").unwrap_or_else(|_| "warmplane".to_string());
let endpoint = std::env::var("OTEL_EXPORTER_OTLP_ENDPOINT")
.or_else(|_| std::env::var("WARMPLANE_OTEL_ENDPOINT"))
.unwrap_or_else(|_| "http://127.0.0.1:4317".to_string());
let exporter = opentelemetry_otlp::SpanExporter::builder()
.with_tonic()
.with_endpoint(endpoint)
.build()?;
let provider = TracerProvider::builder()
.with_batch_exporter(exporter, Tokio)
.with_resource(Resource::new_with_defaults(vec![KeyValue::new(
"service.name",
service_name,
)]))
.build();
let tracer = provider.tracer("warmplane");
global::set_tracer_provider(provider.clone());
let otel_layer = tracing_opentelemetry::layer().with_tracer(tracer);
tracing_subscriber::registry()
.with(env_filter)
.with(fmt_layer)
.with(otel_layer)
.init();
Ok(TelemetryGuard {
tracer_provider: Some(provider),
})
}