@@ -190,11 +190,8 @@ impl opentelemetry::trace::Tracer for SdkTracer {
190190 let trace_flags;
191191 let mut psc = & SpanContext :: empty_context ( ) ;
192192
193- let parent_span = if parent_cx. has_active_span ( ) {
194- Some ( parent_cx. span ( ) )
195- } else {
196- None
197- } ;
193+ // Invalid parents must start a new trace.
194+ let parent_span = Some ( parent_cx. span ( ) ) . filter ( |span| span. span_context ( ) . is_valid ( ) ) ;
198195
199196 // Inherit flags with the trace ID, or derive them from its generator.
200197 if let Some ( sc) = parent_span. as_ref ( ) . map ( |parent| parent. span_context ( ) ) {
@@ -782,6 +779,38 @@ mod tests {
782779 ) ;
783780 }
784781
782+ #[ test]
783+ fn invalid_parent_starts_new_trace_with_generator_random_flag ( ) {
784+ // Neither the invalid trace ID nor the parent's flags should be inherited.
785+ let invalid_parent = Context :: current_with_span ( TestSpan ( SpanContext :: new (
786+ TraceId :: INVALID ,
787+ SpanId :: from ( 7 ) ,
788+ TraceFlags :: SAMPLED | TraceFlags :: new ( 0x80 ) ,
789+ true ,
790+ TraceState :: default ( ) ,
791+ ) ) ) ;
792+
793+ for random in [ false , true ] {
794+ let tracer_provider = crate :: trace:: SdkTracerProvider :: builder ( )
795+ . with_id_generator ( TestIdGenerator { random } )
796+ . build ( ) ;
797+ let tracer = tracer_provider. tracer ( "test" ) ;
798+ let span = tracer. start_with_context ( "child" , & invalid_parent) ;
799+ let sc = span. span_context ( ) ;
800+ assert ! ( sc. is_valid( ) ) ;
801+ assert_eq ! ( sc. trace_id( ) , TraceId :: from( 1 ) ) ;
802+ assert_eq ! (
803+ span. exported_data( ) . unwrap( ) . parent_span_id,
804+ SpanId :: INVALID
805+ ) ;
806+ assert_eq ! (
807+ sc. trace_flags( ) ,
808+ TraceFlags :: SAMPLED . with_random( random) ,
809+ "random = {random}"
810+ ) ;
811+ }
812+ }
813+
785814 #[ test]
786815 fn dropped_child_keeps_only_random_flag ( ) {
787816 // Propagators may stash private bits (e.g. B3's deferred marker) in the
0 commit comments