xref: /aosp_15_r20/external/webrtc/api/test/metrics/print_result_proxy_metrics_exporter.cc (revision d9f758449e529ab9291ac668be2861e7a55c2422)
1 /*
2  *  Copyright (c) 2022 The WebRTC project authors. All Rights Reserved.
3  *
4  *  Use of this source code is governed by a BSD-style license
5  *  that can be found in the LICENSE file in the root of the source
6  *  tree. An additional intellectual property rights grant can be found
7  *  in the file PATENTS.  All contributing project authors may
8  *  be found in the AUTHORS file in the root of the source tree.
9  */
10 #include "api/test/metrics/print_result_proxy_metrics_exporter.h"
11 
12 #include <string>
13 #include <unordered_set>
14 
15 #include "api/array_view.h"
16 #include "api/test/metrics/metric.h"
17 #include "test/testsupport/perf_test.h"
18 
19 namespace webrtc {
20 namespace test {
21 namespace {
22 
ToPrintResultUnit(Unit unit)23 std::string ToPrintResultUnit(Unit unit) {
24   switch (unit) {
25     case Unit::kMilliseconds:
26       return "msBestFitFormat";
27     case Unit::kPercent:
28       return "n%";
29     case Unit::kBytes:
30       return "sizeInBytes";
31     case Unit::kKilobitsPerSecond:
32       // PrintResults prefer Chrome Perf Dashboard units, which doesn't have
33       // kpbs units, so we change the unit and value accordingly.
34       return "bytesPerSecond";
35     case Unit::kHertz:
36       return "Hz";
37     case Unit::kUnitless:
38       return "unitless";
39     case Unit::kCount:
40       return "count";
41   }
42 }
43 
ToPrintResultValue(double value,Unit unit)44 double ToPrintResultValue(double value, Unit unit) {
45   switch (unit) {
46     case Unit::kKilobitsPerSecond:
47       // PrintResults prefer Chrome Perf Dashboard units, which doesn't have
48       // kpbs units, so we change the unit and value accordingly.
49       return value * 1000 / 8;
50     default:
51       return value;
52   }
53 }
54 
ToPrintResultImproveDirection(ImprovementDirection direction)55 ImproveDirection ToPrintResultImproveDirection(ImprovementDirection direction) {
56   switch (direction) {
57     case ImprovementDirection::kBiggerIsBetter:
58       return ImproveDirection::kBiggerIsBetter;
59     case ImprovementDirection::kNeitherIsBetter:
60       return ImproveDirection::kNone;
61     case ImprovementDirection::kSmallerIsBetter:
62       return ImproveDirection::kSmallerIsBetter;
63   }
64 }
65 
IsEmpty(const Metric::Stats & stats)66 bool IsEmpty(const Metric::Stats& stats) {
67   return !stats.mean.has_value() && !stats.stddev.has_value() &&
68          !stats.min.has_value() && !stats.max.has_value();
69 }
70 
NameEndsWithConnected(const std::string & name)71 bool NameEndsWithConnected(const std::string& name) {
72   static const std::string suffix = "_connected";
73   return name.size() >= suffix.size() &&
74          0 == name.compare(name.size() - suffix.size(), suffix.size(), suffix);
75 }
76 
77 }  // namespace
78 
Export(rtc::ArrayView<const Metric> metrics)79 bool PrintResultProxyMetricsExporter::Export(
80     rtc::ArrayView<const Metric> metrics) {
81   static const std::unordered_set<std::string> per_call_metrics{
82       "actual_encode_bitrate",
83       "encode_frame_rate",
84       "harmonic_framerate",
85       "max_skipped",
86       "min_psnr_dB",
87       "retransmission_bitrate",
88       "sent_packets_loss",
89       "transmission_bitrate",
90       "dropped_frames",
91       "frames_in_flight",
92       "rendered_frames",
93       "average_receive_rate",
94       "average_send_rate",
95       "bytes_discarded_no_receiver",
96       "bytes_received",
97       "bytes_sent",
98       "packets_discarded_no_receiver",
99       "packets_received",
100       "packets_sent",
101       "payload_bytes_received",
102       "payload_bytes_sent",
103       "cpu_usage"};
104 
105   for (const Metric& metric : metrics) {
106     if (metric.time_series.samples.empty() && IsEmpty(metric.stats)) {
107       // If there were no data collected for the metric it is expected that 0
108       // will be exported, so add 0 to the samples.
109       PrintResult(metric.name, /*modifier=*/"", metric.test_case,
110                   ToPrintResultValue(0, metric.unit),
111                   ToPrintResultUnit(metric.unit), /*important=*/false,
112                   ToPrintResultImproveDirection(metric.improvement_direction));
113       continue;
114     }
115 
116     if (metric.time_series.samples.empty()) {
117       PrintResultMeanAndError(
118           metric.name, /*modifier=*/"", metric.test_case,
119           ToPrintResultValue(*metric.stats.mean, metric.unit),
120           ToPrintResultValue(*metric.stats.stddev, metric.unit),
121           ToPrintResultUnit(metric.unit),
122           /*important=*/false,
123           ToPrintResultImproveDirection(metric.improvement_direction));
124       continue;
125     }
126 
127     if (metric.time_series.samples.size() == 1lu &&
128         (per_call_metrics.count(metric.name) > 0 ||
129          NameEndsWithConnected(metric.name))) {
130       // Increase backwards compatibility for 1 value use case.
131       PrintResult(
132           metric.name, /*modifier=*/"", metric.test_case,
133           ToPrintResultValue(metric.time_series.samples[0].value, metric.unit),
134           ToPrintResultUnit(metric.unit), /*important=*/false,
135           ToPrintResultImproveDirection(metric.improvement_direction));
136       continue;
137     }
138 
139     SamplesStatsCounter counter;
140     for (size_t i = 0; i < metric.time_series.samples.size(); ++i) {
141       counter.AddSample(SamplesStatsCounter::StatsSample{
142           .value = ToPrintResultValue(metric.time_series.samples[i].value,
143                                       metric.unit),
144           .time = metric.time_series.samples[i].timestamp,
145           .metadata = metric.time_series.samples[i].sample_metadata});
146     }
147 
148     PrintResult(metric.name, /*modifier=*/"", metric.test_case, counter,
149                 ToPrintResultUnit(metric.unit),
150                 /*important=*/false,
151                 ToPrintResultImproveDirection(metric.improvement_direction));
152   }
153   return true;
154 }
155 
156 }  // namespace test
157 }  // namespace webrtc
158