@@ -680,6 +680,116 @@ public void StartTransaction_SameInstrumenter_SampledIn()
680680 transaction . IsSampled . Should ( ) . BeTrue ( ) ;
681681 }
682682
683+ [ Fact ]
684+ public void StartTransaction_NoDynamicSamplingContext_GeneratesSampleRand ( )
685+ {
686+ // Arrange
687+ var transactionContext = new TransactionContext ( "name" , "operation" ) ;
688+ var customContext = new Dictionary < string , object > ( ) ;
689+
690+ var hub = _fixture . GetSut ( ) ;
691+
692+ // Act
693+ var transaction = hub . StartTransaction ( transactionContext , customContext ) ;
694+
695+ // Assert
696+ var transactionTracer = ( ( TransactionTracer ) transaction ) ;
697+ transactionTracer . SampleRand . Should ( ) . NotBeNull ( ) ;
698+ transactionTracer . DynamicSamplingContext . Should ( ) . NotBeNull ( ) ;
699+ transactionTracer . DynamicSamplingContext ! . Items . Should ( ) . ContainKey ( "sample_rand" ) ;
700+ transactionTracer . DynamicSamplingContext . Items [ "sample_rand" ] . Should ( ) . Be ( transactionTracer . SampleRand ! . Value . ToString ( "N4" , CultureInfo . InvariantCulture ) ) ;
701+ }
702+
703+ [ Fact ]
704+ public void StartTransaction_DynamicSamplingContext_InheritsSampleRand ( )
705+ {
706+ // Arrange
707+ var transactionContext = new TransactionContext ( "name" , "operation" ) ;
708+ var customContext = new Dictionary < string , object > ( ) ;
709+ var dsc = BaggageHeader . Create ( new List < KeyValuePair < string , string > >
710+ {
711+ { "sentry-trace_id" , "43365712692146d08ee11a729dfbcaca" } ,
712+ { "sentry-public_key" , "d4d82fc1c2c4032a83f3a29aa3a3aff" } ,
713+ { "sentry-sampled" , "true" } ,
714+ { "sentry-sample_rate" , "0.5" } , // Required in the baggage header, but ignored by sampling logic
715+ { "sentry-sample_rand" , "0.1234" }
716+ } ) . CreateDynamicSamplingContext ( ) ;
717+
718+ _fixture . Options . TracesSampleRate = 0.4 ;
719+ var hub = _fixture . GetSut ( ) ;
720+
721+ // Act
722+ var transaction = hub . StartTransaction ( transactionContext , customContext , dsc ) ;
723+
724+ // Assert
725+ var transactionTracer = ( ( TransactionTracer ) transaction ) ;
726+ transactionTracer . IsSampled . Should ( ) . Be ( true ) ;
727+ transactionTracer . SampleRate . Should ( ) . Be ( 0.4 ) ;
728+ transactionTracer . SampleRand . Should ( ) . Be ( 0.1234 ) ;
729+ transactionTracer . DynamicSamplingContext . Should ( ) . Be ( dsc ) ;
730+ }
731+
732+ [ Theory ]
733+ [ InlineData ( 0.1 , false ) ]
734+ [ InlineData ( 0.2 , true ) ]
735+ public void StartTransaction_TraceSampler_UsesSampleRand ( double sampleRate , bool expectedIsSampled )
736+ {
737+ // Arrange
738+ var transactionContext = new TransactionContext ( "name" , "operation" ) ;
739+ var customContext = new Dictionary < string , object > ( ) ;
740+ var dsc = BaggageHeader . Create ( new List < KeyValuePair < string , string > >
741+ {
742+ { "sentry-trace_id" , "43365712692146d08ee11a729dfbcaca" } ,
743+ { "sentry-public_key" , "d4d82fc1c2c4032a83f3a29aa3a3aff" } ,
744+ { "sentry-sampled" , "true" } ,
745+ { "sentry-sample_rate" , "0.5" } ,
746+ { "sentry-sample_rand" , "0.1234" }
747+ } ) . CreateDynamicSamplingContext ( ) ;
748+
749+ _fixture . Options . TracesSampler = _ => sampleRate ;
750+ var hub = _fixture . GetSut ( ) ;
751+
752+ // Act
753+ var transaction = hub . StartTransaction ( transactionContext , customContext , dsc ) ;
754+
755+ // Assert
756+ var transactionTracer = ( ( TransactionTracer ) transaction ) ;
757+ transactionTracer . IsSampled . Should ( ) . Be ( expectedIsSampled ) ;
758+ transactionTracer . SampleRate . Should ( ) . Be ( sampleRate ) ;
759+ transactionTracer . SampleRand . Should ( ) . Be ( 0.1234 ) ;
760+ transactionTracer . DynamicSamplingContext . Should ( ) . Be ( dsc ) ;
761+ }
762+
763+ [ Theory ]
764+ [ InlineData ( 0.1 , false ) ]
765+ [ InlineData ( 0.2 , true ) ]
766+ public void StartTransaction_StaticSampler_UsesSampleRand ( double sampleRate , bool expectedIsSampled )
767+ {
768+ // Arrange
769+ var transactionContext = new TransactionContext ( "name" , "operation" ) ;
770+ var customContext = new Dictionary < string , object > ( ) ;
771+ var dsc = BaggageHeader . Create ( new List < KeyValuePair < string , string > >
772+ {
773+ { "sentry-trace_id" , "43365712692146d08ee11a729dfbcaca" } ,
774+ { "sentry-public_key" , "d4d82fc1c2c4032a83f3a29aa3a3aff" } ,
775+ { "sentry-sample_rate" , "0.5" } , // Static sampling ignores this and uses options.TracesSampleRate instead
776+ { "sentry-sample_rand" , "0.1234" }
777+ } ) . CreateDynamicSamplingContext ( ) ;
778+
779+ _fixture . Options . TracesSampleRate = sampleRate ;
780+ var hub = _fixture . GetSut ( ) ;
781+
782+ // Act
783+ var transaction = hub . StartTransaction ( transactionContext , customContext , dsc ) ;
784+
785+ // Assert
786+ var transactionTracer = ( ( TransactionTracer ) transaction ) ;
787+ transactionTracer . IsSampled . Should ( ) . Be ( expectedIsSampled ) ;
788+ transactionTracer . SampleRate . Should ( ) . Be ( sampleRate ) ;
789+ transactionTracer . SampleRand . Should ( ) . Be ( 0.1234 ) ;
790+ transactionTracer . DynamicSamplingContext . Should ( ) . Be ( dsc ) ;
791+ }
792+
683793 [ Fact ]
684794 public void StartTransaction_DifferentInstrumenter_SampledIn ( )
685795 {
0 commit comments