Skip to content

Commit d4467b6

Browse files
authored
feat: allow sample_rate to also be a float type (#4181)
This PR makes the `sample_rate` parsing more lenient so it allows both `string` and `float` types. The goal of this change is to mitigate bugs from SDKs which accidentally send the `sample_rate` field as float
1 parent e9213e8 commit d4467b6

File tree

2 files changed

+54
-6
lines changed

2 files changed

+54
-6
lines changed

CHANGELOG.md

+2-2
Original file line numberDiff line numberDiff line change
@@ -2,15 +2,15 @@
22

33
## Unreleased
44

5-
**Bug Fixes:**
5+
**Bug Fixes**
66

77
- Allow profile chunks without release. ([#4155](https://github.com/getsentry/relay/pull/4155))
88
- Add validation for timestamps sent from the future. ([#4163](https://github.com/getsentry/relay/pull/4163))
99

10-
1110
**Features:**
1211

1312
- Retain empty string values in `span.data` and `event.contexts.trace.data`. ([#4174](https://github.com/getsentry/relay/pull/4174))
13+
- Allow `sample_rate` to be float type when deserializing `DynamicSamplingContext`. ([#4181](https://github.com/getsentry/relay/pull/4181))
1414

1515
**Internal:**
1616

relay-sampling/src/dsc.rs

+52-4
Original file line numberDiff line numberDiff line change
@@ -149,13 +149,24 @@ mod sample_rate_as_string {
149149
where
150150
D: serde::Deserializer<'de>,
151151
{
152-
let value = match Option::<Cow<'_, str>>::deserialize(deserializer)? {
152+
#[derive(Debug, Clone, Deserialize)]
153+
#[serde(untagged)]
154+
enum StringOrFloat<'a> {
155+
String(#[serde(borrow)] Cow<'a, str>),
156+
Float(f64),
157+
}
158+
159+
let value = match Option::<StringOrFloat>::deserialize(deserializer)? {
153160
Some(value) => value,
154161
None => return Ok(None),
155162
};
156163

157-
let parsed_value =
158-
serde_json::from_str(&value).map_err(|e| serde::de::Error::custom(e.to_string()))?;
164+
let parsed_value = match value {
165+
StringOrFloat::Float(f) => f,
166+
StringOrFloat::String(s) => {
167+
serde_json::from_str(&s).map_err(serde::de::Error::custom)?
168+
}
169+
};
159170

160171
if parsed_value < 0.0 {
161172
return Err(serde::de::Error::custom("sample rate cannot be negative"));
@@ -387,7 +398,44 @@ mod tests {
387398
"sample_rate": 0.1
388399
}
389400
"#;
390-
serde_json::from_str::<DynamicSamplingContext>(json).unwrap_err();
401+
let dsc = serde_json::from_str::<DynamicSamplingContext>(json).unwrap();
402+
insta::assert_ron_snapshot!(dsc, @r#"
403+
{
404+
"trace_id": "00000000-0000-0000-0000-000000000000",
405+
"public_key": "abd0f232775f45feab79864e580d160b",
406+
"release": None,
407+
"environment": None,
408+
"transaction": None,
409+
"sample_rate": "0.1",
410+
"user_id": "hello",
411+
"replay_id": None,
412+
}
413+
"#);
414+
}
415+
416+
#[test]
417+
fn test_parse_sample_rate_integer() {
418+
let json = r#"
419+
{
420+
"trace_id": "00000000-0000-0000-0000-000000000000",
421+
"public_key": "abd0f232775f45feab79864e580d160b",
422+
"user_id": "hello",
423+
"sample_rate": "1"
424+
}
425+
"#;
426+
let dsc = serde_json::from_str::<DynamicSamplingContext>(json).unwrap();
427+
insta::assert_ron_snapshot!(dsc, @r#"
428+
{
429+
"trace_id": "00000000-0000-0000-0000-000000000000",
430+
"public_key": "abd0f232775f45feab79864e580d160b",
431+
"release": None,
432+
"environment": None,
433+
"transaction": None,
434+
"sample_rate": "1.0",
435+
"user_id": "hello",
436+
"replay_id": None,
437+
}
438+
"#);
391439
}
392440

393441
#[test]

0 commit comments

Comments
 (0)