Skip to content

Commit ed82d78

Browse files
authored
Add a special test for synchronous instruments (cumulative aggregation) (#2010)
1 parent 6c3cffb commit ed82d78

File tree

1 file changed

+142
-0
lines changed
  • opentelemetry-sdk/src/metrics

1 file changed

+142
-0
lines changed

opentelemetry-sdk/src/metrics/mod.rs

+142
Original file line numberDiff line numberDiff line change
@@ -1251,6 +1251,140 @@ mod tests {
12511251
counter_multithreaded_aggregation_helper(Temporality::Cumulative);
12521252
}
12531253

1254+
#[tokio::test(flavor = "multi_thread", worker_threads = 1)]
1255+
async fn synchronous_instruments_cumulative_with_gap_in_measurements() {
1256+
// Run this test with stdout enabled to see output.
1257+
// cargo test synchronous_instruments_cumulative_with_gap_in_measurements --features=testing -- --nocapture
1258+
1259+
synchronous_instruments_cumulative_with_gap_in_measurements_helper("counter");
1260+
synchronous_instruments_cumulative_with_gap_in_measurements_helper("updown_counter");
1261+
synchronous_instruments_cumulative_with_gap_in_measurements_helper("histogram");
1262+
1263+
/* Synchronous Gauge has an aggregation bug. Uncomment the code below to run the test for gauge
1264+
once this issue is fixed: https://github.com/open-telemetry/opentelemetry-rust/issues/1975
1265+
*/
1266+
1267+
// synchronous_instruments_cumulative_with_gap_in_measurements_helper("gauge");
1268+
}
1269+
1270+
fn synchronous_instruments_cumulative_with_gap_in_measurements_helper(
1271+
instrument_name: &'static str,
1272+
) {
1273+
let mut test_context = TestContext::new(Temporality::Cumulative);
1274+
let attributes = &[KeyValue::new("key1", "value1")];
1275+
1276+
// Create instrument and emit measurements
1277+
match instrument_name {
1278+
"counter" => {
1279+
let counter = test_context.meter().u64_counter("test_counter").init();
1280+
counter.add(5, &[]);
1281+
counter.add(10, attributes);
1282+
}
1283+
"updown_counter" => {
1284+
let updown_counter = test_context
1285+
.meter()
1286+
.i64_up_down_counter("test_updowncounter")
1287+
.init();
1288+
updown_counter.add(15, &[]);
1289+
updown_counter.add(20, attributes);
1290+
}
1291+
"histogram" => {
1292+
let histogram = test_context.meter().u64_histogram("test_histogram").init();
1293+
histogram.record(25, &[]);
1294+
histogram.record(30, attributes);
1295+
}
1296+
"gauge" => {
1297+
let gauge = test_context.meter().u64_gauge("test_gauge").init();
1298+
gauge.record(35, &[]);
1299+
gauge.record(40, attributes);
1300+
}
1301+
_ => panic!("Incorrect instrument kind provided"),
1302+
};
1303+
1304+
test_context.flush_metrics();
1305+
1306+
// Test the first export
1307+
assert_correct_export(&mut test_context, instrument_name);
1308+
1309+
// Reset and export again without making any measurements
1310+
test_context.reset_metrics();
1311+
1312+
test_context.flush_metrics();
1313+
1314+
// Test that latest export has the same data as the previous one
1315+
assert_correct_export(&mut test_context, instrument_name);
1316+
1317+
fn assert_correct_export(test_context: &mut TestContext, instrument_name: &'static str) {
1318+
match instrument_name {
1319+
"counter" => {
1320+
let counter_data =
1321+
test_context.get_aggregation::<data::Sum<u64>>("test_counter", None);
1322+
assert_eq!(counter_data.data_points.len(), 2);
1323+
let zero_attribute_datapoint =
1324+
find_datapoint_with_no_attributes(&counter_data.data_points)
1325+
.expect("datapoint with no attributes expected");
1326+
assert_eq!(zero_attribute_datapoint.value, 5);
1327+
let data_point1 =
1328+
find_datapoint_with_key_value(&counter_data.data_points, "key1", "value1")
1329+
.expect("datapoint with key1=value1 expected");
1330+
assert_eq!(data_point1.value, 10);
1331+
}
1332+
"updown_counter" => {
1333+
let updown_counter_data =
1334+
test_context.get_aggregation::<data::Sum<i64>>("test_updowncounter", None);
1335+
assert_eq!(updown_counter_data.data_points.len(), 2);
1336+
let zero_attribute_datapoint =
1337+
find_datapoint_with_no_attributes(&updown_counter_data.data_points)
1338+
.expect("datapoint with no attributes expected");
1339+
assert_eq!(zero_attribute_datapoint.value, 15);
1340+
let data_point1 = find_datapoint_with_key_value(
1341+
&updown_counter_data.data_points,
1342+
"key1",
1343+
"value1",
1344+
)
1345+
.expect("datapoint with key1=value1 expected");
1346+
assert_eq!(data_point1.value, 20);
1347+
}
1348+
"histogram" => {
1349+
let histogram_data = test_context
1350+
.get_aggregation::<data::Histogram<u64>>("test_histogram", None);
1351+
assert_eq!(histogram_data.data_points.len(), 2);
1352+
let zero_attribute_datapoint =
1353+
find_histogram_datapoint_with_no_attributes(&histogram_data.data_points)
1354+
.expect("datapoint with no attributes expected");
1355+
assert_eq!(zero_attribute_datapoint.count, 1);
1356+
assert_eq!(zero_attribute_datapoint.sum, 25);
1357+
assert_eq!(zero_attribute_datapoint.min, Some(25));
1358+
assert_eq!(zero_attribute_datapoint.max, Some(25));
1359+
let data_point1 = find_histogram_datapoint_with_key_value(
1360+
&histogram_data.data_points,
1361+
"key1",
1362+
"value1",
1363+
)
1364+
.expect("datapoint with key1=value1 expected");
1365+
assert_eq!(data_point1.count, 1);
1366+
assert_eq!(data_point1.sum, 30);
1367+
assert_eq!(data_point1.min, Some(30));
1368+
assert_eq!(data_point1.max, Some(30));
1369+
}
1370+
"gauge" => {
1371+
let gauge_data =
1372+
test_context.get_aggregation::<data::Gauge<u64>>("test_gauge", None);
1373+
assert_eq!(gauge_data.data_points.len(), 2);
1374+
let zero_attribute_datapoint =
1375+
find_datapoint_with_no_attributes(&gauge_data.data_points)
1376+
.expect("datapoint with no attributes expected");
1377+
assert_eq!(zero_attribute_datapoint.value, 35);
1378+
let data_point1 =
1379+
find_datapoint_with_key_value(&gauge_data.data_points, "key1", "value1")
1380+
.expect("datapoint with key1=value1 expected");
1381+
assert_eq!(data_point1.value, 40);
1382+
}
1383+
_ => panic!("Incorrect instrument kind provided"),
1384+
}
1385+
}
1386+
}
1387+
12541388
fn counter_multithreaded_aggregation_helper(temporality: Temporality) {
12551389
// Arrange
12561390
let mut test_context = TestContext::new(temporality);
@@ -1716,6 +1850,14 @@ mod tests {
17161850
})
17171851
}
17181852

1853+
fn find_histogram_datapoint_with_no_attributes<T>(
1854+
data_points: &[HistogramDataPoint<T>],
1855+
) -> Option<&HistogramDataPoint<T>> {
1856+
data_points
1857+
.iter()
1858+
.find(|&datapoint| datapoint.attributes.is_empty())
1859+
}
1860+
17191861
fn find_scope_metric<'a>(
17201862
metrics: &'a [ScopeMetrics],
17211863
name: &'a str,

0 commit comments

Comments
 (0)