1#![allow(unused_imports)] use opentelemetry::trace::{TraceId, TracerProvider};
3use opentelemetry_sdk::{runtime, trace as sdktrace, trace::Config, Resource};
4use tracing::Instrument;
5use tracing_subscriber::{prelude::*, EnvFilter, Registry};
6
7pub fn get_trace_id() -> TraceId {
9 use opentelemetry::trace::TraceContextExt as _; use tracing_opentelemetry::OpenTelemetrySpanExt as _; tracing::Span::current()
12 .context()
13 .span()
14 .span_context()
15 .trace_id()
16}
17
18#[cfg(feature = "telemetry")]
19fn resource() -> Resource {
20 use opentelemetry::KeyValue;
21 Resource::new([
22 KeyValue::new("service.name", env!("CARGO_PKG_NAME")),
23 KeyValue::new("service.version", env!("CARGO_PKG_VERSION")),
24 ])
25}
26
27#[cfg(feature = "telemetry")]
28fn init_tracer() -> sdktrace::Tracer {
29 use opentelemetry_otlp::{SpanExporter, WithExportConfig};
30 let endpoint = std::env::var("OPENTELEMETRY_ENDPOINT_URL").expect("Needs an otel collector");
31 let exporter = SpanExporter::builder()
32 .with_tonic()
33 .with_endpoint(endpoint)
34 .build()
35 .unwrap();
36
37 let provider = sdktrace::TracerProvider::builder()
38 .with_batch_exporter(exporter, runtime::Tokio)
39 .with_resource(resource())
40 .build();
41
42 opentelemetry::global::set_tracer_provider(provider.clone());
43 provider.tracer("tracing-otel-subscriber")
44}
45
46pub async fn init() {
48 #[cfg(feature = "telemetry")]
50 let otel = tracing_opentelemetry::OpenTelemetryLayer::new(init_tracer());
51
52 let logger = tracing_subscriber::fmt::layer().compact();
53 let env_filter = EnvFilter::try_from_default_env()
54 .or(EnvFilter::try_new("info"))
55 .unwrap();
56
57 let reg = Registry::default();
59 #[cfg(feature = "telemetry")]
60 reg.with(env_filter).with(logger).with(otel).init();
61 #[cfg(not(feature = "telemetry"))]
62 reg.with(env_filter).with(logger).init();
63}
64
65#[cfg(test)]
66mod test {
67 #[cfg(feature = "telemetry")]
70 #[tokio::test]
71 #[ignore = "requires a trace exporter"]
72 async fn get_trace_id_returns_valid_traces() {
73 use super::*;
74 super::init().await;
75 #[tracing::instrument(name = "test_span")] fn test_trace_id() -> TraceId {
77 get_trace_id()
78 }
79 assert_ne!(test_trace_id(), TraceId::INVALID, "valid trace");
80 }
81}