Skip to main content

synapse_trace/
lib.rs

1use tracing_subscriber::{fmt::format::FmtSpan, layer::SubscriberExt, util::SubscriberInitExt};
2
3/// Initialize tracing subscriber (fmt only, no OTLP export)
4pub fn init_trace(crate_name: &str) {
5    tracing_subscriber::registry()
6        .with(
7            tracing_subscriber::EnvFilter::try_from_default_env()
8                .unwrap_or_else(|_| format!("{}=debug,tower_http=debug", crate_name).into()),
9        )
10        .with(tracing_subscriber::fmt::layer().with_span_events(FmtSpan::CLOSE))
11        .init();
12}
13
14/// Initialize tracing with OTLP export to a collector (e.g. Jaeger)
15///
16/// Requires the `otlp` feature. Falls back to `init_trace` if OTLP setup fails.
17#[cfg(feature = "otlp")]
18pub fn init_trace_with_otlp(crate_name: &str, otlp_endpoint: &str, service_name: &str) {
19    use opentelemetry::trace::TracerProvider;
20    use opentelemetry_otlp::WithExportConfig;
21    use opentelemetry_sdk::trace::SdkTracerProvider;
22
23    let exporter = match opentelemetry_otlp::SpanExporter::builder()
24        .with_tonic()
25        .with_endpoint(otlp_endpoint)
26        .build()
27    {
28        Ok(e) => e,
29        Err(err) => {
30            eprintln!("Failed to create OTLP exporter: {err} — falling back to fmt-only tracing");
31            init_trace(crate_name);
32            return;
33        }
34    };
35
36    let provider = SdkTracerProvider::builder()
37        .with_batch_exporter(exporter)
38        .with_resource(
39            opentelemetry_sdk::Resource::builder()
40                .with_service_name(service_name.to_string())
41                .build(),
42        )
43        .build();
44
45    let tracer = provider.tracer(service_name.to_string());
46
47    // Store provider for shutdown
48    PROVIDER.set(provider).ok();
49
50    let otel_layer = tracing_opentelemetry::layer().with_tracer(tracer);
51
52    tracing_subscriber::registry()
53        .with(
54            tracing_subscriber::EnvFilter::try_from_default_env()
55                .unwrap_or_else(|_| format!("{}=debug,tower_http=debug", crate_name).into()),
56        )
57        .with(tracing_subscriber::fmt::layer().with_span_events(FmtSpan::CLOSE))
58        .with(otel_layer)
59        .init();
60}
61
62#[cfg(feature = "otlp")]
63static PROVIDER: std::sync::OnceLock<opentelemetry_sdk::trace::SdkTracerProvider> =
64    std::sync::OnceLock::new();
65
66/// Gracefully shut down the OpenTelemetry tracer provider, flushing pending spans.
67#[cfg(feature = "otlp")]
68pub fn shutdown_trace() {
69    if let Some(provider) = PROVIDER.get() {
70        let _ = provider.shutdown();
71    }
72}
73
74/// No-op shutdown when OTLP is not enabled.
75#[cfg(not(feature = "otlp"))]
76pub fn shutdown_trace() {}