@@ -11,29 +11,29 @@ use std::sync::{LazyLock, OnceLock};
1111use anyhow:: Context as _;
1212use bytes:: Bytes ;
1313use http_body_util:: Full ;
14- use hyper:: { Response , header:: CONTENT_TYPE } ;
14+ use hyper:: { header:: CONTENT_TYPE , Response } ;
1515use mas_config:: {
1616 MetricsConfig , MetricsExporterKind , Propagator , TelemetryConfig , TracingConfig ,
1717 TracingExporterKind ,
1818} ;
1919use opentelemetry:: {
20- InstrumentationScope , KeyValue ,
2120 metrics:: Meter ,
2221 propagation:: { TextMapCompositePropagator , TextMapPropagator } ,
2322 trace:: TracerProvider as _,
23+ InstrumentationScope , KeyValue ,
2424} ;
2525use opentelemetry_otlp:: { WithExportConfig , WithHttpConfig } ;
2626use opentelemetry_prometheus_text_exporter:: PrometheusExporter ;
2727use opentelemetry_sdk:: {
28- Resource ,
29- metrics:: { ManualReader , SdkMeterProvider , periodic_reader_with_async_runtime:: PeriodicReader } ,
28+ metrics:: { periodic_reader_with_async_runtime:: PeriodicReader , ManualReader , SdkMeterProvider } ,
3029 propagation:: { BaggagePropagator , TraceContextPropagator } ,
3130 trace:: {
32- Sampler , SdkTracerProvider , Tracer , span_processor_with_async_runtime:: BatchSpanProcessor ,
31+ span_processor_with_async_runtime:: BatchSpanProcessor , IdGenerator , Sampler ,
32+ SdkTracerProvider , Tracer ,
3333 } ,
34+ Resource ,
3435} ;
3536use opentelemetry_semantic_conventions as semcov;
36- use url:: Url ;
3737
3838static SCOPE : LazyLock < InstrumentationScope > = LazyLock :: new ( || {
3939 InstrumentationScope :: builder ( env ! ( "CARGO_PKG_NAME" ) )
@@ -94,50 +94,64 @@ fn propagator(propagators: &[Propagator]) -> TextMapCompositePropagator {
9494 TextMapCompositePropagator :: new ( propagators)
9595}
9696
97- fn stdout_tracer_provider ( ) -> SdkTracerProvider {
98- let exporter = opentelemetry_stdout:: SpanExporter :: default ( ) ;
99- SdkTracerProvider :: builder ( )
100- . with_simple_exporter ( exporter)
101- . build ( )
102- }
103-
104- fn otlp_tracer_provider (
105- endpoint : Option < & Url > ,
106- sample_rate : f64 ,
107- ) -> anyhow:: Result < SdkTracerProvider > {
108- let mut exporter = opentelemetry_otlp:: SpanExporter :: builder ( )
109- . with_http ( )
110- . with_http_client ( mas_http:: reqwest_client ( ) ) ;
111- if let Some ( endpoint) = endpoint {
112- exporter = exporter. with_endpoint ( endpoint. to_string ( ) ) ;
97+ /// An [`IdGenerator`] which always returns an invalid trace ID and span ID
98+ ///
99+ /// This is used when no exporter is being used, so that we don't log the trace
100+ /// ID when we're not tracing.
101+ #[ derive( Debug , Clone , Copy ) ]
102+ struct InvalidIdGenerator ;
103+ impl IdGenerator for InvalidIdGenerator {
104+ fn new_trace_id ( & self ) -> opentelemetry:: TraceId {
105+ opentelemetry:: TraceId :: INVALID
113106 }
114- let exporter = exporter
115- . build ( )
116- . context ( "Failed to configure OTLP trace exporter" ) ?;
107+ fn new_span_id ( & self ) -> opentelemetry:: SpanId {
108+ opentelemetry:: SpanId :: INVALID
109+ }
110+ }
117111
118- let batch_processor =
119- BatchSpanProcessor :: builder ( exporter , opentelemetry_sdk :: runtime :: Tokio ) . build ( ) ;
112+ fn init_tracer ( config : & TracingConfig ) -> anyhow :: Result < ( ) > {
113+ let sample_rate = config . sample_rate . unwrap_or ( 1.0 ) ;
120114
121115 // We sample traces based on the parent if we have one, and if not, we
122116 // sample a ratio based on the configured sample rate
123117 let sampler = Sampler :: ParentBased ( Box :: new ( Sampler :: TraceIdRatioBased ( sample_rate) ) ) ;
124118
125- let tracer_provider = SdkTracerProvider :: builder ( )
126- . with_span_processor ( batch_processor)
119+ let tracer_provider_builder = SdkTracerProvider :: builder ( )
127120 . with_resource ( resource ( ) )
128- . with_sampler ( sampler)
129- . build ( ) ;
130-
131- Ok ( tracer_provider)
132- }
121+ . with_sampler ( sampler) ;
133122
134- fn init_tracer ( config : & TracingConfig ) -> anyhow:: Result < ( ) > {
135- let sample_rate = config. sample_rate . unwrap_or ( 1.0 ) ;
136123 let tracer_provider = match config. exporter {
137- TracingExporterKind :: None => return Ok ( ( ) ) ,
138- TracingExporterKind :: Stdout => stdout_tracer_provider ( ) ,
139- TracingExporterKind :: Otlp => otlp_tracer_provider ( config. endpoint . as_ref ( ) , sample_rate) ?,
124+ TracingExporterKind :: None => tracer_provider_builder
125+ . with_id_generator ( InvalidIdGenerator )
126+ . build ( ) ,
127+
128+ TracingExporterKind :: Stdout => {
129+ let exporter = opentelemetry_stdout:: SpanExporter :: default ( ) ;
130+ tracer_provider_builder
131+ . with_simple_exporter ( exporter)
132+ . build ( )
133+ }
134+
135+ TracingExporterKind :: Otlp => {
136+ let mut exporter = opentelemetry_otlp:: SpanExporter :: builder ( )
137+ . with_http ( )
138+ . with_http_client ( mas_http:: reqwest_client ( ) ) ;
139+ if let Some ( endpoint) = & config. endpoint {
140+ exporter = exporter. with_endpoint ( endpoint. as_str ( ) ) ;
141+ }
142+ let exporter = exporter
143+ . build ( )
144+ . context ( "Failed to configure OTLP trace exporter" ) ?;
145+
146+ let batch_processor =
147+ BatchSpanProcessor :: builder ( exporter, opentelemetry_sdk:: runtime:: Tokio ) . build ( ) ;
148+
149+ tracer_provider_builder
150+ . with_span_processor ( batch_processor)
151+ . build ( )
152+ }
140153 } ;
154+
141155 TRACER_PROVIDER
142156 . set ( tracer_provider. clone ( ) )
143157 . map_err ( |_| anyhow:: anyhow!( "TRACER_PROVIDER was set twice" ) ) ?;
0 commit comments