blob: 51b1c9b4208ec5c1e466a89460fa3a7bbaabf34a [file]
// Protocol Buffers - Google's data interchange format
// Copyright 2023 Google Inc. All rights reserved.
//
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file or at
// https://developers.google.com/open-source/licenses/bsd
//
#include "google/protobuf/port.h"
#include <cstdio>
#include <cstdlib>
#include <map>
#include <utility>
#include "absl/strings/str_format.h"
#include "absl/strings/str_split.h"
#include "absl/strings/string_view.h"
// Must be included last
#include "google/protobuf/port_def.inc"
namespace google {
namespace protobuf {
namespace internal {
// protobuf_assumption_failed() is declared and used in port_def.inc to assert
// PROTOBUF_ASSUME conditions in debug mode. This function avoids having
// port_def.inc depend on assert.h or other headers, minimizing the compilation
// footprint.
void protobuf_assumption_failed(const char* pred, const char* file, int line) {
fprintf(stderr, "%s: %d: Assumption failed: '%s'\n", file, line, pred);
abort();
}
static void PrintAllCounters();
static auto& CounterMap() {
using Map = std::map<absl::string_view,
std::map<absl::string_view, const RealDebugCounter*>>;
static auto* counter_map = new Map{};
static bool dummy = std::atexit(PrintAllCounters);
(void)dummy;
return *counter_map;
}
static void PrintAllCounters() {
auto& counters = CounterMap();
if (counters.empty()) return;
absl::FPrintF(stderr, "Protobuf debug counters:\n");
for (auto& category : counters) {
// Example output:
//
// Category :
// Value 1 : 1234 (12.34%)
// Value 2 : 2345 (23.45%)
// Total : 3579
absl::FPrintF(stderr, " %-12s:\n", category.first);
size_t total = 0;
for (auto& count : category.second) {
total += count.second->value();
}
for (auto& count : category.second) {
size_t value = count.second->value();
absl::FPrintF(stderr, " %-10s: %10zu", count.first, value);
if (total != 0 && category.second.size() > 1) {
absl::FPrintF(
stderr, " (%5.2f%%)",
100. * static_cast<double>(value) / static_cast<double>(total));
}
absl::FPrintF(stderr, "\n");
}
if (total != 0 && category.second.size() > 1) {
absl::FPrintF(stderr, " %-10s: %10zu\n", "Total", total);
}
}
}
void RealDebugCounter::Register(absl::string_view name) {
std::pair<absl::string_view, absl::string_view> parts =
absl::StrSplit(name, '.');
CounterMap()[parts.first][parts.second] = this;
}
} // namespace internal
} // namespace protobuf
} // namespace google
#include "google/protobuf/port_undef.inc"