Skip to content

Commit 03d5e9a

Browse files
committed
add tests for NaN
1 parent c811133 commit 03d5e9a

File tree

1 file changed

+181
-0
lines changed

1 file changed

+181
-0
lines changed

opentelemetry-proto/tests/json_serde.rs

Lines changed: 181 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1503,4 +1503,185 @@ mod json_serde {
15031503
}
15041504
}
15051505
}
1506+
#[cfg(feature = "metrics")]
1507+
mod metrics_with_nan {
1508+
use super::*;
1509+
use opentelemetry_proto::tonic::metrics::v1::summary_data_point::ValueAtQuantile;
1510+
use opentelemetry_proto::tonic::metrics::v1::Summary;
1511+
use opentelemetry_proto::tonic::metrics::v1::SummaryDataPoint;
1512+
1513+
fn value_with_nan() -> ExportMetricsServiceRequest {
1514+
ExportMetricsServiceRequest {
1515+
resource_metrics: vec![ResourceMetrics {
1516+
resource: Some(Resource {
1517+
attributes: vec![KeyValue {
1518+
key: String::from("service.name"),
1519+
value: None,
1520+
}],
1521+
dropped_attributes_count: 0,
1522+
}),
1523+
scope_metrics: vec![ScopeMetrics {
1524+
scope: None,
1525+
metrics: vec![Metric {
1526+
name: String::from("example_metric"),
1527+
description: String::from("A sample metric with NaN values"),
1528+
unit: String::from("1"),
1529+
metadata: vec![],
1530+
data: Some(
1531+
opentelemetry_proto::tonic::metrics::v1::metric::Data::Summary(
1532+
Summary {
1533+
data_points: vec![SummaryDataPoint {
1534+
attributes: vec![],
1535+
start_time_unix_nano: 0,
1536+
time_unix_nano: 0,
1537+
count: 100,
1538+
sum: 500.0,
1539+
quantile_values: vec![
1540+
ValueAtQuantile {
1541+
quantile: 0.5,
1542+
value: f64::NAN,
1543+
},
1544+
ValueAtQuantile {
1545+
quantile: 0.9,
1546+
value: f64::NAN,
1547+
},
1548+
],
1549+
flags: 0,
1550+
}],
1551+
},
1552+
),
1553+
),
1554+
}],
1555+
schema_url: String::new(),
1556+
}],
1557+
schema_url: String::new(),
1558+
}],
1559+
}
1560+
}
1561+
1562+
// language=json
1563+
const CANONICAL_WITH_NAN: &str = r#"{
1564+
"resourceMetrics": [
1565+
{
1566+
"resource": {
1567+
"attributes": [
1568+
{
1569+
"key": "service.name",
1570+
"value": null
1571+
}
1572+
],
1573+
"droppedAttributesCount": 0
1574+
},
1575+
"scopeMetrics": [
1576+
{
1577+
"scope": null,
1578+
"metrics": [
1579+
{
1580+
"name": "example_metric",
1581+
"description": "A sample metric with NaN values",
1582+
"unit": "1",
1583+
"metadata": [],
1584+
"summary": {
1585+
"dataPoints": [
1586+
{
1587+
"attributes": [],
1588+
"startTimeUnixNano": "0",
1589+
"timeUnixNano": "0",
1590+
"count": "100",
1591+
"sum": 500.0,
1592+
"quantileValues": [
1593+
{
1594+
"quantile": 0.5,
1595+
"value": "NaN"
1596+
},
1597+
{
1598+
"quantile": 0.9,
1599+
"value": "NaN"
1600+
}
1601+
],
1602+
"flags": 0
1603+
}
1604+
]
1605+
}
1606+
}
1607+
],
1608+
"schemaUrl": ""
1609+
}
1610+
],
1611+
"schemaUrl": ""
1612+
}
1613+
]
1614+
}"#;
1615+
1616+
#[test]
1617+
fn serialize_with_nan() {
1618+
let input: ExportMetricsServiceRequest = value_with_nan();
1619+
1620+
// Serialize the structure to JSON
1621+
let actual = serde_json::to_string_pretty(&input).expect("serialization must succeed");
1622+
1623+
// Normalize both the actual and expected JSON for comparison
1624+
let actual_value: serde_json::Value =
1625+
serde_json::from_str(&actual).expect("valid JSON");
1626+
let expected_value: serde_json::Value =
1627+
serde_json::from_str(CANONICAL_WITH_NAN).expect("valid JSON");
1628+
1629+
// Compare the normalized JSON values
1630+
assert_eq!(actual_value, expected_value);
1631+
}
1632+
1633+
#[test]
1634+
fn deserialize_with_nan() {
1635+
let actual: ExportMetricsServiceRequest =
1636+
serde_json::from_str(CANONICAL_WITH_NAN).expect("deserialization must succeed");
1637+
1638+
// Ensure the deserialized structure matches the expected values
1639+
assert_eq!(actual.resource_metrics.len(), 1);
1640+
1641+
let resource_metric = &actual.resource_metrics[0];
1642+
assert_eq!(
1643+
resource_metric.resource.as_ref().unwrap().attributes.len(),
1644+
1
1645+
);
1646+
assert_eq!(
1647+
resource_metric.resource.as_ref().unwrap().attributes[0].key,
1648+
"service.name"
1649+
);
1650+
assert!(resource_metric.resource.as_ref().unwrap().attributes[0]
1651+
.value
1652+
.is_none());
1653+
1654+
assert_eq!(resource_metric.scope_metrics.len(), 1);
1655+
1656+
let scope_metric = &resource_metric.scope_metrics[0];
1657+
assert!(scope_metric.scope.is_none());
1658+
assert_eq!(scope_metric.metrics.len(), 1);
1659+
1660+
let metric = &scope_metric.metrics[0];
1661+
assert_eq!(metric.name, "example_metric");
1662+
assert_eq!(metric.description, "A sample metric with NaN values");
1663+
assert_eq!(metric.unit, "1");
1664+
1665+
if let Some(opentelemetry_proto::tonic::metrics::v1::metric::Data::Summary(summary)) =
1666+
&metric.data
1667+
{
1668+
assert_eq!(summary.data_points.len(), 1);
1669+
1670+
let data_point = &summary.data_points[0];
1671+
assert_eq!(data_point.attributes.len(), 0);
1672+
assert_eq!(data_point.start_time_unix_nano, 0);
1673+
assert_eq!(data_point.time_unix_nano, 0);
1674+
assert_eq!(data_point.count, 100);
1675+
assert_eq!(data_point.sum, 500.0);
1676+
1677+
assert_eq!(data_point.quantile_values.len(), 2);
1678+
1679+
// Verify that quantile values are NaN
1680+
assert!(data_point.quantile_values[0].value.is_nan());
1681+
assert!(data_point.quantile_values[1].value.is_nan());
1682+
} else {
1683+
panic!("Expected metric data to be of type Summary");
1684+
}
1685+
}
1686+
}
15061687
}

0 commit comments

Comments
 (0)