diff --git a/api/test/metrics/print_result_proxy_metrics_exporter.cc b/api/test/metrics/print_result_proxy_metrics_exporter.cc index 4ae32fffec..1ce1e63892 100644 --- a/api/test/metrics/print_result_proxy_metrics_exporter.cc +++ b/api/test/metrics/print_result_proxy_metrics_exporter.cc @@ -10,6 +10,7 @@ #include "api/test/metrics/print_result_proxy_metrics_exporter.h" #include +#include #include "api/array_view.h" #include "api/test/metrics/metric.h" @@ -67,10 +68,40 @@ bool IsEmpty(const Metric::Stats& stats) { !stats.min.has_value() && !stats.max.has_value(); } +bool NameEndsWithConnected(const std::string& name) { + static const std::string suffix = "_connected"; + return name.size() >= suffix.size() && + 0 == name.compare(name.size() - suffix.size(), suffix.size(), suffix); +} + } // namespace bool PrintResultProxyMetricsExporter::Export( rtc::ArrayView metrics) { + static const std::unordered_set per_call_metrics{ + "actual_encode_bitrate", + "encode_frame_rate", + "harmonic_framerate", + "max_skipped", + "min_psnr_dB", + "retransmission_bitrate", + "sent_packets_loss", + "transmission_bitrate", + "dropped_frames", + "frames_in_flight", + "rendered_frames", + "average_receive_rate", + "average_send_rate", + "bytes_discarded_no_receiver", + "bytes_received", + "bytes_sent", + "packets_discarded_no_receiver", + "packets_received", + "packets_sent", + "payload_bytes_received", + "payload_bytes_sent", + "cpu_usage"}; + for (const Metric& metric : metrics) { if (metric.time_series.samples.empty() && IsEmpty(metric.stats)) { // If there were no data collected for the metric it is expected that 0 @@ -93,7 +124,9 @@ bool PrintResultProxyMetricsExporter::Export( continue; } - if (metric.time_series.samples.size() == 1lu) { + if (metric.time_series.samples.size() == 1lu && + (per_call_metrics.count(metric.name) > 0 || + NameEndsWithConnected(metric.name))) { // Increase backwards compatibility for 1 value use case. PrintResult( metric.name, /*modifier=*/"", metric.test_case, diff --git a/api/test/metrics/print_result_proxy_metrics_exporter_test.cc b/api/test/metrics/print_result_proxy_metrics_exporter_test.cc index 355eec0d4f..768c794b40 100644 --- a/api/test/metrics/print_result_proxy_metrics_exporter_test.cc +++ b/api/test/metrics/print_result_proxy_metrics_exporter_test.cc @@ -71,36 +71,51 @@ TEST(PrintResultProxyMetricsExporterTest, } TEST(PrintResultProxyMetricsExporterTest, - ExportMetricsWithTimeSeriesOfSingleValueFormatCorrect) { + ExportMetricsTimeSeriesOfSingleValueBackwardCompatibleFormat) { + // This should be printed as {mean, stddev} despite only being a single data + // point. Metric metric1{ - .name = "test_metric1", - .unit = Unit::kMilliseconds, + .name = "available_send_bandwidth", + .unit = Unit::kKilobitsPerSecond, .improvement_direction = ImprovementDirection::kBiggerIsBetter, - .test_case = "test_case_name1", + .test_case = "test_case/alice", + .metric_metadata = DefaultMetadata(), + .time_series = Metric::TimeSeries{.samples = std::vector{Sample(1000)}}, + .stats = Metric::Stats{ + .mean = 1000.0, .stddev = 0.0, .min = 1000.0, .max = 1000.0}}; + // This is a per-call metric that shouldn't have a stddev estimate. + Metric metric2{ + .name = "min_psnr_dB", + .unit = Unit::kUnitless, + .improvement_direction = ImprovementDirection::kBiggerIsBetter, + .test_case = "test_case/alice-video", .metric_metadata = DefaultMetadata(), .time_series = Metric::TimeSeries{.samples = std::vector{Sample(10)}}, .stats = Metric::Stats{.mean = 10.0, .stddev = 0.0, .min = 10.0, .max = 10.0}}; - Metric metric2{ - .name = "test_metric2", - .unit = Unit::kKilobitsPerSecond, - .improvement_direction = ImprovementDirection::kSmallerIsBetter, - .test_case = "test_case_name2", + // This is a per-call metric that shouldn't have a stddev estimate. + Metric metric3{ + .name = "alice_connected", + .unit = Unit::kUnitless, + .improvement_direction = ImprovementDirection::kBiggerIsBetter, + .test_case = "test_case", .metric_metadata = DefaultMetadata(), - .time_series = Metric::TimeSeries{.samples = std::vector{Sample(20)}}, + .time_series = Metric::TimeSeries{.samples = std::vector{Sample(1)}}, .stats = - Metric::Stats{.mean = 20.0, .stddev = 0.0, .min = 20.0, .max = 20.0}}; + Metric::Stats{.mean = 1.0, .stddev = 0.0, .min = 1.0, .max = 1.0}}; testing::internal::CaptureStdout(); PrintResultProxyMetricsExporter exporter; std::string expected = - "RESULT test_metric1: test_case_name1= 10 " - "msBestFitFormat_biggerIsBetter\n" - "RESULT test_metric2: test_case_name2= 2500 " - "bytesPerSecond_smallerIsBetter\n"; + "RESULT available_send_bandwidth: test_case/alice= {125000,0} " + "bytesPerSecond_biggerIsBetter\n" + "RESULT min_psnr_dB: test_case/alice-video= 10 " + "unitless_biggerIsBetter\n" + "RESULT alice_connected: test_case= 1 " + "unitless_biggerIsBetter\n"; - EXPECT_TRUE(exporter.Export(std::vector{metric1, metric2})); + EXPECT_TRUE(exporter.Export(std::vector{metric1, metric2, metric3})); EXPECT_EQ(expected, testing::internal::GetCapturedStdout()); }