Remove rtc_event_log2stats.
This tool does not seem useful enough to justfy the maintenance cost. If we want something like this in the future, then the core logic should be added to the parser. Bug: webrtc:8111 Change-Id: Ifc3dc9b91e85246d35d7775c68d0f2dc687516aa Reviewed-on: https://webrtc-review.googlesource.com/c/110724 Reviewed-by: Elad Alon <eladalon@webrtc.org> Commit-Queue: Björn Terelius <terelius@webrtc.org> Cr-Commit-Position: refs/heads/master@{#25623}
This commit is contained in:

committed by
Commit Bot

parent
8544799cf1
commit
c7e3af1ad9
@ -421,20 +421,6 @@ if (rtc_enable_protobuf) {
|
||||
}
|
||||
}
|
||||
}
|
||||
if (rtc_include_tests) {
|
||||
rtc_executable("rtc_event_log2stats") {
|
||||
testonly = true
|
||||
sources = [
|
||||
"rtc_event_log/rtc_event_log2stats.cc",
|
||||
]
|
||||
deps = [
|
||||
":rtc_event_log_api",
|
||||
":rtc_event_log_proto",
|
||||
"../rtc_base:checks",
|
||||
"../rtc_base:rtc_base_approved",
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
rtc_source_set("ice_log") {
|
||||
|
@ -1,265 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2017 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 <inttypes.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include <fstream>
|
||||
#include <iostream>
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include <tuple>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
#include "logging/rtc_event_log/rtc_event_log.h"
|
||||
#include "rtc_base/checks.h"
|
||||
#include "rtc_base/flags.h"
|
||||
#include "rtc_base/ignore_wundef.h"
|
||||
#include "rtc_base/logging.h"
|
||||
|
||||
// Files generated at build-time by the protobuf compiler.
|
||||
RTC_PUSH_IGNORING_WUNDEF()
|
||||
#ifdef WEBRTC_ANDROID_PLATFORM_BUILD
|
||||
#include "external/webrtc/webrtc/logging/rtc_event_log/rtc_event_log.pb.h"
|
||||
#else
|
||||
#include "logging/rtc_event_log/rtc_event_log.pb.h"
|
||||
#endif
|
||||
RTC_POP_IGNORING_WUNDEF()
|
||||
|
||||
namespace {
|
||||
|
||||
WEBRTC_DEFINE_bool(help, false, "Prints this message.");
|
||||
|
||||
struct Stats {
|
||||
int count = 0;
|
||||
size_t total_size = 0;
|
||||
};
|
||||
|
||||
// We are duplicating some parts of the parser here because we want to get
|
||||
// access to raw protobuf events.
|
||||
std::pair<uint64_t, bool> ParseVarInt(std::istream& stream) {
|
||||
uint64_t varint = 0;
|
||||
for (size_t bytes_read = 0; bytes_read < 10; ++bytes_read) {
|
||||
// The most significant bit of each byte is 0 if it is the last byte in
|
||||
// the varint and 1 otherwise. Thus, we take the 7 least significant bits
|
||||
// of each byte and shift them 7 bits for each byte read previously to get
|
||||
// the (unsigned) integer.
|
||||
int byte = stream.get();
|
||||
if (stream.eof()) {
|
||||
return std::make_pair(varint, false);
|
||||
}
|
||||
RTC_DCHECK_GE(byte, 0);
|
||||
RTC_DCHECK_LE(byte, 255);
|
||||
varint |= static_cast<uint64_t>(byte & 0x7F) << (7 * bytes_read);
|
||||
if ((byte & 0x80) == 0) {
|
||||
return std::make_pair(varint, true);
|
||||
}
|
||||
}
|
||||
return std::make_pair(varint, false);
|
||||
}
|
||||
|
||||
bool ParseEvents(const std::string& filename,
|
||||
std::vector<webrtc::rtclog::Event>* events) {
|
||||
std::ifstream stream(filename, std::ios_base::in | std::ios_base::binary);
|
||||
if (!stream.good() || !stream.is_open()) {
|
||||
RTC_LOG(LS_WARNING) << "Could not open file for reading.";
|
||||
return false;
|
||||
}
|
||||
|
||||
const size_t kMaxEventSize = (1u << 16) - 1;
|
||||
std::vector<char> tmp_buffer(kMaxEventSize);
|
||||
uint64_t tag;
|
||||
uint64_t message_length;
|
||||
bool success;
|
||||
|
||||
RTC_DCHECK(stream.good());
|
||||
|
||||
while (1) {
|
||||
// Check whether we have reached end of file.
|
||||
stream.peek();
|
||||
if (stream.eof()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Read the next message tag. The tag number is defined as
|
||||
// (fieldnumber << 3) | wire_type. In our case, the field number is
|
||||
// supposed to be 1 and the wire type for an length-delimited field is 2.
|
||||
const uint64_t kExpectedTag = (1 << 3) | 2;
|
||||
std::tie(tag, success) = ParseVarInt(stream);
|
||||
if (!success) {
|
||||
RTC_LOG(LS_WARNING)
|
||||
<< "Missing field tag from beginning of protobuf event.";
|
||||
return false;
|
||||
} else if (tag != kExpectedTag) {
|
||||
RTC_LOG(LS_WARNING)
|
||||
<< "Unexpected field tag at beginning of protobuf event.";
|
||||
return false;
|
||||
}
|
||||
|
||||
// Read the length field.
|
||||
std::tie(message_length, success) = ParseVarInt(stream);
|
||||
if (!success) {
|
||||
RTC_LOG(LS_WARNING) << "Missing message length after protobuf field tag.";
|
||||
return false;
|
||||
} else if (message_length > kMaxEventSize) {
|
||||
RTC_LOG(LS_WARNING) << "Protobuf message length is too large.";
|
||||
return false;
|
||||
}
|
||||
|
||||
// Read the next protobuf event to a temporary char buffer.
|
||||
stream.read(tmp_buffer.data(), message_length);
|
||||
if (stream.gcount() != static_cast<int>(message_length)) {
|
||||
RTC_LOG(LS_WARNING) << "Failed to read protobuf message from file.";
|
||||
return false;
|
||||
}
|
||||
|
||||
// Parse the protobuf event from the buffer.
|
||||
webrtc::rtclog::Event event;
|
||||
if (!event.ParseFromArray(tmp_buffer.data(), message_length)) {
|
||||
RTC_LOG(LS_WARNING) << "Failed to parse protobuf message.";
|
||||
return false;
|
||||
}
|
||||
events->push_back(event);
|
||||
}
|
||||
}
|
||||
|
||||
// TODO(terelius): Should this be placed in some utility file instead?
|
||||
std::string EventTypeToString(webrtc::rtclog::Event::EventType event_type) {
|
||||
switch (event_type) {
|
||||
case webrtc::rtclog::Event::UNKNOWN_EVENT:
|
||||
return "UNKNOWN_EVENT";
|
||||
case webrtc::rtclog::Event::LOG_START:
|
||||
return "LOG_START";
|
||||
case webrtc::rtclog::Event::LOG_END:
|
||||
return "LOG_END";
|
||||
case webrtc::rtclog::Event::RTP_EVENT:
|
||||
return "RTP_EVENT";
|
||||
case webrtc::rtclog::Event::RTCP_EVENT:
|
||||
return "RTCP_EVENT";
|
||||
case webrtc::rtclog::Event::AUDIO_PLAYOUT_EVENT:
|
||||
return "AUDIO_PLAYOUT_EVENT";
|
||||
case webrtc::rtclog::Event::LOSS_BASED_BWE_UPDATE:
|
||||
return "LOSS_BASED_BWE_UPDATE";
|
||||
case webrtc::rtclog::Event::DELAY_BASED_BWE_UPDATE:
|
||||
return "DELAY_BASED_BWE_UPDATE";
|
||||
case webrtc::rtclog::Event::VIDEO_RECEIVER_CONFIG_EVENT:
|
||||
return "VIDEO_RECV_CONFIG";
|
||||
case webrtc::rtclog::Event::VIDEO_SENDER_CONFIG_EVENT:
|
||||
return "VIDEO_SEND_CONFIG";
|
||||
case webrtc::rtclog::Event::AUDIO_RECEIVER_CONFIG_EVENT:
|
||||
return "AUDIO_RECV_CONFIG";
|
||||
case webrtc::rtclog::Event::AUDIO_SENDER_CONFIG_EVENT:
|
||||
return "AUDIO_SEND_CONFIG";
|
||||
case webrtc::rtclog::Event::AUDIO_NETWORK_ADAPTATION_EVENT:
|
||||
return "AUDIO_NETWORK_ADAPTATION";
|
||||
case webrtc::rtclog::Event::BWE_PROBE_CLUSTER_CREATED_EVENT:
|
||||
return "BWE_PROBE_CREATED";
|
||||
case webrtc::rtclog::Event::BWE_PROBE_RESULT_EVENT:
|
||||
return "BWE_PROBE_RESULT";
|
||||
case webrtc::rtclog::Event::ALR_STATE_EVENT:
|
||||
return "ALR_STATE_EVENT";
|
||||
case webrtc::rtclog::Event::ICE_CANDIDATE_PAIR_CONFIG:
|
||||
return "ICE_CANDIDATE_PAIR_CONFIG";
|
||||
case webrtc::rtclog::Event::ICE_CANDIDATE_PAIR_EVENT:
|
||||
return "ICE_CANDIDATE_PAIR_EVENT";
|
||||
}
|
||||
RTC_NOTREACHED();
|
||||
return "UNKNOWN_EVENT";
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
// This utility will print basic information about each packet to stdout.
|
||||
// Note that parser will assert if the protobuf event is missing some required
|
||||
// fields and we attempt to access them. We don't handle this at the moment.
|
||||
int main(int argc, char* argv[]) {
|
||||
std::string program_name = argv[0];
|
||||
std::string usage =
|
||||
"Tool for file usage statistics from an RtcEventLog.\n"
|
||||
"Run " +
|
||||
program_name +
|
||||
" --help for usage.\n"
|
||||
"Example usage:\n" +
|
||||
program_name + " input.rel\n";
|
||||
if (rtc::FlagList::SetFlagsFromCommandLine(&argc, argv, true) || FLAG_help ||
|
||||
argc != 2) {
|
||||
std::cout << usage;
|
||||
if (FLAG_help) {
|
||||
rtc::FlagList::Print(nullptr, false);
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
std::string file_name = argv[1];
|
||||
|
||||
std::vector<webrtc::rtclog::Event> events;
|
||||
if (!ParseEvents(file_name, &events)) {
|
||||
RTC_LOG(LS_ERROR) << "Failed to parse event log.";
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Get file size
|
||||
FILE* file = fopen(file_name.c_str(), "rb");
|
||||
fseek(file, 0L, SEEK_END);
|
||||
int64_t file_size = ftell(file);
|
||||
fclose(file);
|
||||
|
||||
// We are deliberately using low level protobuf functions to get the stats
|
||||
// since the convenience functions in the parser would CHECK that the events
|
||||
// are well formed.
|
||||
std::map<webrtc::rtclog::Event::EventType, Stats> stats;
|
||||
int malformed_events = 0;
|
||||
size_t malformed_event_size = 0;
|
||||
size_t accumulated_event_size = 0;
|
||||
for (const webrtc::rtclog::Event& event : events) {
|
||||
size_t serialized_size = event.ByteSizeLong();
|
||||
// When the event is written on the disk, it is part of an EventStream
|
||||
// object. The event stream will prepend a 1 byte field number/wire type,
|
||||
// and a varint encoding (base 128) of the event length.
|
||||
serialized_size =
|
||||
1 + (1 + (serialized_size > 127) + (serialized_size > 16383)) +
|
||||
serialized_size;
|
||||
|
||||
if (event.has_type() && event.has_timestamp_us()) {
|
||||
stats[event.type()].count++;
|
||||
stats[event.type()].total_size += serialized_size;
|
||||
} else {
|
||||
// The event is missing the type or the timestamp field.
|
||||
malformed_events++;
|
||||
malformed_event_size += serialized_size;
|
||||
}
|
||||
accumulated_event_size += serialized_size;
|
||||
}
|
||||
|
||||
printf("Type \tCount\tTotal size\tAverage size\tPercent\n");
|
||||
printf(
|
||||
"-----------------------------------------------------------------------"
|
||||
"\n");
|
||||
for (const auto it : stats) {
|
||||
printf("%-22s\t%5d\t%10zu\t%12.2lf\t%7.2lf\n",
|
||||
EventTypeToString(it.first).c_str(), it.second.count,
|
||||
it.second.total_size,
|
||||
static_cast<double>(it.second.total_size) / it.second.count,
|
||||
static_cast<double>(it.second.total_size) / file_size * 100);
|
||||
}
|
||||
if (malformed_events != 0) {
|
||||
printf("%-22s\t%5d\t%10zu\t%12.2lf\t%7.2lf\n", "MALFORMED",
|
||||
malformed_events, malformed_event_size,
|
||||
static_cast<double>(malformed_event_size) / malformed_events,
|
||||
static_cast<double>(malformed_event_size) / file_size * 100);
|
||||
}
|
||||
if (file_size - accumulated_event_size != 0) {
|
||||
printf("WARNING: %" PRId64 " bytes not accounted for\n",
|
||||
file_size - accumulated_event_size);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
Reference in New Issue
Block a user