summaryrefslogtreecommitdiff
path: root/runtime/metrics/metrics.cc
diff options
context:
space:
mode:
author Eric Holk <eholk@google.com> 2020-12-07 15:07:00 -0800
committer Treehugger Robot <treehugger-gerrit@google.com> 2020-12-21 18:09:31 +0000
commit51a9283984b05511bd98f9bcbd1f2f18900239cc (patch)
tree09b25eb574b2c93f4e940bfab423b58acdf340bd /runtime/metrics/metrics.cc
parent20cadbf2a204a029b595cd44f9298f6570b5c812 (diff)
[metrics] Add file output support
Adds a new command line option, -Xwrite-metrics-to-file=_, which specifies a file for writing metrics to. This can be used in conjunction with -Xwrite-metrics-to-log, which will cause the output to go to both logcat and the file. Writing metrics to a file can be helpful for testing or benchmarking environments. Access to the file is protected using advisory locking, so it is safe to have multiple processes write metrics to the same file. Test: test/run-test --host test/2234-write-metrics-to-file Bug: 175025360, 170149255 Change-Id: I83a4f959cbb96847dc71188035c050a73b915064
Diffstat (limited to 'runtime/metrics/metrics.cc')
-rw-r--r--runtime/metrics/metrics.cc39
1 files changed, 36 insertions, 3 deletions
diff --git a/runtime/metrics/metrics.cc b/runtime/metrics/metrics.cc
index 81ae2b4dab..e85897b19e 100644
--- a/runtime/metrics/metrics.cc
+++ b/runtime/metrics/metrics.cc
@@ -16,12 +16,20 @@
#include "metrics.h"
+#include <sstream>
+
+#include "android-base/file.h"
#include "android-base/logging.h"
#include "base/macros.h"
+#include "base/scoped_flock.h"
+#include "runtime.h"
+#include "runtime_options.h"
#pragma clang diagnostic push
#pragma clang diagnostic error "-Wconversion"
+using android::base::WriteStringToFd;
+
namespace art {
namespace metrics {
@@ -116,15 +124,15 @@ std::unique_ptr<MetricsReporter> MetricsReporter::Create(ReportingConfig config,
std::unique_ptr<MetricsBackend> backend;
// We can't use std::make_unique here because the MetricsReporter constructor is private.
- return std::unique_ptr<MetricsReporter>{new MetricsReporter{config, metrics}};
+ return std::unique_ptr<MetricsReporter>{new MetricsReporter{std::move(config), metrics}};
}
MetricsReporter::MetricsReporter(ReportingConfig config, const ArtMetrics* metrics)
- : config_{config}, metrics_{metrics} {}
+ : config_{std::move(config)}, metrics_{metrics} {}
MetricsReporter::~MetricsReporter() {
// If we are configured to report metrics, do one final report at the end.
- if (config_.dump_to_logcat) {
+ if (config_.ReportingEnabled()) {
LOG_STREAM(INFO) << "\n*** ART internal metrics ***\n\n";
// LOG_STREAM(INFO) destroys the stream at the end of the statement, which makes it tricky pass
// it to store as a field in StreamBackend. To get around this, we use an immediately-invoked
@@ -136,6 +144,31 @@ MetricsReporter::~MetricsReporter() {
}(LOG_STREAM(INFO));
LOG_STREAM(INFO) << "\n*** Done dumping ART internal metrics ***\n";
}
+ if (config_.dump_to_file.has_value()) {
+ const auto& filename = config_.dump_to_file.value();
+ std::ostringstream stream;
+ StreamBackend backend{stream};
+ metrics_->ReportAllMetrics(&backend);
+
+ std::string error_message;
+ auto file{
+ LockedFile::Open(filename.c_str(), O_CREAT | O_WRONLY | O_APPEND, true, &error_message)};
+ if (file.get() == nullptr) {
+ LOG(WARNING) << "Could open metrics file '" << filename << "': " << error_message;
+ } else {
+ if (!WriteStringToFd(stream.str(), file.get()->Fd())) {
+ PLOG(WARNING) << "Error writing metrics to file";
+ }
+ }
+ }
+}
+
+ReportingConfig ReportingConfig::FromRuntimeArguments(const RuntimeArgumentMap& args) {
+ using M = RuntimeArgumentMap;
+ return {
+ .dump_to_logcat = args.Exists(M::WriteMetricsToLog),
+ .dump_to_file = args.GetOptional(M::WriteMetricsToFile),
+ };
}
} // namespace metrics