diff --git a/relay-profiling/src/measurements.rs b/relay-profiling/src/measurements.rs index 209992c57e..98fdeb633e 100644 --- a/relay-profiling/src/measurements.rs +++ b/relay-profiling/src/measurements.rs @@ -9,14 +9,24 @@ pub struct Measurement { } #[derive(Debug, Serialize, Deserialize, Clone)] -pub struct MeasurementValue { - // nanoseconds elapsed since the start of the profile - #[serde(deserialize_with = "deserialize_number_from_string")] - elapsed_since_start_ns: u64, +#[serde(untagged)] +pub enum MeasurementValue { + Default { + // nanoseconds elapsed since the start of the profile + #[serde(deserialize_with = "deserialize_number_from_string")] + elapsed_since_start_ns: u64, - // Android 6.8.0 sends a string instead of a float64 so we need to accept both - #[serde(deserialize_with = "deserialize_number_from_string")] - value: f64, + // Android 6.8.0 sends a string instead of a float64 so we need to accept both + #[serde(deserialize_with = "deserialize_number_from_string")] + value: f64, + }, + SampleV2 { + // UNIX timestamp in seconds as a float + timestamp: f64, + + #[serde(deserialize_with = "deserialize_number_from_string")] + value: f64, + }, } #[derive(Clone, Debug, Serialize, Deserialize)] @@ -36,12 +46,25 @@ pub enum MeasurementUnit { mod tests { use super::*; + #[test] + fn test_roundtrip() { + let raw_value = r#"{"elapsed_since_start_ns":1234567890,"value":1234.56789}"#; + let parsed_value = serde_json::from_str::(raw_value); + assert!(parsed_value.is_ok()); + let value = parsed_value.unwrap(); + let encoded_value = serde_json::to_string(&value).unwrap(); + assert_eq!(encoded_value, raw_value); + } + #[test] fn test_value_as_float() { let measurement_json = r#"{"elapsed_since_start_ns":1234567890,"value":1234.56789}"#; let measurement = serde_json::from_str::(measurement_json); assert!(measurement.is_ok()); - assert_eq!(measurement.unwrap().value, 1234.56789); + match measurement.unwrap() { + MeasurementValue::Default { value, .. } => assert_eq!(value, 1234.56789), + _ => panic!("measurement wasn't properly decoded"), + } } #[test] @@ -49,7 +72,10 @@ mod tests { let measurement_json = r#"{"elapsed_since_start_ns":1234567890,"value":"1234.56789"}"#; let measurement = serde_json::from_str::(measurement_json); assert!(measurement.is_ok()); - assert_eq!(measurement.unwrap().value, 1234.56789); + match measurement.unwrap() { + MeasurementValue::Default { value, .. } => assert_eq!(value, 1234.56789), + _ => panic!("measurement wasn't properly decoded"), + } } #[test] @@ -57,7 +83,10 @@ mod tests { let measurement_json = r#"{"elapsed_since_start_ns":1234567890,"value":"1e3"}"#; let measurement = serde_json::from_str::(measurement_json); assert!(measurement.is_ok()); - assert_eq!(measurement.unwrap().value, 1e3f64); + match measurement.unwrap() { + MeasurementValue::Default { value, .. } => assert_eq!(value, 1e3f64), + _ => panic!("measurement wasn't properly decoded"), + } } #[test] @@ -65,7 +94,10 @@ mod tests { let measurement_json = r#"{"elapsed_since_start_ns":1234567890,"value":"+Infinity"}"#; let measurement = serde_json::from_str::(measurement_json); assert!(measurement.is_ok()); - assert_eq!(measurement.unwrap().value, f64::INFINITY); + match measurement.unwrap() { + MeasurementValue::Default { value, .. } => assert_eq!(value, f64::INFINITY), + _ => panic!("measurement wasn't properly decoded"), + } } #[test] @@ -73,7 +105,10 @@ mod tests { let measurement_json = r#"{"elapsed_since_start_ns":1234567890,"value":1e3}"#; let measurement = serde_json::from_str::(measurement_json); assert!(measurement.is_ok()); - assert_eq!(measurement.unwrap().value, 1e3f64); + match measurement.unwrap() { + MeasurementValue::Default { value, .. } => assert_eq!(value, 1e3f64), + _ => panic!("measurement wasn't properly decoded"), + } } #[test] @@ -82,4 +117,11 @@ mod tests { let measurement = serde_json::from_str::(measurement_json); assert!(measurement.is_err()); } + + #[test] + fn test_with_timestamp_only() { + let measurement_json = r#"{"timestamp":1717161756.408,"value":10.3}"#; + let measurement = serde_json::from_str::(measurement_json); + assert!(measurement.is_ok()); + } }