@@ -7,7 +7,7 @@ use opentelemetry::{
7
7
use opentelemetry_sdk:: {
8
8
export:: trace:: { ExportResult , SpanData , SpanExporter } ,
9
9
propagation:: { BaggagePropagator , TraceContextPropagator } ,
10
- trace:: { Tracer , TracerProvider } ,
10
+ trace:: { Config , Sampler , Tracer , TracerProvider } ,
11
11
} ;
12
12
use std:: collections:: { HashMap , HashSet } ;
13
13
use std:: sync:: { Arc , Mutex } ;
@@ -101,6 +101,49 @@ fn inject_context_into_outgoing_requests() {
101
101
assert_carrier_attrs_eq ( & carrier, & outgoing_req_carrier) ;
102
102
}
103
103
104
+ #[ test]
105
+ fn sampling_decision_respects_new_parent ( ) {
106
+ // custom setup required due to ParentBased(AlwaysOff) sampler
107
+ let exporter = TestExporter :: default ( ) ;
108
+ let provider = TracerProvider :: builder ( )
109
+ . with_simple_exporter ( exporter. clone ( ) )
110
+ . with_config (
111
+ Config :: default ( ) . with_sampler ( Sampler :: ParentBased ( Box :: new ( Sampler :: AlwaysOff ) ) ) ,
112
+ )
113
+ . build ( ) ;
114
+ let tracer = provider. tracer ( "test" ) ;
115
+ let subscriber = tracing_subscriber:: registry ( ) . with ( layer ( ) . with_tracer ( tracer. clone ( ) ) ) ;
116
+
117
+ // set up remote sampled headers
118
+ let sampled_headers = HashMap :: from ( [ (
119
+ "traceparent" . to_string ( ) ,
120
+ "00-0af7651916cd43dd8448eb211c80319c-b7ad6b7169203331-01" . to_string ( ) ,
121
+ ) ] ) ;
122
+ let remote_sampled_cx = TraceContextPropagator :: new ( ) . extract ( & sampled_headers) ;
123
+ let root_span = tracer. start_with_context ( "root_span" , & remote_sampled_cx) ;
124
+
125
+ tracing:: subscriber:: with_default ( subscriber, || {
126
+ let child = tracing:: debug_span!( "child" ) ;
127
+ child. context ( ) ; // force a sampling decision
128
+ child. set_parent ( Context :: current_with_span ( root_span) ) ;
129
+ } ) ;
130
+
131
+ drop ( provider) ; // flush all spans
132
+
133
+ // assert new parent-based sampling decision
134
+ let spans = exporter. 0 . lock ( ) . unwrap ( ) ;
135
+ assert_eq ! ( spans. len( ) , 2 , "Expected 2 spans, got {}" , spans. len( ) ) ;
136
+ assert ! (
137
+ spans[ 0 ] . span_context. is_sampled( ) ,
138
+ "Root span should be sampled"
139
+ ) ;
140
+ assert_eq ! (
141
+ spans[ 1 ] . span_context. is_sampled( ) ,
142
+ spans[ 0 ] . span_context. is_sampled( ) ,
143
+ "Child span should respect parent sampling decision"
144
+ ) ;
145
+ }
146
+
104
147
fn assert_shared_attrs_eq ( sc_a : & SpanContext , sc_b : & SpanContext ) {
105
148
assert_eq ! ( sc_a. trace_id( ) , sc_b. trace_id( ) ) ;
106
149
assert_eq ! ( sc_a. trace_state( ) , sc_b. trace_state( ) ) ;
0 commit comments