66import sys
77from collections .abc import Mapping
88from datetime import timedelta
9- from decimal import ROUND_DOWN , Decimal , DefaultContext , localcontext
109from random import Random
1110from urllib .parse import quote , unquote
1211import uuid
@@ -502,7 +501,7 @@ def _fill_sample_rand(self):
502501 return
503502
504503 sample_rand = try_convert (
505- Decimal , self .dynamic_sampling_context .get ("sample_rand" )
504+ float , self .dynamic_sampling_context .get ("sample_rand" )
506505 )
507506 if sample_rand is not None and 0 <= sample_rand < 1 :
508507 # sample_rand is present and valid, so don't overwrite it
@@ -650,7 +649,7 @@ def populate_from_transaction(cls, transaction):
650649 options = client .options or {}
651650
652651 sentry_items ["trace_id" ] = transaction .trace_id
653- sentry_items ["sample_rand" ] = str ( transaction ._sample_rand )
652+ sentry_items ["sample_rand" ] = f" { transaction ._sample_rand :.6f } " # noqa: E231
654653
655654 if options .get ("environment" ):
656655 sentry_items ["environment" ] = options ["environment" ]
@@ -724,15 +723,15 @@ def strip_sentry_baggage(header):
724723 )
725724
726725 def _sample_rand (self ):
727- # type: () -> Optional[Decimal ]
726+ # type: () -> Optional[float ]
728727 """Convenience method to get the sample_rand value from the sentry_items.
729728
730- We validate the value and parse it as a Decimal before returning it. The value is considered
731- valid if it is a Decimal in the range [0, 1).
729+ We validate the value and parse it as a float before returning it. The value is considered
730+ valid if it is a float in the range [0, 1).
732731 """
733- sample_rand = try_convert (Decimal , self .sentry_items .get ("sample_rand" ))
732+ sample_rand = try_convert (float , self .sentry_items .get ("sample_rand" ))
734733
735- if sample_rand is not None and Decimal ( 0 ) <= sample_rand < Decimal ( 1 ) :
734+ if sample_rand is not None and 0.0 <= sample_rand < 1.0 :
736735 return sample_rand
737736
738737 return None
@@ -898,7 +897,7 @@ def _generate_sample_rand(
898897 * ,
899898 interval = (0.0 , 1.0 ), # type: tuple[float, float]
900899):
901- # type: (...) -> Decimal
900+ # type: (...) -> float
902901 """Generate a sample_rand value from a trace ID.
903902
904903 The generated value will be pseudorandomly chosen from the provided
@@ -913,19 +912,16 @@ def _generate_sample_rand(
913912 raise ValueError ("Invalid interval: lower must be less than upper" )
914913
915914 rng = Random (trace_id )
916- sample_rand = upper
917- while sample_rand >= upper :
918- sample_rand = rng .uniform (lower , upper )
919-
920- # Round down to exactly six decimal-digit precision.
921- # Setting the context is needed to avoid an InvalidOperation exception
922- # in case the user has changed the default precision or set traps.
923- with localcontext (DefaultContext ) as ctx :
924- ctx .prec = 6
925- return Decimal (sample_rand ).quantize (
926- Decimal ("0.000001" ),
927- rounding = ROUND_DOWN ,
928- )
915+ lower_scaled = int (lower * 1_000_000 )
916+ upper_scaled = int (upper * 1_000_000 )
917+ try :
918+ sample_rand_scaled = rng .randrange (lower_scaled , upper_scaled )
919+ except ValueError :
920+ # In some corner cases it might happen that the range is too small
921+ # In that case, just take the lower bound
922+ sample_rand_scaled = lower_scaled
923+
924+ return sample_rand_scaled / 1_000_000
929925
930926
931927def _sample_rand_range (parent_sampled , sample_rate ):
0 commit comments