blob: 5ce0539e69500b075be0db7d3c3e30b73abca116 [file] [log] [blame]
// Copyright 2020 The Chromium 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 "fuchsia/base/legacymetrics_client.h"
#include <lib/fit/function.h>
#include <lib/sys/cpp/component_context.h>
#include <memory>
#include <utility>
#include <vector>
#include "base/fuchsia/default_context.h"
#include "base/fuchsia/fuchsia_logging.h"
#include "base/logging.h"
#include "base/threading/thread_task_runner_handle.h"
#include "base/time/time.h"
#include "fuchsia/base/legacymetrics_histogram_flattener.h"
namespace cr_fuchsia {
LegacyMetricsClient::LegacyMetricsClient() = default;
LegacyMetricsClient::~LegacyMetricsClient() {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
}
void LegacyMetricsClient::Start(base::TimeDelta report_interval) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
DCHECK_GT(report_interval, base::TimeDelta::FromSeconds(0));
DCHECK(!metrics_recorder_) << "Start() called more than once.";
report_interval_ = report_interval;
metrics_recorder_ = base::fuchsia::ComponentContextForCurrentProcess()
->svc()
->Connect<fuchsia::legacymetrics::MetricsRecorder>();
metrics_recorder_.set_error_handler(fit::bind_member(
this, &LegacyMetricsClient::OnMetricsRecorderDisconnected));
user_events_recorder_ = std::make_unique<LegacyMetricsUserActionRecorder>();
ScheduleNextReport();
}
void LegacyMetricsClient::SetReportAdditionalMetricsCallback(
ReportAdditionalMetricsCallback callback) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
DCHECK(!metrics_recorder_)
<< "SetReportAdditionalMetricsCallback() must be called before Start().";
DCHECK(!report_additional_callback_);
DCHECK(callback);
report_additional_callback_ = std::move(callback);
}
void LegacyMetricsClient::ScheduleNextReport() {
DVLOG(1) << "Scheduling next report in " << report_interval_.InSeconds()
<< "seconds.";
timer_.Start(FROM_HERE, report_interval_, this, &LegacyMetricsClient::Report);
}
void LegacyMetricsClient::Report() {
DCHECK(metrics_recorder_);
DVLOG(1) << __func__ << "called.";
std::vector<fuchsia::legacymetrics::Event> events;
// Add events from the additional metrics callback, if set.
if (report_additional_callback_)
report_additional_callback_.Run(&events);
// Include histograms.
for (auto& histogram : GetLegacyMetricsDeltas()) {
fuchsia::legacymetrics::Event histogram_event;
histogram_event.set_histogram(std::move(histogram));
events.push_back(std::move(histogram_event));
}
// Include user events.
if (user_events_recorder_->HasEvents()) {
for (auto& event : user_events_recorder_->TakeEvents()) {
fuchsia::legacymetrics::Event user_event;
user_event.set_user_action_event(std::move(event));
events.push_back(std::move(user_event));
}
}
if (events.empty()) {
ScheduleNextReport();
return;
}
metrics_recorder_->Record(std::move(events), [this]() {
VLOG(1) << "Report finished.";
ScheduleNextReport();
});
}
void LegacyMetricsClient::OnMetricsRecorderDisconnected(zx_status_t status) {
ZX_LOG_IF(ERROR, status != ZX_ERR_PEER_CLOSED, status)
<< "MetricsRecorder connection lost.";
// Stop recording & reporting user events.
user_events_recorder_.reset();
timer_.AbandonAndStop();
}
} // namespace cr_fuchsia