blob: 25e0d239f8afb0483df1c8f5b282b3884f51ea11 [file] [log] [blame]
// Copyright (c) 2012 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 "components/tracing/child/background_tracing_agent_impl.h"
#include <memory>
#include "base/metrics/statistics_recorder.h"
#include "base/threading/sequenced_task_runner_handle.h"
#include "base/trace_event/trace_event.h"
#include "mojo/public/cpp/bindings/self_owned_receiver.h"
namespace tracing {
namespace {
constexpr base::TimeDelta kMinTimeBetweenHistogramChanges =
base::TimeDelta::FromSeconds(10);
} // namespace
BackgroundTracingAgentImpl::BackgroundTracingAgentImpl(
mojo::PendingRemote<mojom::BackgroundTracingAgentClient> client)
: client_(std::move(client)) {
client_->OnInitialized();
}
BackgroundTracingAgentImpl::~BackgroundTracingAgentImpl() = default;
void BackgroundTracingAgentImpl::SetUMACallback(
const std::string& histogram_name,
int32_t histogram_lower_value,
int32_t histogram_upper_value,
bool repeat) {
histogram_last_changed_ = base::Time();
base::WeakPtr<BackgroundTracingAgentImpl> weak_self =
weak_factory_.GetWeakPtr();
// This callback will run on a random thread, so we need to proxy back to the
// current sequence before touching |this|.
base::StatisticsRecorder::SetCallback(
histogram_name,
base::BindRepeating(&BackgroundTracingAgentImpl::OnHistogramChanged,
weak_self, base::SequencedTaskRunnerHandle::Get(),
histogram_name, histogram_lower_value,
histogram_upper_value, repeat));
base::HistogramBase* existing_histogram =
base::StatisticsRecorder::FindHistogram(histogram_name);
if (!existing_histogram)
return;
std::unique_ptr<base::HistogramSamples> samples =
existing_histogram->SnapshotSamples();
if (!samples)
return;
std::unique_ptr<base::SampleCountIterator> sample_iterator =
samples->Iterator();
if (!sample_iterator)
return;
while (!sample_iterator->Done()) {
base::HistogramBase::Sample min;
int64_t max;
base::HistogramBase::Count count;
sample_iterator->Get(&min, &max, &count);
if (min >= histogram_lower_value && max <= histogram_upper_value) {
SendTriggerMessage(histogram_name);
break;
}
if (!repeat) {
SendAbortBackgroundTracingMessage();
break;
}
sample_iterator->Next();
}
}
void BackgroundTracingAgentImpl::ClearUMACallback(
const std::string& histogram_name) {
histogram_last_changed_ = base::Time();
base::StatisticsRecorder::ClearCallback(histogram_name);
}
// static
void BackgroundTracingAgentImpl::OnHistogramChanged(
base::WeakPtr<BackgroundTracingAgentImpl> weak_self,
scoped_refptr<base::SequencedTaskRunner> task_runner,
const std::string& histogram_name,
base::Histogram::Sample histogram_lower_value,
base::Histogram::Sample histogram_upper_value,
bool repeat,
base::Histogram::Sample actual_value) {
// NOTE: This method is called from an arbitrary sequence.
if (actual_value < histogram_lower_value ||
actual_value > histogram_upper_value) {
if (!repeat) {
task_runner->PostTask(
FROM_HERE,
base::BindOnce(
&BackgroundTracingAgentImpl::SendAbortBackgroundTracingMessage,
weak_self));
}
return;
}
task_runner->PostTask(
FROM_HERE, base::BindOnce(&BackgroundTracingAgentImpl::SendTriggerMessage,
weak_self, histogram_name));
}
void BackgroundTracingAgentImpl::SendTriggerMessage(
const std::string& histogram_name) {
base::Time now = TRACE_TIME_NOW();
if (!histogram_last_changed_.is_null()) {
base::Time computed_next_allowed_time =
histogram_last_changed_ + kMinTimeBetweenHistogramChanges;
if (computed_next_allowed_time > now)
return;
}
histogram_last_changed_ = now;
client_->OnTriggerBackgroundTrace(histogram_name);
}
void BackgroundTracingAgentImpl::SendAbortBackgroundTracingMessage() {
client_->OnAbortBackgroundTrace();
}
} // namespace tracing