@@ -9,7 +9,7 @@ use tracing::{debug, warn};
99use crate :: {
1010 Serialize ,
1111 common:: {
12- config:: ConfRange ,
12+ config:: { ConfRange , Probability } ,
1313 strings,
1414 strings:: { random_strings_with_length, random_strings_with_length_range} ,
1515 } ,
@@ -226,15 +226,15 @@ pub struct TimestampConfig {
226226 ///
227227 /// The `DogStatsD` protocol only supports this field for count and gauge metrics.
228228 pub range : ConfRange < u32 > ,
229- /// Probability between 0 and 1 that a generated count or gauge metric includes `|T`.
230- pub probability : f32 ,
229+ /// Probability that a generated count or gauge metric includes `|T`.
230+ pub probability : Probability ,
231231}
232232
233233impl Default for TimestampConfig {
234234 fn default ( ) -> Self {
235235 Self {
236236 range : ConfRange :: Constant ( 1 ) ,
237- probability : 0.0 ,
237+ probability : Probability :: try_new ( 0.0 ) . expect ( "0.0 is in [0.0, 1.0]" ) ,
238238 }
239239 }
240240}
@@ -245,13 +245,7 @@ impl TimestampConfig {
245245 if !range_valid {
246246 return Result :: Err ( format ! ( "Timestamp range is invalid: {reason}" ) ) ;
247247 }
248- if !self . probability . is_finite ( ) || self . probability < 0.0 || self . probability > 1.0 {
249- return Result :: Err ( format ! (
250- "Timestamp probability {} must be finite and in range [0.0, 1.0]" ,
251- self . probability
252- ) ) ;
253- }
254- if self . probability > 0.0 && self . range . start ( ) == 0 {
248+ if self . probability . get ( ) > 0.0 && self . range . start ( ) == 0 {
255249 return Result :: Err (
256250 "Timestamp range start value cannot be 0 when timestamps are enabled" . to_string ( ) ,
257251 ) ;
@@ -450,7 +444,7 @@ impl MemberGenerator {
450444 external_data : Vec < String > ,
451445 cardinality : Vec < String > ,
452446 timestamp_range : ConfRange < u32 > ,
453- timestamp_probability : f32 ,
447+ timestamp_probability : Probability ,
454448 mut rng : & mut R ,
455449 ) -> Result < Self , crate :: Error >
456450 where
@@ -833,12 +827,16 @@ impl DogStatsD {
833827
834828#[ cfg( test) ]
835829mod test {
836- use super :: { ConfRange , Config , KindWeights , MetricWeights , TimestampConfig } ;
830+ use super :: { ConfRange , Config , KindWeights , MetricWeights , Probability , TimestampConfig } ;
837831 use proptest:: prelude:: * ;
838832 use rand:: { SeedableRng , rngs:: SmallRng } ;
839833
840834 use crate :: { DogStatsD , Serialize } ;
841835
836+ fn prob ( value : f32 ) -> Probability {
837+ Probability :: try_new ( value) . expect ( "value must be in [0.0, 1.0]" )
838+ }
839+
842840 // Generate a batch of raw DogStatsD bytes using the given config and seed.
843841 fn generate_bytes ( config : & Config , seed : u64 ) -> Vec < u8 > {
844842 let mut rng = SmallRng :: seed_from_u64 ( seed) ;
@@ -942,7 +940,7 @@ mod test {
942940 metric_weights : MetricWeights :: new ( 100 , 100 , 0 , 0 , 0 , 0 ) ,
943941 timestamp : Box :: new ( TimestampConfig {
944942 range : ConfRange :: Constant ( 1_656_581_400 ) ,
945- probability : 1.0 ,
943+ probability : prob ( 1.0 ) ,
946944 } ) ,
947945 ..Default :: default ( )
948946 } ;
@@ -956,7 +954,7 @@ mod test {
956954 metric_weights : MetricWeights :: new ( 100 , 100 , 0 , 0 , 0 , 0 ) ,
957955 timestamp : Box :: new ( TimestampConfig {
958956 range : ConfRange :: Constant ( 1_656_581_400 ) ,
959- probability : 0.0 ,
957+ probability : prob ( 0.0 ) ,
960958 } ) ,
961959 ..Default :: default ( )
962960 } ;
@@ -974,7 +972,7 @@ mod test {
974972 metric_weights : MetricWeights :: new ( 100 , 100 , 0 , 0 , 0 , 0 ) ,
975973 timestamp : Box :: new ( TimestampConfig {
976974 range : ConfRange :: Inclusive { min : 10 , max : 20 } ,
977- probability : 1.0 ,
975+ probability : prob ( 1.0 ) ,
978976 } ) ,
979977 ..Default :: default ( )
980978 } ;
@@ -1001,7 +999,7 @@ mod test {
1001999 metric_weights : MetricWeights :: new ( 0 , 0 , 100 , 0 , 0 , 0 ) ,
10021000 timestamp : Box :: new ( TimestampConfig {
10031001 range : ConfRange :: Constant ( 1_656_581_400 ) ,
1004- probability : 1.0 ,
1002+ probability : prob ( 1.0 ) ,
10051003 } ) ,
10061004 ..Default :: default ( )
10071005 } ;
@@ -1013,23 +1011,22 @@ mod test {
10131011 }
10141012
10151013 #[ test]
1016- fn timestamp_probability_must_be_valid ( ) {
1017- let config = Config {
1018- timestamp : Box :: new ( TimestampConfig {
1019- probability : 2.0 ,
1020- ..Default :: default ( )
1021- } ) ,
1022- ..Default :: default ( )
1023- } ;
1024- assert ! ( config. valid( ) . is_err( ) ) ;
1014+ fn timestamp_probability_rejects_out_of_range_on_deserialize ( ) {
1015+ let yaml = "range: !constant 1\n probability: 2.0\n " ;
1016+ let err = serde_yaml:: from_str :: < TimestampConfig > ( yaml)
1017+ . expect_err ( "probability 2.0 must be rejected at deserialize time" ) ;
1018+ assert ! (
1019+ err. to_string( ) . contains( "exceeds 1.0" ) ,
1020+ "unexpected error: {err}"
1021+ ) ;
10251022 }
10261023
10271024 #[ test]
10281025 fn timestamp_range_must_be_positive_when_enabled ( ) {
10291026 let config = Config {
10301027 timestamp : Box :: new ( TimestampConfig {
10311028 range : ConfRange :: Constant ( 0 ) ,
1032- probability : 1.0 ,
1029+ probability : prob ( 1.0 ) ,
10331030 } ) ,
10341031 ..Default :: default ( )
10351032 } ;
@@ -1064,7 +1061,7 @@ mod test {
10641061 metric_weights: MetricWeights :: new( 100 , 100 , 0 , 0 , 0 , 0 ) ,
10651062 timestamp: Box :: new( TimestampConfig {
10661063 range: ConfRange :: Inclusive { min: 10 , max: 20 } ,
1067- probability: 0.5 ,
1064+ probability: prob ( 0.5 ) ,
10681065 } ) ,
10691066 ..Default :: default ( )
10701067 } ;
0 commit comments