@@ -2339,7 +2339,7 @@ impl<'de> Deserialize<'de> for LogAttribute {
23392339
23402340/// An ID that identifies an organization in the Sentry backend.
23412341#[ derive( Clone , Copy , Debug , Serialize , Deserialize , PartialEq ) ]
2342- struct OrganizationId ( u64 ) ;
2342+ pub struct OrganizationId ( u64 ) ;
23432343
23442344impl From < u64 > for OrganizationId {
23452345 fn from ( value : u64 ) -> Self {
@@ -2363,25 +2363,51 @@ impl std::fmt::Display for OrganizationId {
23632363
23642364/// A random number generated at the start of a trace by the head of trace SDK.
23652365#[ derive( Clone , Copy , Debug , Serialize , Deserialize , PartialEq ) ]
2366- struct SampleRand ( f64 ) ;
2366+ pub struct SampleRand ( f64 ) ;
23672367
2368- impl From < f64 > for SampleRand {
2369- fn from ( value : f64 ) -> Self {
2370- Self ( value)
2368+ /// An error that indicates failure to construct a SampleRand.
2369+ #[ derive( Debug , Error ) ]
2370+ pub enum InvalidSampleRandError {
2371+ /// Indicates that the given value cannot be converted to a f64 succesfully.
2372+ #[ error( "failed to parse f64: {0}" ) ]
2373+ InvalidFloat ( #[ from] std:: num:: ParseFloatError ) ,
2374+
2375+ /// Indicates that the given float is outside of the valid range for a sample rand, that is the
2376+ /// half-open interval [0.0, 1.0).
2377+ #[ error( "sample rand value out of admissible interval [0.0, 1.0)" ) ]
2378+ OutOfRange ,
2379+ }
2380+
2381+ impl TryFrom < f64 > for SampleRand {
2382+ type Error = InvalidSampleRandError ;
2383+
2384+ fn try_from ( value : f64 ) -> Result < Self , Self :: Error > {
2385+ if !( 0.0 ..1.0 ) . contains ( & value) {
2386+ return Err ( InvalidSampleRandError :: OutOfRange ) ;
2387+ }
2388+ Ok ( Self ( value) )
23712389 }
23722390}
23732391
23742392impl std:: str:: FromStr for SampleRand {
2375- type Err = std :: num :: ParseFloatError ;
2393+ type Err = InvalidSampleRandError ;
23762394
23772395 fn from_str ( s : & str ) -> Result < Self , Self :: Err > {
2378- s. parse ( ) . map ( Self )
2396+ let x: f64 = s. parse ( ) . map_err ( InvalidSampleRandError :: InvalidFloat ) ?;
2397+ Self :: try_from ( x)
23792398 }
23802399}
23812400
23822401impl std:: fmt:: Display for SampleRand {
23832402 fn fmt ( & self , f : & mut std:: fmt:: Formatter < ' _ > ) -> std:: fmt:: Result {
2384- write ! ( f, "{:.6}" , self . 0 )
2403+ // Special case: "{:.6}" would round values greater than or equal to 0.9999995 to 1.0,
2404+ // as Rust uses [rounding half-to-even](https://doc.rust-lang.org/std/fmt/#precision).
2405+ // Round to 0.999999 instead to comply with spec.
2406+ if self . 0 >= 0.9999995 {
2407+ write ! ( f, "0.999999" )
2408+ } else {
2409+ write ! ( f, "{:.6}" , self . 0 )
2410+ }
23852411 }
23862412}
23872413
@@ -2392,8 +2418,8 @@ impl std::fmt::Display for SampleRand {
23922418/// This feature allows users to specify target sample rates for each project via the frontend instead of requiring an application redeployment.
23932419/// The backend needs additional information from the SDK to support these features, contained in
23942420/// the Dynamic Sampling Context.
2395- #[ derive( Clone , Debug , Serialize , Deserialize , PartialEq ) ]
2396- pub ( crate ) struct DynamicSamplingContext {
2421+ #[ derive( Clone , Debug , Default , Serialize , Deserialize , PartialEq ) ]
2422+ pub struct DynamicSamplingContext {
23972423 // Strictly required fields
23982424 // Still typed as optional, as when deserializing an envelope created by an older SDK they might still be missing
23992425 #[ serde( default , skip_serializing_if = "Option::is_none" ) ]
@@ -2432,3 +2458,73 @@ pub(crate) struct DynamicSamplingContext {
24322458 ) ]
24332459 org_id : Option < OrganizationId > ,
24342460}
2461+
2462+ impl DynamicSamplingContext {
2463+ /// Creates an empty Dynamic Sampling Context.
2464+ pub fn new ( ) -> Self {
2465+ Default :: default ( )
2466+ }
2467+
2468+ /// Sets the trace ID.
2469+ #[ must_use]
2470+ pub fn with_trace_id ( mut self , trace_id : TraceId ) -> Self {
2471+ self . trace_id = Some ( trace_id) ;
2472+ self
2473+ }
2474+
2475+ /// Sets the DSN public key.
2476+ #[ must_use]
2477+ pub fn with_public_key ( mut self , public_key : String ) -> Self {
2478+ self . public_key = Some ( public_key) ;
2479+ self
2480+ }
2481+
2482+ /// Sets the sample rate.
2483+ #[ must_use]
2484+ pub fn with_sample_rate ( mut self , sample_rate : f32 ) -> Self {
2485+ self . sample_rate = Some ( sample_rate) ;
2486+ self
2487+ }
2488+
2489+ /// Sets the sample random value generated by the head of trace SDK.
2490+ #[ must_use]
2491+ pub fn with_sample_rand ( mut self , sample_rand : SampleRand ) -> Self {
2492+ self . sample_rand = Some ( sample_rand) ;
2493+ self
2494+ }
2495+
2496+ /// Sets the sampled flag.
2497+ #[ must_use]
2498+ pub fn with_sampled ( mut self , sampled : bool ) -> Self {
2499+ self . sampled = Some ( sampled) ;
2500+ self
2501+ }
2502+
2503+ /// Sets the release.
2504+ #[ must_use]
2505+ pub fn with_release ( mut self , release : String ) -> Self {
2506+ self . release = Some ( release) ;
2507+ self
2508+ }
2509+
2510+ /// Sets the environment.
2511+ #[ must_use]
2512+ pub fn with_environment ( mut self , environment : String ) -> Self {
2513+ self . environment = Some ( environment) ;
2514+ self
2515+ }
2516+
2517+ /// Sets the transaction.
2518+ #[ must_use]
2519+ pub fn with_transaction ( mut self , transaction : String ) -> Self {
2520+ self . transaction = Some ( transaction) ;
2521+ self
2522+ }
2523+
2524+ /// Sets the organization ID.
2525+ #[ must_use]
2526+ pub fn with_org_id ( mut self , org_id : OrganizationId ) -> Self {
2527+ self . org_id = Some ( org_id) ;
2528+ self
2529+ }
2530+ }
0 commit comments