blob: 3e415f8b97f54cbb248c8bddb8e67ef45f58b56e [file] [log] [blame]
// Copyright 2017 The Goma Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "counterz.h"
#include <algorithm>
#include <glog/logging.h>
#include "absl/strings/match.h"
#include "file_helper.h"
#include "google/protobuf/util/json_util.h"
namespace devtools_goma {
void CounterInfo::Dump(
std::string* name, int64_t* time_ns, int64_t* count) const {
*name = location_ + "(" + funcname_ + ":" + name_ + ")";
*count = counter_.value();
*time_ns = total_time_in_ns_.value();
}
void CounterInfo::DumpToProto(CounterzStat* counterz) const {
counterz->set_name(name_);
counterz->set_function_name(funcname_);
counterz->set_location(location_);
counterz->set_total_count(counter_.value());
counterz->set_total_time_ns(total_time_in_ns_.value());
}
void Counterz::DumpToJson(Json::Value* json) const {
struct stat {
std::string name;
int64_t count, time_ns;
};
std::vector<stat> stats;
{
AUTOLOCK(lock, &mu_);
for (size_t i = 0; i < counters_.size(); ++i) {
stat s;
counters_[i]->Dump(&s.name, &s.time_ns, &s.count);
stats.push_back(std::move(s));
}
}
std::sort(stats.begin(), stats.end(),
[](const stat& l, const stat& r) {
return l.time_ns > r.time_ns;
});
*json = Json::Value(Json::arrayValue);
for (const auto& s : stats) {
Json::Value j;
j["name"] = s.name;
j["count"] = Json::Int64(s.count);
// TODO: human readable representation.
j["time(s)"] = Json::Value(s.time_ns / 1e9);
j["avg(ms)"] = Json::Value(
s.time_ns / 1e6 / std::max<int64_t>(s.count, 1));
json->append(j);
}
}
void Counterz::DumpToProto(CounterzStats* counters) const {
AUTOLOCK(lock, &mu_);
for (size_t i = 0; i < counters_.size(); ++i) {
counters_[i]->DumpToProto(counters->add_counterz_stats());
}
}
Counterz* Counterz::instance_;
/* static */
void Counterz::Init() {
CHECK(instance_ == nullptr);
instance_ = new Counterz;
}
/* static */
void Counterz::Dump(const std::string& filename) {
CHECK(instance_ != nullptr);
CounterzStats counterz;
instance_->DumpToProto(&counterz);
std::string dump_buf;
if (absl::EndsWith(filename, ".json")) {
google::protobuf::util::JsonPrintOptions options;
options.preserve_proto_field_names = true;
google::protobuf::util::MessageToJsonString(counterz, &dump_buf, options);
} else {
counterz.SerializeToString(&dump_buf);
}
if (!WriteStringToFile(dump_buf, filename)) {
LOG(ERROR) << "failed to dump counterz stats to " << filename;
} else {
LOG(INFO) << "dumped counterz stats to " << filename;
}
}
/* static */
void Counterz::Quit() {
CHECK(instance_ != nullptr);
delete instance_;
instance_ = nullptr;
}
/* static */
Counterz* Counterz::Instance() {
return instance_;
}
} // namespace devtools_goma