blob: 56f0337037c0627e145f0f25348eb2efb8e8d7c0 [file] [log] [blame]
/*
* Copyright (c) 2019 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 "test/pc/e2e/network_quality_metrics_reporter.h"
#include <utility>
#include "api/stats_types.h"
#include "rtc_base/event.h"
#include "system_wrappers/include/field_trial.h"
#include "test/testsupport/perf_test.h"
namespace webrtc {
namespace webrtc_pc_e2e {
namespace {
constexpr int kStatsWaitTimeoutMs = 1000;
// Field trial which controls whether to report standard-compliant bytes
// sent/received per stream. If enabled, padding and headers are not included
// in bytes sent or received.
constexpr char kUseStandardBytesStats[] = "WebRTC-UseStandardBytesStats";
}
void NetworkQualityMetricsReporter::Start(absl::string_view test_case_name) {
test_case_name_ = std::string(test_case_name);
// Check that network stats are clean before test execution.
EmulatedNetworkStats alice_stats = PopulateStats(alice_network_);
RTC_CHECK_EQ(alice_stats.packets_sent, 0);
RTC_CHECK_EQ(alice_stats.packets_received, 0);
EmulatedNetworkStats bob_stats = PopulateStats(bob_network_);
RTC_CHECK_EQ(bob_stats.packets_sent, 0);
RTC_CHECK_EQ(bob_stats.packets_received, 0);
}
void NetworkQualityMetricsReporter::OnStatsReports(
const std::string& pc_label,
const StatsReports& reports) {
rtc::CritScope cs(&lock_);
int64_t payload_bytes_received = 0;
int64_t payload_bytes_sent = 0;
for (const StatsReport* report : reports) {
if (report->type() == StatsReport::kStatsReportTypeSsrc) {
const auto* received =
report->FindValue(StatsReport::kStatsValueNameBytesReceived);
if (received) {
payload_bytes_received += received->int64_val();
}
const auto* sent =
report->FindValue(StatsReport::kStatsValueNameBytesSent);
if (sent) {
payload_bytes_sent += sent->int64_val();
}
}
}
PCStats& stats = pc_stats_[pc_label];
stats.payload_bytes_received = payload_bytes_received;
stats.payload_bytes_sent = payload_bytes_sent;
}
void NetworkQualityMetricsReporter::StopAndReportResults() {
EmulatedNetworkStats alice_stats = PopulateStats(alice_network_);
EmulatedNetworkStats bob_stats = PopulateStats(bob_network_);
ReportStats("alice", alice_stats,
alice_stats.packets_sent - bob_stats.packets_received);
ReportStats("bob", bob_stats,
bob_stats.packets_sent - alice_stats.packets_received);
if (!webrtc::field_trial::IsEnabled(kUseStandardBytesStats)) {
RTC_LOG(LS_ERROR)
<< "Non-standard GetStats; \"payload\" counts include RTP headers";
}
rtc::CritScope cs(&lock_);
for (const auto& pair : pc_stats_) {
ReportPCStats(pair.first, pair.second);
}
}
EmulatedNetworkStats NetworkQualityMetricsReporter::PopulateStats(
EmulatedNetworkManagerInterface* network) {
rtc::Event wait;
EmulatedNetworkStats stats;
network->GetStats([&](const EmulatedNetworkStats& s) {
stats = s;
wait.Set();
});
bool stats_received = wait.Wait(kStatsWaitTimeoutMs);
RTC_CHECK(stats_received);
return stats;
}
void NetworkQualityMetricsReporter::ReportStats(
const std::string& network_label,
const EmulatedNetworkStats& stats,
int64_t packet_loss) {
ReportResult("bytes_sent", network_label, stats.bytes_sent.bytes(),
"sizeInBytes");
ReportResult("packets_sent", network_label, stats.packets_sent, "unitless");
ReportResult(
"average_send_rate", network_label,
stats.packets_sent >= 2 ? stats.AverageSendRate().bytes_per_sec() : 0,
"bytesPerSecond");
ReportResult("bytes_dropped", network_label, stats.bytes_dropped.bytes(),
"sizeInBytes");
ReportResult("packets_dropped", network_label, stats.packets_dropped,
"unitless");
ReportResult("bytes_received", network_label, stats.bytes_received.bytes(),
"sizeInBytes");
ReportResult("packets_received", network_label, stats.packets_received,
"unitless");
ReportResult("average_receive_rate", network_label,
stats.packets_received >= 2
? stats.AverageReceiveRate().bytes_per_sec()
: 0,
"bytesPerSecond");
ReportResult("sent_packets_loss", network_label, packet_loss, "unitless");
}
void NetworkQualityMetricsReporter::ReportPCStats(const std::string& pc_label,
const PCStats& stats) {
ReportResult("payload_bytes_received", pc_label, stats.payload_bytes_received,
"sizeInBytes");
ReportResult("payload_bytes_sent", pc_label, stats.payload_bytes_sent,
"sizeInBytes");
}
void NetworkQualityMetricsReporter::ReportResult(
const std::string& metric_name,
const std::string& network_label,
const double value,
const std::string& unit) const {
test::PrintResult(metric_name, /*modifier=*/"",
GetTestCaseName(network_label), value, unit,
/*important=*/false);
}
std::string NetworkQualityMetricsReporter::GetTestCaseName(
const std::string& network_label) const {
return test_case_name_ + "/" + network_label;
}
} // namespace webrtc_pc_e2e
} // namespace webrtc