blob: 3712259d4795f481f1aa90bfb3c3efae0185b0c0 [file] [log] [blame]
// Copyright 2023 The ChromiumOS Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "metrics/metrics_writer.h"
#include <string>
#include <unistd.h>
#include <utility>
#include <vector>
#include <base/files/file_path.h>
#include <base/logging.h>
#include <base/location.h>
#include <base/strings/string_number_conversions.h>
#include <base/synchronization/waitable_event.h>
#include "metrics/serialization/serialization_utils.h"
SynchronousMetricsWriter::SynchronousMetricsWriter(
bool avoid_blocking,
base::FilePath uma_events_file,
base::FilePath uma_events_dir)
: avoid_blocking_(avoid_blocking),
uma_events_file_(std::move(uma_events_file)),
uma_events_dir_(std::move(uma_events_dir)) {}
bool SynchronousMetricsWriter::WriteMetrics(
std::vector<metrics::MetricSample> samples) {
base::FilePath uma_events_file = uma_events_file_;
if (avoid_blocking_) {
uma_events_file = uma_events_dir_.Append(base::NumberToString(getpid()));
}
return metrics::SerializationUtils::WriteMetricsToFile(
samples, uma_events_file.value());
}
bool SynchronousMetricsWriter::SetOutputFile(const std::string& output_file) {
uma_events_file_ = base::FilePath(output_file);
return true;
}
AsynchronousMetricsWriter::AsynchronousMetricsWriter(
scoped_refptr<base::SequencedTaskRunner> task_runner,
bool wait_on_destructor,
base::FilePath uma_events_file)
: task_runner_(std::move(task_runner)),
wait_on_destructor_(wait_on_destructor),
uma_events_file_(std::move(uma_events_file)) {}
AsynchronousMetricsWriter::~AsynchronousMetricsWriter() {
if (wait_on_destructor_) {
WaitUntilFlushed();
}
}
bool AsynchronousMetricsWriter::WriteMetrics(
std::vector<metrics::MetricSample> samples) {
return task_runner_->PostTask(
FROM_HERE,
base::BindOnce(&AsynchronousMetricsWriter::WriteMetricsOnThread,
weak_ptr_factory_.GetWeakPtr(), std::move(samples)));
}
bool AsynchronousMetricsWriter::SetOutputFile(const std::string& output_file) {
return task_runner_->PostTask(
FROM_HERE,
base::BindOnce(&AsynchronousMetricsWriter::SetOutputFileOnThread,
weak_ptr_factory_.GetWeakPtr(),
base::FilePath(output_file)));
}
void AsynchronousMetricsWriter::WaitUntilFlushed() {
// If this is called on the SequencedTaskRunner thread, this will deadlock.
CHECK(!task_runner_->RunsTasksInCurrentSequence());
base::WaitableEvent flushed;
CHECK(task_runner_->PostNonNestableTask(
FROM_HERE,
base::BindOnce(
[](base::WaitableEvent& flushed_ref) { flushed_ref.Signal(); },
std::ref(flushed))));
flushed.Wait();
}
void AsynchronousMetricsWriter::WriteMetricsOnThread(
std::vector<metrics::MetricSample> samples) {
if (!metrics::SerializationUtils::WriteMetricsToFile(
samples, uma_events_file_.value())) {
LOG(ERROR) << "Failed to write metrics";
}
}
void AsynchronousMetricsWriter::SetOutputFileOnThread(
base::FilePath output_file) {
uma_events_file_ = std::move(output_file);
}