mirror of
https://github.com/mollyim/webrtc.git
synced 2025-05-13 13:50:40 +01:00
Introduce MetricsLoggerAndExporter
Introduce main API for new test performance metrics logging system. Bug: b/246095034 Change-Id: I9b33740bfe69158c2d7f3f73e18442d1683aa8d4 Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/274901 Reviewed-by: Tomas Gunnarsson <tommi@webrtc.org> Reviewed-by: Mirko Bonadei <mbonadei@webrtc.org> Commit-Queue: Artem Titov <titovartem@webrtc.org> Cr-Commit-Position: refs/heads/main@{#38116}
This commit is contained in:
parent
495e058730
commit
44161f542b
6 changed files with 601 additions and 4 deletions
|
@ -11,6 +11,8 @@
|
|||
#ifndef API_NUMERICS_SAMPLES_STATS_COUNTER_H_
|
||||
#define API_NUMERICS_SAMPLES_STATS_COUNTER_H_
|
||||
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "api/array_view.h"
|
||||
|
@ -27,6 +29,8 @@ class SamplesStatsCounter {
|
|||
struct StatsSample {
|
||||
double value;
|
||||
Timestamp time;
|
||||
// Sample's specific metadata.
|
||||
std::map<std::string, std::string> metadata;
|
||||
};
|
||||
|
||||
SamplesStatsCounter();
|
||||
|
|
|
@ -12,6 +12,7 @@ group("metrics") {
|
|||
deps = [
|
||||
":metric",
|
||||
":metrics_exporter",
|
||||
":metrics_logger_and_exporter",
|
||||
":stdout_metrics_exporter",
|
||||
]
|
||||
}
|
||||
|
@ -20,7 +21,10 @@ if (rtc_include_tests) {
|
|||
group("metrics_unittests") {
|
||||
testonly = true
|
||||
|
||||
deps = [ ":stdout_metrics_exporter_test" ]
|
||||
deps = [
|
||||
":metrics_logger_and_exporter_test",
|
||||
":stdout_metrics_exporter_test",
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -39,7 +43,7 @@ rtc_library("metrics_exporter") {
|
|||
sources = [ "metrics_exporter.h" ]
|
||||
deps = [
|
||||
":metric",
|
||||
"../../../api:array_view",
|
||||
"../..:array_view",
|
||||
]
|
||||
}
|
||||
|
||||
|
@ -52,12 +56,34 @@ rtc_library("stdout_metrics_exporter") {
|
|||
deps = [
|
||||
":metric",
|
||||
":metrics_exporter",
|
||||
"../../../api:array_view",
|
||||
"../..:array_view",
|
||||
"../../../rtc_base:stringutils",
|
||||
]
|
||||
absl_deps = [ "//third_party/abseil-cpp/absl/types:optional" ]
|
||||
}
|
||||
|
||||
rtc_library("metrics_logger_and_exporter") {
|
||||
visibility = [ "*" ]
|
||||
sources = [
|
||||
"metrics_logger_and_exporter.cc",
|
||||
"metrics_logger_and_exporter.h",
|
||||
]
|
||||
deps = [
|
||||
":metric",
|
||||
":metrics_exporter",
|
||||
"../../../rtc_base:checks",
|
||||
"../../../rtc_base:logging",
|
||||
"../../../rtc_base/synchronization:mutex",
|
||||
"../../../system_wrappers",
|
||||
"../../numerics",
|
||||
]
|
||||
|
||||
absl_deps = [
|
||||
"//third_party/abseil-cpp/absl/strings",
|
||||
"//third_party/abseil-cpp/absl/types:optional",
|
||||
]
|
||||
}
|
||||
|
||||
if (rtc_include_tests) {
|
||||
rtc_library("stdout_metrics_exporter_test") {
|
||||
testonly = true
|
||||
|
@ -65,8 +91,22 @@ if (rtc_include_tests) {
|
|||
deps = [
|
||||
":metric",
|
||||
":stdout_metrics_exporter",
|
||||
"../../../api/units:timestamp",
|
||||
"../../../test:test_support",
|
||||
"../../units:timestamp",
|
||||
]
|
||||
}
|
||||
|
||||
rtc_library("metrics_logger_and_exporter_test") {
|
||||
testonly = true
|
||||
sources = [ "metrics_logger_and_exporter_test.cc" ]
|
||||
deps = [
|
||||
":metric",
|
||||
":metrics_exporter",
|
||||
":metrics_logger_and_exporter",
|
||||
"../../../system_wrappers",
|
||||
"../../../test:test_support",
|
||||
"../../numerics",
|
||||
]
|
||||
absl_deps = [ "//third_party/abseil-cpp/absl/types:optional" ]
|
||||
}
|
||||
}
|
||||
|
|
6
api/test/metrics/DEPS
Normal file
6
api/test/metrics/DEPS
Normal file
|
@ -0,0 +1,6 @@
|
|||
specific_include_rules = {
|
||||
"metrics_logger_and_exporter\.h": [
|
||||
"+rtc_base/synchronization/mutex.h",
|
||||
"+system_wrappers/include/clock.h",
|
||||
],
|
||||
}
|
120
api/test/metrics/metrics_logger_and_exporter.cc
Normal file
120
api/test/metrics/metrics_logger_and_exporter.cc
Normal file
|
@ -0,0 +1,120 @@
|
|||
/*
|
||||
* Copyright (c) 2022 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
#include "api/test/metrics/metrics_logger_and_exporter.h"
|
||||
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
#include "absl/strings/string_view.h"
|
||||
#include "absl/types/optional.h"
|
||||
#include "api/numerics/samples_stats_counter.h"
|
||||
#include "api/test/metrics/metric.h"
|
||||
#include "rtc_base/checks.h"
|
||||
#include "rtc_base/logging.h"
|
||||
#include "rtc_base/synchronization/mutex.h"
|
||||
|
||||
namespace webrtc {
|
||||
namespace test {
|
||||
|
||||
MetricsLoggerAndExporter::~MetricsLoggerAndExporter() {
|
||||
bool export_result = Export();
|
||||
if (crash_on_export_failure_) {
|
||||
RTC_CHECK(export_result);
|
||||
} else {
|
||||
RTC_LOG(LS_ERROR) << "One of exporters failed to export collected metrics";
|
||||
}
|
||||
}
|
||||
|
||||
void MetricsLoggerAndExporter::LogSingleValueMetric(
|
||||
absl::string_view name,
|
||||
absl::string_view test_case_name,
|
||||
double value,
|
||||
Unit unit,
|
||||
ImprovementDirection improvement_direction,
|
||||
std::map<std::string, std::string> metadata) {
|
||||
MutexLock lock(&mutex_);
|
||||
metrics_.push_back(Metric{
|
||||
.name = std::string(name),
|
||||
.unit = unit,
|
||||
.improvement_direction = improvement_direction,
|
||||
.test_case = std::string(test_case_name),
|
||||
.metric_metadata = std::move(metadata),
|
||||
.time_series =
|
||||
Metric::TimeSeries{.samples = std::vector{Metric::TimeSeries::Sample{
|
||||
.timestamp = Now(), .value = value}}},
|
||||
.stats = Metric::Stats{
|
||||
.mean = value, .stddev = absl::nullopt, .min = value, .max = value}});
|
||||
}
|
||||
|
||||
void MetricsLoggerAndExporter::LogMetric(
|
||||
absl::string_view name,
|
||||
absl::string_view test_case_name,
|
||||
const SamplesStatsCounter& values,
|
||||
Unit unit,
|
||||
ImprovementDirection improvement_direction,
|
||||
std::map<std::string, std::string> metadata) {
|
||||
MutexLock lock(&mutex_);
|
||||
Metric::TimeSeries time_series;
|
||||
for (const SamplesStatsCounter::StatsSample& sample :
|
||||
values.GetTimedSamples()) {
|
||||
time_series.samples.push_back(
|
||||
Metric::TimeSeries::Sample{.timestamp = sample.time,
|
||||
.value = sample.value,
|
||||
.sample_metadata = sample.metadata});
|
||||
}
|
||||
|
||||
metrics_.push_back(
|
||||
Metric{.name = std::string(name),
|
||||
.unit = unit,
|
||||
.improvement_direction = improvement_direction,
|
||||
.test_case = std::string(test_case_name),
|
||||
.metric_metadata = std::move(metadata),
|
||||
.time_series = std::move(time_series),
|
||||
.stats = Metric::Stats{.mean = values.GetAverage(),
|
||||
.stddev = values.GetStandardDeviation(),
|
||||
.min = values.GetMin(),
|
||||
.max = values.GetMax()}});
|
||||
}
|
||||
|
||||
void MetricsLoggerAndExporter::LogMetric(
|
||||
absl::string_view name,
|
||||
absl::string_view test_case_name,
|
||||
const Metric::Stats& metric_stats,
|
||||
Unit unit,
|
||||
ImprovementDirection improvement_direction,
|
||||
std::map<std::string, std::string> metadata) {
|
||||
MutexLock lock(&mutex_);
|
||||
metrics_.push_back(Metric{.name = std::string(name),
|
||||
.unit = unit,
|
||||
.improvement_direction = improvement_direction,
|
||||
.test_case = std::string(test_case_name),
|
||||
.metric_metadata = std::move(metadata),
|
||||
.time_series = Metric::TimeSeries{.samples = {}},
|
||||
.stats = std::move(metric_stats)});
|
||||
}
|
||||
|
||||
Timestamp MetricsLoggerAndExporter::Now() {
|
||||
return clock_->CurrentTime();
|
||||
}
|
||||
|
||||
bool MetricsLoggerAndExporter::Export() {
|
||||
MutexLock lock(&mutex_);
|
||||
bool success = true;
|
||||
for (auto& exporter : exporters_) {
|
||||
bool export_result = exporter->Export(metrics_);
|
||||
success = success && export_result;
|
||||
}
|
||||
return success;
|
||||
}
|
||||
|
||||
} // namespace test
|
||||
} // namespace webrtc
|
94
api/test/metrics/metrics_logger_and_exporter.h
Normal file
94
api/test/metrics/metrics_logger_and_exporter.h
Normal file
|
@ -0,0 +1,94 @@
|
|||
/*
|
||||
* Copyright (c) 2022 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#ifndef API_TEST_METRICS_METRICS_LOGGER_AND_EXPORTER_H_
|
||||
#define API_TEST_METRICS_METRICS_LOGGER_AND_EXPORTER_H_
|
||||
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
#include "absl/strings/string_view.h"
|
||||
#include "api/numerics/samples_stats_counter.h"
|
||||
#include "api/test/metrics/metric.h"
|
||||
#include "api/test/metrics/metrics_exporter.h"
|
||||
#include "rtc_base/synchronization/mutex.h"
|
||||
#include "system_wrappers/include/clock.h"
|
||||
|
||||
namespace webrtc {
|
||||
namespace test {
|
||||
|
||||
// Combines metrics logging and exporting to provide simple API to automatically
|
||||
// export metrics at the end of the scope.
|
||||
class MetricsLoggerAndExporter {
|
||||
public:
|
||||
// `crash_on_export_failure` - makes MetricsLoggerAndExporter to crash if
|
||||
// any of exporters failed to export data.
|
||||
MetricsLoggerAndExporter(
|
||||
webrtc::Clock* clock,
|
||||
std::vector<std::unique_ptr<MetricsExporter>> exporters,
|
||||
bool crash_on_export_failure = true)
|
||||
: clock_(clock),
|
||||
crash_on_export_failure_(crash_on_export_failure),
|
||||
exporters_(std::move(exporters)) {}
|
||||
~MetricsLoggerAndExporter();
|
||||
|
||||
// Adds a metric with a single value.
|
||||
// `metadata` - metric's level metadata to add.
|
||||
void LogSingleValueMetric(absl::string_view name,
|
||||
absl::string_view test_case_name,
|
||||
double value,
|
||||
Unit unit,
|
||||
ImprovementDirection improvement_direction,
|
||||
std::map<std::string, std::string> metadata);
|
||||
|
||||
// Adds metrics with a time series created based on the provided `values`.
|
||||
// `metadata` - metric's level metadata to add.
|
||||
void LogMetric(absl::string_view name,
|
||||
absl::string_view test_case_name,
|
||||
const SamplesStatsCounter& values,
|
||||
Unit unit,
|
||||
ImprovementDirection improvement_direction,
|
||||
std::map<std::string, std::string> metadata);
|
||||
|
||||
// Adds metric with a time series with only stats object and without actual
|
||||
// collected values.
|
||||
// `metadata` - metric's level metadata to add.
|
||||
void LogMetric(absl::string_view name,
|
||||
absl::string_view test_case_name,
|
||||
const Metric::Stats& metric_stats,
|
||||
Unit unit,
|
||||
ImprovementDirection improvement_direction,
|
||||
std::map<std::string, std::string> metadata);
|
||||
|
||||
// Returns all metrics collected by this logger.
|
||||
std::vector<Metric> GetCollectedMetrics() const {
|
||||
MutexLock lock(&mutex_);
|
||||
return metrics_;
|
||||
}
|
||||
|
||||
private:
|
||||
webrtc::Timestamp Now();
|
||||
bool Export();
|
||||
|
||||
webrtc::Clock* const clock_;
|
||||
const bool crash_on_export_failure_;
|
||||
|
||||
mutable Mutex mutex_;
|
||||
std::vector<Metric> metrics_ RTC_GUARDED_BY(mutex_);
|
||||
std::vector<std::unique_ptr<MetricsExporter>> exporters_;
|
||||
};
|
||||
|
||||
} // namespace test
|
||||
} // namespace webrtc
|
||||
|
||||
#endif // API_TEST_METRICS_METRICS_LOGGER_AND_EXPORTER_H_
|
333
api/test/metrics/metrics_logger_and_exporter_test.cc
Normal file
333
api/test/metrics/metrics_logger_and_exporter_test.cc
Normal file
|
@ -0,0 +1,333 @@
|
|||
/*
|
||||
* Copyright (c) 2022 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
#include "api/test/metrics/metrics_logger_and_exporter.h"
|
||||
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "absl/types/optional.h"
|
||||
#include "api/numerics/samples_stats_counter.h"
|
||||
#include "api/test/metrics/metric.h"
|
||||
#include "api/test/metrics/metrics_exporter.h"
|
||||
#include "system_wrappers/include/clock.h"
|
||||
#include "test/gmock.h"
|
||||
#include "test/gtest.h"
|
||||
|
||||
namespace webrtc {
|
||||
namespace test {
|
||||
namespace {
|
||||
|
||||
using ::testing::Eq;
|
||||
using ::testing::IsEmpty;
|
||||
|
||||
std::map<std::string, std::string> DefaultMetadata() {
|
||||
return std::map<std::string, std::string>{{"key", "value"}};
|
||||
}
|
||||
|
||||
struct TestMetricsExporterFactory {
|
||||
public:
|
||||
std::unique_ptr<MetricsExporter> CreateExporter() {
|
||||
return std::make_unique<TestMetricsExporter>(this, /*export_result=*/true);
|
||||
}
|
||||
|
||||
std::unique_ptr<MetricsExporter> CreateFailureExporter() {
|
||||
return std::make_unique<TestMetricsExporter>(this, /*export_result=*/false);
|
||||
}
|
||||
|
||||
std::vector<Metric> exported_metrics;
|
||||
|
||||
private:
|
||||
class TestMetricsExporter : public MetricsExporter {
|
||||
public:
|
||||
TestMetricsExporter(TestMetricsExporterFactory* factory, bool export_result)
|
||||
: factory_(factory), export_result_(export_result) {}
|
||||
~TestMetricsExporter() override = default;
|
||||
|
||||
bool Export(rtc::ArrayView<const Metric> metrics) override {
|
||||
factory_->exported_metrics =
|
||||
std::vector<Metric>(metrics.begin(), metrics.end());
|
||||
return export_result_;
|
||||
}
|
||||
|
||||
TestMetricsExporterFactory* factory_;
|
||||
bool export_result_;
|
||||
};
|
||||
};
|
||||
|
||||
TEST(MetricsLoggerAndExporterTest, LogSingleValueMetricRecordsMetric) {
|
||||
TestMetricsExporterFactory exporter_factory;
|
||||
{
|
||||
std::vector<std::unique_ptr<MetricsExporter>> exporters;
|
||||
exporters.push_back(exporter_factory.CreateExporter());
|
||||
MetricsLoggerAndExporter logger(Clock::GetRealTimeClock(),
|
||||
std::move(exporters));
|
||||
logger.LogSingleValueMetric(
|
||||
"metric_name", "test_case_name",
|
||||
/*value=*/10, Unit::kTimeMs, ImprovementDirection::kBiggerIsBetter,
|
||||
std::map<std::string, std::string>{{"key", "value"}});
|
||||
}
|
||||
|
||||
std::vector<Metric> metrics = exporter_factory.exported_metrics;
|
||||
ASSERT_THAT(metrics.size(), Eq(1lu));
|
||||
const Metric& metric = metrics[0];
|
||||
EXPECT_THAT(metric.name, Eq("metric_name"));
|
||||
EXPECT_THAT(metric.test_case, Eq("test_case_name"));
|
||||
EXPECT_THAT(metric.unit, Eq(Unit::kTimeMs));
|
||||
EXPECT_THAT(metric.improvement_direction,
|
||||
Eq(ImprovementDirection::kBiggerIsBetter));
|
||||
EXPECT_THAT(metric.metric_metadata,
|
||||
Eq(std::map<std::string, std::string>{{"key", "value"}}));
|
||||
ASSERT_THAT(metric.time_series.samples.size(), Eq(1lu));
|
||||
EXPECT_THAT(metric.time_series.samples[0].value, Eq(10.0));
|
||||
EXPECT_THAT(metric.time_series.samples[0].sample_metadata,
|
||||
Eq(std::map<std::string, std::string>{}));
|
||||
ASSERT_THAT(metric.stats.mean, absl::optional<double>(10.0));
|
||||
ASSERT_THAT(metric.stats.stddev, absl::nullopt);
|
||||
ASSERT_THAT(metric.stats.min, absl::optional<double>(10.0));
|
||||
ASSERT_THAT(metric.stats.max, absl::optional<double>(10.0));
|
||||
}
|
||||
|
||||
TEST(MetricsLoggerAndExporterTest,
|
||||
LogMetricWithSamplesStatsCounterRecordsMetric) {
|
||||
TestMetricsExporterFactory exporter_factory;
|
||||
{
|
||||
std::vector<std::unique_ptr<MetricsExporter>> exporters;
|
||||
exporters.push_back(exporter_factory.CreateExporter());
|
||||
MetricsLoggerAndExporter logger(Clock::GetRealTimeClock(),
|
||||
std::move(exporters));
|
||||
|
||||
SamplesStatsCounter values;
|
||||
values.AddSample(SamplesStatsCounter::StatsSample{
|
||||
.value = 10,
|
||||
.time = Clock::GetRealTimeClock()->CurrentTime(),
|
||||
.metadata =
|
||||
std::map<std::string, std::string>{{"point_key1", "value1"}}});
|
||||
values.AddSample(SamplesStatsCounter::StatsSample{
|
||||
.value = 20,
|
||||
.time = Clock::GetRealTimeClock()->CurrentTime(),
|
||||
.metadata =
|
||||
std::map<std::string, std::string>{{"point_key2", "value2"}}});
|
||||
logger.LogMetric("metric_name", "test_case_name", values, Unit::kTimeMs,
|
||||
ImprovementDirection::kBiggerIsBetter,
|
||||
std::map<std::string, std::string>{{"key", "value"}});
|
||||
}
|
||||
|
||||
std::vector<Metric> metrics = exporter_factory.exported_metrics;
|
||||
ASSERT_THAT(metrics.size(), Eq(1lu));
|
||||
const Metric& metric = metrics[0];
|
||||
EXPECT_THAT(metric.name, Eq("metric_name"));
|
||||
EXPECT_THAT(metric.test_case, Eq("test_case_name"));
|
||||
EXPECT_THAT(metric.unit, Eq(Unit::kTimeMs));
|
||||
EXPECT_THAT(metric.improvement_direction,
|
||||
Eq(ImprovementDirection::kBiggerIsBetter));
|
||||
EXPECT_THAT(metric.metric_metadata,
|
||||
Eq(std::map<std::string, std::string>{{"key", "value"}}));
|
||||
ASSERT_THAT(metric.time_series.samples.size(), Eq(2lu));
|
||||
EXPECT_THAT(metric.time_series.samples[0].value, Eq(10.0));
|
||||
EXPECT_THAT(metric.time_series.samples[0].sample_metadata,
|
||||
Eq(std::map<std::string, std::string>{{"point_key1", "value1"}}));
|
||||
EXPECT_THAT(metric.time_series.samples[1].value, Eq(20.0));
|
||||
EXPECT_THAT(metric.time_series.samples[1].sample_metadata,
|
||||
Eq(std::map<std::string, std::string>{{"point_key2", "value2"}}));
|
||||
ASSERT_THAT(metric.stats.mean, absl::optional<double>(15.0));
|
||||
ASSERT_THAT(metric.stats.stddev, absl::optional<double>(5.0));
|
||||
ASSERT_THAT(metric.stats.min, absl::optional<double>(10.0));
|
||||
ASSERT_THAT(metric.stats.max, absl::optional<double>(20.0));
|
||||
}
|
||||
|
||||
TEST(MetricsLoggerAndExporterTest, LogMetricWithStatsRecordsMetric) {
|
||||
TestMetricsExporterFactory exporter_factory;
|
||||
{
|
||||
std::vector<std::unique_ptr<MetricsExporter>> exporters;
|
||||
exporters.push_back(exporter_factory.CreateExporter());
|
||||
MetricsLoggerAndExporter logger(Clock::GetRealTimeClock(),
|
||||
std::move(exporters));
|
||||
Metric::Stats metric_stats{.mean = 15, .stddev = 5, .min = 10, .max = 20};
|
||||
logger.LogMetric("metric_name", "test_case_name", metric_stats,
|
||||
Unit::kTimeMs, ImprovementDirection::kBiggerIsBetter,
|
||||
std::map<std::string, std::string>{{"key", "value"}});
|
||||
}
|
||||
|
||||
std::vector<Metric> metrics = exporter_factory.exported_metrics;
|
||||
ASSERT_THAT(metrics.size(), Eq(1lu));
|
||||
const Metric& metric = metrics[0];
|
||||
EXPECT_THAT(metric.name, Eq("metric_name"));
|
||||
EXPECT_THAT(metric.test_case, Eq("test_case_name"));
|
||||
EXPECT_THAT(metric.unit, Eq(Unit::kTimeMs));
|
||||
EXPECT_THAT(metric.improvement_direction,
|
||||
Eq(ImprovementDirection::kBiggerIsBetter));
|
||||
EXPECT_THAT(metric.metric_metadata,
|
||||
Eq(std::map<std::string, std::string>{{"key", "value"}}));
|
||||
ASSERT_THAT(metric.time_series.samples.size(), Eq(0lu));
|
||||
ASSERT_THAT(metric.stats.mean, absl::optional<double>(15.0));
|
||||
ASSERT_THAT(metric.stats.stddev, absl::optional<double>(5.0));
|
||||
ASSERT_THAT(metric.stats.min, absl::optional<double>(10.0));
|
||||
ASSERT_THAT(metric.stats.max, absl::optional<double>(20.0));
|
||||
}
|
||||
|
||||
TEST(MetricsLoggerAndExporterTest, LogSingleValueMetricRecordsMultipleMetrics) {
|
||||
TestMetricsExporterFactory exporter_factory;
|
||||
{
|
||||
std::vector<std::unique_ptr<MetricsExporter>> exporters;
|
||||
exporters.push_back(exporter_factory.CreateExporter());
|
||||
MetricsLoggerAndExporter logger(Clock::GetRealTimeClock(),
|
||||
std::move(exporters));
|
||||
|
||||
logger.LogSingleValueMetric("metric_name1", "test_case_name1",
|
||||
/*value=*/10, Unit::kTimeMs,
|
||||
ImprovementDirection::kBiggerIsBetter,
|
||||
DefaultMetadata());
|
||||
logger.LogSingleValueMetric("metric_name2", "test_case_name2",
|
||||
/*value=*/10, Unit::kTimeMs,
|
||||
ImprovementDirection::kBiggerIsBetter,
|
||||
DefaultMetadata());
|
||||
}
|
||||
|
||||
std::vector<Metric> metrics = exporter_factory.exported_metrics;
|
||||
ASSERT_THAT(metrics.size(), Eq(2lu));
|
||||
EXPECT_THAT(metrics[0].name, Eq("metric_name1"));
|
||||
EXPECT_THAT(metrics[0].test_case, Eq("test_case_name1"));
|
||||
EXPECT_THAT(metrics[1].name, Eq("metric_name2"));
|
||||
EXPECT_THAT(metrics[1].test_case, Eq("test_case_name2"));
|
||||
}
|
||||
|
||||
TEST(MetricsLoggerAndExporterTest,
|
||||
LogMetricWithSamplesStatsCounterRecordsMultipleMetrics) {
|
||||
TestMetricsExporterFactory exporter_factory;
|
||||
{
|
||||
std::vector<std::unique_ptr<MetricsExporter>> exporters;
|
||||
exporters.push_back(exporter_factory.CreateExporter());
|
||||
MetricsLoggerAndExporter logger(Clock::GetRealTimeClock(),
|
||||
std::move(exporters));
|
||||
SamplesStatsCounter values;
|
||||
values.AddSample(SamplesStatsCounter::StatsSample{
|
||||
.value = 10,
|
||||
.time = Clock::GetRealTimeClock()->CurrentTime(),
|
||||
.metadata = DefaultMetadata()});
|
||||
values.AddSample(SamplesStatsCounter::StatsSample{
|
||||
.value = 20,
|
||||
.time = Clock::GetRealTimeClock()->CurrentTime(),
|
||||
.metadata = DefaultMetadata()});
|
||||
|
||||
logger.LogMetric("metric_name1", "test_case_name1", values, Unit::kTimeMs,
|
||||
ImprovementDirection::kBiggerIsBetter, DefaultMetadata());
|
||||
logger.LogMetric("metric_name2", "test_case_name2", values, Unit::kTimeMs,
|
||||
ImprovementDirection::kBiggerIsBetter, DefaultMetadata());
|
||||
}
|
||||
|
||||
std::vector<Metric> metrics = exporter_factory.exported_metrics;
|
||||
ASSERT_THAT(metrics.size(), Eq(2lu));
|
||||
EXPECT_THAT(metrics[0].name, Eq("metric_name1"));
|
||||
EXPECT_THAT(metrics[0].test_case, Eq("test_case_name1"));
|
||||
EXPECT_THAT(metrics[1].name, Eq("metric_name2"));
|
||||
EXPECT_THAT(metrics[1].test_case, Eq("test_case_name2"));
|
||||
}
|
||||
|
||||
TEST(MetricsLoggerAndExporterTest, LogMetricWithStatsRecordsMultipleMetrics) {
|
||||
TestMetricsExporterFactory exporter_factory;
|
||||
{
|
||||
std::vector<std::unique_ptr<MetricsExporter>> exporters;
|
||||
exporters.push_back(exporter_factory.CreateExporter());
|
||||
MetricsLoggerAndExporter logger(Clock::GetRealTimeClock(),
|
||||
std::move(exporters));
|
||||
Metric::Stats metric_stats{.mean = 15, .stddev = 5, .min = 10, .max = 20};
|
||||
|
||||
logger.LogMetric("metric_name1", "test_case_name1", metric_stats,
|
||||
Unit::kTimeMs, ImprovementDirection::kBiggerIsBetter,
|
||||
DefaultMetadata());
|
||||
logger.LogMetric("metric_name2", "test_case_name2", metric_stats,
|
||||
Unit::kTimeMs, ImprovementDirection::kBiggerIsBetter,
|
||||
DefaultMetadata());
|
||||
}
|
||||
|
||||
std::vector<Metric> metrics = exporter_factory.exported_metrics;
|
||||
ASSERT_THAT(metrics.size(), Eq(2lu));
|
||||
EXPECT_THAT(metrics[0].name, Eq("metric_name1"));
|
||||
EXPECT_THAT(metrics[0].test_case, Eq("test_case_name1"));
|
||||
EXPECT_THAT(metrics[1].name, Eq("metric_name2"));
|
||||
EXPECT_THAT(metrics[1].test_case, Eq("test_case_name2"));
|
||||
}
|
||||
|
||||
TEST(MetricsLoggerAndExporterTest,
|
||||
LogMetricThroughtAllMethodsAccumulateAllMetrics) {
|
||||
TestMetricsExporterFactory exporter_factory;
|
||||
{
|
||||
std::vector<std::unique_ptr<MetricsExporter>> exporters;
|
||||
exporters.push_back(exporter_factory.CreateExporter());
|
||||
MetricsLoggerAndExporter logger(Clock::GetRealTimeClock(),
|
||||
std::move(exporters));
|
||||
SamplesStatsCounter values;
|
||||
values.AddSample(SamplesStatsCounter::StatsSample{
|
||||
.value = 10,
|
||||
.time = Clock::GetRealTimeClock()->CurrentTime(),
|
||||
.metadata = DefaultMetadata()});
|
||||
values.AddSample(SamplesStatsCounter::StatsSample{
|
||||
.value = 20,
|
||||
.time = Clock::GetRealTimeClock()->CurrentTime(),
|
||||
.metadata = DefaultMetadata()});
|
||||
Metric::Stats metric_stats{.mean = 15, .stddev = 5, .min = 10, .max = 20};
|
||||
|
||||
logger.LogSingleValueMetric("metric_name1", "test_case_name1",
|
||||
/*value=*/10, Unit::kTimeMs,
|
||||
ImprovementDirection::kBiggerIsBetter,
|
||||
DefaultMetadata());
|
||||
logger.LogMetric("metric_name2", "test_case_name2", values, Unit::kTimeMs,
|
||||
ImprovementDirection::kBiggerIsBetter, DefaultMetadata());
|
||||
logger.LogMetric("metric_name3", "test_case_name3", metric_stats,
|
||||
Unit::kTimeMs, ImprovementDirection::kBiggerIsBetter,
|
||||
DefaultMetadata());
|
||||
}
|
||||
|
||||
std::vector<Metric> metrics = exporter_factory.exported_metrics;
|
||||
ASSERT_THAT(metrics.size(), Eq(3lu));
|
||||
EXPECT_THAT(metrics[0].name, Eq("metric_name1"));
|
||||
EXPECT_THAT(metrics[0].test_case, Eq("test_case_name1"));
|
||||
EXPECT_THAT(metrics[1].name, Eq("metric_name2"));
|
||||
EXPECT_THAT(metrics[1].test_case, Eq("test_case_name2"));
|
||||
EXPECT_THAT(metrics[2].name, Eq("metric_name3"));
|
||||
EXPECT_THAT(metrics[2].test_case, Eq("test_case_name3"));
|
||||
}
|
||||
|
||||
TEST(MetricsLoggerAndExporterTest,
|
||||
OneFailedExporterDoesNotPreventExportToOthers) {
|
||||
TestMetricsExporterFactory exporter_factory1;
|
||||
TestMetricsExporterFactory exporter_factory2;
|
||||
TestMetricsExporterFactory exporter_factory3;
|
||||
{
|
||||
std::vector<std::unique_ptr<MetricsExporter>> exporters;
|
||||
exporters.push_back(exporter_factory1.CreateExporter());
|
||||
exporters.push_back(exporter_factory2.CreateFailureExporter());
|
||||
exporters.push_back(exporter_factory3.CreateExporter());
|
||||
MetricsLoggerAndExporter logger(Clock::GetRealTimeClock(),
|
||||
std::move(exporters),
|
||||
/*crash_on_export_failure=*/false);
|
||||
|
||||
logger.LogSingleValueMetric("metric_name", "test_case_name",
|
||||
/*value=*/10, Unit::kTimeMs,
|
||||
ImprovementDirection::kBiggerIsBetter,
|
||||
DefaultMetadata());
|
||||
}
|
||||
|
||||
std::vector<Metric> metrics1 = exporter_factory1.exported_metrics;
|
||||
std::vector<Metric> metrics2 = exporter_factory2.exported_metrics;
|
||||
std::vector<Metric> metrics3 = exporter_factory3.exported_metrics;
|
||||
ASSERT_THAT(metrics1.size(), Eq(1lu));
|
||||
EXPECT_THAT(metrics1[0].name, Eq("metric_name"));
|
||||
ASSERT_THAT(metrics2.size(), Eq(1lu));
|
||||
EXPECT_THAT(metrics2[0].name, Eq("metric_name"));
|
||||
ASSERT_THAT(metrics3.size(), Eq(1lu));
|
||||
EXPECT_THAT(metrics3[0].name, Eq("metric_name"));
|
||||
}
|
||||
|
||||
} // namespace
|
||||
} // namespace test
|
||||
} // namespace webrtc
|
Loading…
Reference in a new issue