@@ -146,10 +146,11 @@ public void OnStart_Transaction_With_DynamicSamplingContext()
146146 }
147147
148148 [ Fact ]
149- public void OnStart_WithParentSpanId_StartsChildSpan ( )
149+ public void OnStart_SampledWithParentSpanId_StartsChildSpan ( )
150150 {
151151 // Arrange
152152 _fixture . Options . Instrumenter = Instrumenter . OpenTelemetry ;
153+ _fixture . Options . TracesSampleRate = 1.0 ;
153154 var sut = _fixture . GetSut ( ) ;
154155
155156 using var parent = Tracer . StartActivity ( "Parent" ) ;
@@ -164,16 +165,18 @@ public void OnStart_WithParentSpanId_StartsChildSpan()
164165 Assert . True ( sut . _map . TryGetValue ( data . SpanId , out var span ) ) ;
165166 using ( new AssertionScope ( ) )
166167 {
167- span . Should ( ) . BeOfType < SpanTracer > ( ) ;
168+ span . IsSampled . Should ( ) . Be ( true ) ;
168169 span . SpanId . Should ( ) . Be ( data . SpanId . AsSentrySpanId ( ) ) ;
170+
169171 if ( span is not SpanTracer spanTracer )
170172 {
171173 Assert . Fail ( "Span is not a span tracer" ) ;
172174 return ;
173175 }
176+
177+ span . SpanId . Should ( ) . Be ( data . SpanId . AsSentrySpanId ( ) ) ;
174178 using ( new AssertionScope ( ) )
175179 {
176- spanTracer . SpanId . Should ( ) . Be ( data . SpanId . AsSentrySpanId ( ) ) ;
177180 spanTracer . ParentSpanId . Should ( ) . Be ( data . ParentSpanId . AsSentrySpanId ( ) ) ;
178181 spanTracer . TraceId . Should ( ) . Be ( data . TraceId . AsSentryId ( ) ) ;
179182 spanTracer . Operation . Should ( ) . Be ( data . OperationName ) ;
@@ -184,6 +187,32 @@ public void OnStart_WithParentSpanId_StartsChildSpan()
184187 }
185188 }
186189
190+ [ Fact ]
191+ public void OnStart_NotSampledWithParentSpanId_StartsChildSpan ( )
192+ {
193+ // Arrange
194+ _fixture . Options . Instrumenter = Instrumenter . OpenTelemetry ;
195+ _fixture . Options . TracesSampleRate = 0.0 ;
196+ var sut = _fixture . GetSut ( ) ;
197+
198+ using var parent = Tracer . StartActivity ( "Parent" ) ;
199+ sut . OnStart ( parent ) ;
200+
201+ using var data = Tracer . StartActivity ( "TestActivity" ) ;
202+
203+ // Act
204+ sut . OnStart ( data ! ) ;
205+
206+ // Assert
207+ Assert . True ( sut . _map . TryGetValue ( data . SpanId , out var span ) ) ;
208+ using ( new AssertionScope ( ) )
209+ {
210+ span . IsSampled . Should ( ) . Be ( false ) ;
211+ span . SpanId . Should ( ) . Be ( data . SpanId . AsSentrySpanId ( ) ) ;
212+ span . Should ( ) . BeOfType < UnsampledSpan > ( ) ;
213+ }
214+ }
215+
187216 [ Fact ]
188217 public void OnStart_WithSentryParentSpanId_StartsChildSpan ( )
189218 {
@@ -257,10 +286,11 @@ public void StartSpan_UsingSentryTracing_StartsChildSpan()
257286 }
258287
259288 [ Fact ]
260- public void OnStart_WithoutParentSpanId_StartsNewTransaction ( )
289+ public void OnStart_SampledWithoutParentSpanId_StartsNewTransaction ( )
261290 {
262291 // Arrange
263292 _fixture . Options . Instrumenter = Instrumenter . OpenTelemetry ;
293+ _fixture . Options . TracesSampleRate = 1.0 ;
264294 _fixture . ScopeManager = Substitute . For < IInternalScopeManager > ( ) ;
265295 var scope = new Scope ( ) ;
266296 var clientScope = new KeyValuePair < Scope , ISentryClient > ( scope , _fixture . Client ) ;
@@ -279,6 +309,7 @@ public void OnStart_WithoutParentSpanId_StartsNewTransaction()
279309 Assert . Fail ( "Span is not a transaction tracer" ) ;
280310 return ;
281311 }
312+
282313 using ( new AssertionScope ( ) )
283314 {
284315 transaction . SpanId . Should ( ) . Be ( data . SpanId . AsSentrySpanId ( ) ) ;
@@ -293,7 +324,39 @@ public void OnStart_WithoutParentSpanId_StartsNewTransaction()
293324 }
294325
295326 [ Fact ]
296- public void OnEnd_FinishesSpan ( )
327+ public void OnStart_NotSampledWithoutParentSpanId_StartsNewTransaction ( )
328+ {
329+ // Arrange
330+ _fixture . Options . Instrumenter = Instrumenter . OpenTelemetry ;
331+ _fixture . Options . TracesSampleRate = 0.0 ;
332+ _fixture . ScopeManager = Substitute . For < IInternalScopeManager > ( ) ;
333+ var scope = new Scope ( ) ;
334+ var clientScope = new KeyValuePair < Scope , ISentryClient > ( scope , _fixture . Client ) ;
335+ _fixture . ScopeManager . GetCurrent ( ) . Returns ( clientScope ) ;
336+ var sut = _fixture . GetSut ( ) ;
337+
338+ var data = Tracer . StartActivity ( "test op" ) ;
339+
340+ // Act
341+ sut . OnStart ( data ! ) ;
342+
343+ // Assert
344+ Assert . True ( sut . _map . TryGetValue ( data . SpanId , out var span ) ) ;
345+ if ( span is not UnsampledTransaction transaction )
346+ {
347+ Assert . Fail ( "Span is not an unsampled transaction" ) ;
348+ return ;
349+ }
350+
351+ using ( new AssertionScope ( ) )
352+ {
353+ transaction . SpanId . Should ( ) . Be ( data . SpanId . AsSentrySpanId ( ) ) ;
354+ transaction . TraceId . Should ( ) . Be ( data . TraceId . AsSentryId ( ) ) ;
355+ }
356+ }
357+
358+ [ Fact ]
359+ public void OnEnd_Sampled_Span_FinishesSpan ( )
297360 {
298361 // Arrange
299362 _fixture . Options . Instrumenter = Instrumenter . OpenTelemetry ;
@@ -338,6 +401,34 @@ public void OnEnd_FinishesSpan()
338401 }
339402 }
340403
404+ [ Fact ]
405+ public void OnEnd_Unsampled_Span_DoesNotThrow ( )
406+ {
407+ // Arrange
408+ _fixture . Options . Instrumenter = Instrumenter . OpenTelemetry ;
409+ _fixture . Options . TracesSampleRate = 0.0 ;
410+ var sut = _fixture . GetSut ( ) ;
411+
412+ var parent = Tracer . StartActivity ( name : "transaction" ) ! ;
413+ sut . OnStart ( parent ) ;
414+
415+ Dictionary < string , object > tags = [ ] ;
416+ var data = Tracer . StartActivity ( name : "test operation" , kind : ActivityKind . Internal , parentContext : default , tags ) ! ;
417+ data . DisplayName = "test display name" ;
418+ sut . OnStart ( data ) ;
419+
420+ sut . _map . TryGetValue ( data . SpanId , out var span ) ;
421+
422+ // Act
423+ sut . OnEnd ( data ) ;
424+
425+ // Assert
426+ span . Should ( ) . BeOfType < UnsampledSpan > ( ) ;
427+
428+ // There's nothing else to assert here, as long as calling OnEnd does not throw an exception,
429+ // UnsampledSpan.Finish() is basically a no-op.
430+ }
431+
341432 [ Fact ]
342433 public void OnEnd_Transaction_RestoresSavedScope ( )
343434 {
@@ -418,7 +509,7 @@ public void OnEnd_SpansEnriched()
418509 }
419510
420511 [ Fact ]
421- public void OnEnd_FinishesTransaction ( )
512+ public void OnEnd_Sampled_FinishesTransaction ( )
422513 {
423514 // Arrange
424515 _fixture . Options . Instrumenter = Instrumenter . OpenTelemetry ;
@@ -460,6 +551,33 @@ public void OnEnd_FinishesTransaction()
460551 }
461552 }
462553
554+ [ Fact ]
555+ public void OnEnd_NotSampled_FinishesTransaction ( )
556+ {
557+ // Arrange
558+ _fixture . Options . Instrumenter = Instrumenter . OpenTelemetry ;
559+ _fixture . Options . TracesSampleRate = 0.0 ;
560+ var sut = _fixture . GetSut ( ) ;
561+
562+ Dictionary < string , object > tags = [ ] ;
563+ var data = Tracer . StartActivity ( name : "test operation" , kind : ActivityKind . Internal , parentContext : default , tags ) ! ;
564+ data . DisplayName = "test display name" ;
565+ sut . OnStart ( data ) ;
566+
567+ sut . _map . TryGetValue ( data . SpanId , out var span ) ;
568+
569+ // Act
570+ sut . OnEnd ( data ) ;
571+
572+ // Assert
573+ if ( span is not UnsampledTransaction transaction )
574+ {
575+ Assert . Fail ( "Span is not an unsampled transaction" ) ;
576+ return ;
577+ }
578+ transaction . IsFinished . Should ( ) . BeTrue ( ) ;
579+ }
580+
463581 [ Fact ]
464582 public void OnEnd_FilteredTransaction_DoesNotFinishTransaction ( )
465583 {
0 commit comments