/* * 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_set_proto_file_exporter.h" #include #include #include "api/test/metrics/metric.h" #include "rtc_base/logging.h" #include "test/testsupport/file_utils.h" #if WEBRTC_ENABLE_PROTOBUF #include "api/test/metrics/proto/metric.pb.h" #endif namespace webrtc { namespace test { namespace { #if WEBRTC_ENABLE_PROTOBUF webrtc::test_metrics::Unit ToProtoUnit(Unit unit) { switch (unit) { case Unit::kMilliseconds: return webrtc::test_metrics::Unit::MILLISECONDS; case Unit::kPercent: return webrtc::test_metrics::Unit::PERCENT; case Unit::kBytes: return webrtc::test_metrics::Unit::BYTES; case Unit::kKilobitsPerSecond: return webrtc::test_metrics::Unit::KILOBITS_PER_SECOND; case Unit::kHertz: return webrtc::test_metrics::Unit::HERTZ; case Unit::kUnitless: return webrtc::test_metrics::Unit::UNITLESS; case Unit::kCount: return webrtc::test_metrics::Unit::COUNT; } } webrtc::test_metrics::ImprovementDirection ToProtoImprovementDirection( ImprovementDirection direction) { switch (direction) { case ImprovementDirection::kBiggerIsBetter: return webrtc::test_metrics::ImprovementDirection::BIGGER_IS_BETTER; case ImprovementDirection::kNeitherIsBetter: return webrtc::test_metrics::ImprovementDirection::NEITHER_IS_BETTER; case ImprovementDirection::kSmallerIsBetter: return webrtc::test_metrics::ImprovementDirection::SMALLER_IS_BETTER; } } void SetTimeSeries( const Metric::TimeSeries& time_series, webrtc::test_metrics::Metric::TimeSeries* proto_time_series) { for (const Metric::TimeSeries::Sample& sample : time_series.samples) { webrtc::test_metrics::Metric::TimeSeries::Sample* proto_sample = proto_time_series->add_samples(); proto_sample->set_value(sample.value); proto_sample->set_timestamp_us(sample.timestamp.us()); for (const auto& [key, value] : sample.sample_metadata) { proto_sample->mutable_sample_metadata()->insert({key, value}); } } } void SetStats(const Metric::Stats& stats, webrtc::test_metrics::Metric::Stats* proto_stats) { if (stats.mean.has_value()) { proto_stats->set_mean(*stats.mean); } if (stats.stddev.has_value()) { proto_stats->set_stddev(*stats.stddev); } if (stats.min.has_value()) { proto_stats->set_min(*stats.min); } if (stats.max.has_value()) { proto_stats->set_max(*stats.max); } } bool WriteMetricsToFile(const std::string& path, const webrtc::test_metrics::MetricsSet& metrics_set) { std::string data; bool ok = metrics_set.SerializeToString(&data); if (!ok) { RTC_LOG(LS_ERROR) << "Failed to serialize histogram set to string"; return false; } CreateDir(DirName(path)); FILE* output = fopen(path.c_str(), "wb"); if (output == NULL) { RTC_LOG(LS_ERROR) << "Failed to write to " << path; return false; } size_t written = fwrite(data.c_str(), sizeof(char), data.size(), output); fclose(output); if (written != data.size()) { size_t expected = data.size(); RTC_LOG(LS_ERROR) << "Wrote " << written << ", tried to write " << expected; return false; } return true; } #endif // WEBRTC_ENABLE_PROTOBUF } // namespace MetricsSetProtoFileExporter::Options::Options( absl::string_view export_file_path) : export_file_path(export_file_path) {} MetricsSetProtoFileExporter::Options::Options( absl::string_view export_file_path, bool export_whole_time_series) : export_file_path(export_file_path), export_whole_time_series(export_whole_time_series) {} bool MetricsSetProtoFileExporter::Export(rtc::ArrayView metrics) { #if WEBRTC_ENABLE_PROTOBUF webrtc::test_metrics::MetricsSet metrics_set; for (const Metric& metric : metrics) { webrtc::test_metrics::Metric* metric_proto = metrics_set.add_metrics(); metric_proto->set_name(metric.name); metric_proto->set_unit(ToProtoUnit(metric.unit)); metric_proto->set_improvement_direction( ToProtoImprovementDirection(metric.improvement_direction)); metric_proto->set_test_case(metric.test_case); for (const auto& [key, value] : metric.metric_metadata) { metric_proto->mutable_metric_metadata()->insert({key, value}); } if (options_.export_whole_time_series) { SetTimeSeries(metric.time_series, metric_proto->mutable_time_series()); } SetStats(metric.stats, metric_proto->mutable_stats()); } return WriteMetricsToFile(options_.export_file_path, metrics_set); #else RTC_LOG(LS_ERROR) << "Compile with protobuf support to properly use this class"; return false; #endif } } // namespace test } // namespace webrtc