Improve backwards compatibility of metrics exporter

Bug: b/248979985
Change-Id: I7c472bfa9cde2f0dc7fc61599b836dd74cad70d0
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/278240
Commit-Queue: Björn Terelius <terelius@webrtc.org>
Reviewed-by: Artem Titov <titovartem@webrtc.org>
Cr-Commit-Position: refs/heads/main@{#38317}
diff --git a/api/test/metrics/print_result_proxy_metrics_exporter.cc b/api/test/metrics/print_result_proxy_metrics_exporter.cc
index 4ae32ff..1ce1e63 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 <string>
+#include <unordered_set>
 
 #include "api/array_view.h"
 #include "api/test/metrics/metric.h"
@@ -67,10 +68,40 @@
          !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<const Metric> metrics) {
+  static const std::unordered_set<std::string> 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 @@
       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 355eec0..768c794 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,
-     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<Metric>{metric1, metric2}));
+  EXPECT_TRUE(exporter.Export(std::vector<Metric>{metric1, metric2, metric3}));
   EXPECT_EQ(expected, testing::internal::GetCapturedStdout());
 }