relay_profiling/
measurements.rs1use serde::{Deserialize, Serialize};
2
3use crate::utils::deserialize_number_from_string;
4
5#[derive(Debug, Serialize, Deserialize, Clone)]
6pub struct LegacyMeasurement {
7 unit: MeasurementUnit,
8 values: Vec<LegacyMeasurementValue>,
9}
10
11#[derive(Debug, Serialize, Deserialize, Clone)]
12pub struct ChunkMeasurement {
13 unit: MeasurementUnit,
14 values: Vec<ChunkMeasurementValue>,
15}
16
17#[derive(Debug, Serialize, Deserialize, Clone)]
18pub struct LegacyMeasurementValue {
19 #[serde(deserialize_with = "deserialize_number_from_string")]
21 elapsed_since_start_ns: u64,
22
23 #[serde(deserialize_with = "deserialize_number_from_string")]
25 value: f64,
26}
27
28#[derive(Debug, Serialize, Deserialize, Clone)]
29pub struct ChunkMeasurementValue {
30 timestamp: f64,
32
33 #[serde(deserialize_with = "deserialize_number_from_string")]
34 value: f64,
35}
36
37#[derive(Clone, Debug, Serialize, Deserialize)]
38#[serde(rename_all = "snake_case")]
39pub enum MeasurementUnit {
40 #[serde(alias = "ns")]
41 Nanosecond,
42 #[serde(alias = "hz")]
43 Hertz,
44 Byte,
45 Percent,
46 #[serde(alias = "nj")]
47 Nanojoule,
48}
49
50#[cfg(test)]
51mod tests {
52 use super::{ChunkMeasurementValue, LegacyMeasurementValue};
53
54 #[test]
55 fn test_roundtrip() {
56 let raw_value = r#"{"elapsed_since_start_ns":1234567890,"value":1234.56789}"#;
57 let parsed_value = serde_json::from_str::<LegacyMeasurementValue>(raw_value);
58 assert!(parsed_value.is_ok());
59 let value = parsed_value.unwrap();
60 let encoded_value = serde_json::to_string(&value).unwrap();
61 assert_eq!(encoded_value, raw_value);
62 }
63
64 #[test]
65 fn test_value_as_float() {
66 let measurement_json = r#"{"elapsed_since_start_ns":1234567890,"value":1234.56789}"#;
67 let measurement = serde_json::from_str::<LegacyMeasurementValue>(measurement_json);
68 assert!(measurement.is_ok());
69 assert_eq!(measurement.unwrap().value, 1234.56789);
70 }
71
72 #[test]
73 fn test_value_as_string() {
74 let measurement_json = r#"{"elapsed_since_start_ns":1234567890,"value":"1234.56789"}"#;
75 let measurement = serde_json::from_str::<LegacyMeasurementValue>(measurement_json);
76 assert!(measurement.is_ok());
77 assert_eq!(measurement.unwrap().value, 1234.56789);
78 }
79
80 #[test]
81 fn test_value_as_string_scientific_notation() {
82 let measurement_json = r#"{"elapsed_since_start_ns":1234567890,"value":"1e3"}"#;
83 let measurement = serde_json::from_str::<LegacyMeasurementValue>(measurement_json);
84 assert!(measurement.is_ok());
85 assert_eq!(measurement.unwrap().value, 1e3f64);
86 }
87
88 #[test]
89 fn test_value_as_string_infinity() {
90 let measurement_json = r#"{"elapsed_since_start_ns":1234567890,"value":"+Infinity"}"#;
91 let measurement = serde_json::from_str::<LegacyMeasurementValue>(measurement_json);
92 assert!(measurement.is_ok());
93 assert_eq!(measurement.unwrap().value, f64::INFINITY);
94 }
95
96 #[test]
97 fn test_value_as_float_scientific_notation() {
98 let measurement_json = r#"{"elapsed_since_start_ns":1234567890,"value":1e3}"#;
99 let measurement = serde_json::from_str::<LegacyMeasurementValue>(measurement_json);
100 assert!(measurement.is_ok());
101 assert_eq!(measurement.unwrap().value, 1e3f64);
102 }
103
104 #[test]
105 fn test_value_as_float_infinity() {
106 let measurement_json = r#"{"elapsed_since_start_ns":1234567890,"value":+Infinity}"#;
107 let measurement = serde_json::from_str::<LegacyMeasurementValue>(measurement_json);
108 assert!(measurement.is_err());
109 }
110
111 #[test]
112 fn test_with_timestamp_only() {
113 let measurement_json = r#"{"timestamp":1717161756.408,"value":10.3}"#;
114 let measurement = serde_json::from_str::<ChunkMeasurementValue>(measurement_json);
115 assert!(measurement.is_ok());
116 assert_eq!(measurement.unwrap().value, 10.3);
117 }
118}