metrics_accumulator.cc (4198B)
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/metrics_accumulator.h" 11 12 #include <map> 13 #include <string> 14 #include <utility> 15 #include <vector> 16 17 #include "absl/strings/string_view.h" 18 #include "api/numerics/samples_stats_counter.h" 19 #include "api/test/metrics/metric.h" 20 #include "api/units/timestamp.h" 21 #include "rtc_base/synchronization/mutex.h" 22 23 namespace webrtc { 24 namespace test { 25 namespace { 26 27 Metric::Stats ToStats(const SamplesStatsCounter& values) { 28 if (values.IsEmpty()) { 29 return Metric::Stats(); 30 } 31 return Metric::Stats{.mean = values.GetAverage(), 32 .stddev = values.GetStandardDeviation(), 33 .min = values.GetMin(), 34 .max = values.GetMax()}; 35 } 36 37 Metric SetTimeseries(const Metric& prototype, 38 const SamplesStatsCounter& counter) { 39 Metric output(prototype); 40 Metric::TimeSeries time_series; 41 for (const SamplesStatsCounter::StatsSample& sample : 42 counter.GetTimedSamples()) { 43 time_series.samples.push_back( 44 Metric::TimeSeries::Sample{.timestamp = sample.time, 45 .value = sample.value, 46 .sample_metadata = sample.metadata}); 47 } 48 output.time_series = std::move(time_series); 49 output.stats = ToStats(counter); 50 return output; 51 } 52 53 } // namespace 54 55 bool operator<(const MetricsAccumulator::MetricKey& a, 56 const MetricsAccumulator::MetricKey& b) { 57 if (a.test_case_name < b.test_case_name) { 58 return true; 59 } else if (a.test_case_name > b.test_case_name) { 60 return false; 61 } else { 62 return a.metric_name < b.metric_name; 63 } 64 } 65 66 bool MetricsAccumulator::AddSample( 67 absl::string_view metric_name, 68 absl::string_view test_case_name, 69 double value, 70 Timestamp timestamp, 71 std::map<std::string, std::string> point_metadata) { 72 MutexLock lock(&mutex_); 73 bool created; 74 MetricValue* metric_value = 75 GetOrCreateMetric(metric_name, test_case_name, &created); 76 metric_value->counter.AddSample( 77 SamplesStatsCounter::StatsSample{.value = value, 78 .time = timestamp, 79 .metadata = std::move(point_metadata)}); 80 return created; 81 } 82 83 bool MetricsAccumulator::AddMetricMetadata( 84 absl::string_view metric_name, 85 absl::string_view test_case_name, 86 Unit unit, 87 ImprovementDirection improvement_direction, 88 std::map<std::string, std::string> metric_metadata) { 89 MutexLock lock(&mutex_); 90 bool created; 91 MetricValue* metric_value = 92 GetOrCreateMetric(metric_name, test_case_name, &created); 93 metric_value->metric.unit = unit; 94 metric_value->metric.improvement_direction = improvement_direction; 95 metric_value->metric.metric_metadata = std::move(metric_metadata); 96 return created; 97 } 98 99 std::vector<Metric> MetricsAccumulator::GetCollectedMetrics() const { 100 MutexLock lock(&mutex_); 101 std::vector<Metric> out; 102 out.reserve(metrics_.size()); 103 for (const auto& [unused_key, metric_value] : metrics_) { 104 out.push_back(SetTimeseries(metric_value.metric, metric_value.counter)); 105 } 106 return out; 107 } 108 109 MetricsAccumulator::MetricValue* MetricsAccumulator::GetOrCreateMetric( 110 absl::string_view metric_name, 111 absl::string_view test_case_name, 112 bool* created) { 113 MetricKey key(metric_name, test_case_name); 114 auto it = metrics_.find(key); 115 if (it != metrics_.end()) { 116 *created = false; 117 return &it->second; 118 } 119 *created = true; 120 121 Metric metric{ 122 .name = key.metric_name, 123 .unit = Unit::kUnitless, 124 .improvement_direction = ImprovementDirection::kNeitherIsBetter, 125 .test_case = key.test_case_name, 126 }; 127 return &metrics_.emplace(key, MetricValue{.metric = std::move(metric)}) 128 .first->second; 129 } 130 131 } // namespace test 132 } // namespace webrtc