1 // Copyright 2015 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 #include "content/browser/tracing/background_tracing_rule.h"
9 #include "base/metrics/histogram_macros.h"
10 #include "base/metrics/statistics_recorder.h"
11 #include "base/rand_util.h"
12 #include "base/strings/safe_sprintf.h"
13 #include "base/values.h"
14 #include "components/tracing/tracing_messages.h"
15 #include "content/browser/tracing/background_tracing_manager_impl.h"
16 #include "content/browser/tracing/trace_message_filter.h"
17 #include "content/public/browser/browser_thread.h"
21 const char kConfigRuleKey
[] = "rule";
22 const char kConfigCategoryKey
[] = "category";
23 const char kConfigRuleTriggerNameKey
[] = "trigger_name";
25 const char kConfigRuleHistogramNameKey
[] = "histogram_name";
26 const char kConfigRuleHistogramValueKey
[] = "histogram_value";
28 const char kConfigRuleRandomIntervalTimeoutMin
[] = "timeout_min";
29 const char kConfigRuleRandomIntervalTimeoutMax
[] = "timeout_max";
31 const char kPreemptiveConfigRuleMonitorNamed
[] =
32 "MONITOR_AND_DUMP_WHEN_TRIGGER_NAMED";
34 const char kPreemptiveConfigRuleMonitorHistogram
[] =
35 "MONITOR_AND_DUMP_WHEN_SPECIFIC_HISTOGRAM_AND_VALUE";
37 const char kReactiveConfigRuleTraceOnNavigationUntilTriggerOrFull
[] =
38 "TRACE_ON_NAVIGATION_UNTIL_TRIGGER_OR_FULL";
40 const char kReactiveConfigRuleTraceAtRandomIntervals
[] =
41 "TRACE_AT_RANDOM_INTERVALS";
43 const char kTraceAtRandomIntervalsEventName
[] =
44 "ReactiveTraceAtRandomIntervals";
46 const int kReactiveConfigNavigationTimeout
= 30;
47 const int kReactiveTraceRandomStartTimeMin
= 60;
48 const int kReactiveTraceRandomStartTimeMax
= 120;
54 BackgroundTracingRule::BackgroundTracingRule() {}
56 BackgroundTracingRule::~BackgroundTracingRule() {}
58 bool BackgroundTracingRule::ShouldTriggerNamedEvent(
59 const std::string
& named_event
) const {
63 BackgroundTracingConfigImpl::CategoryPreset
64 BackgroundTracingRule::GetCategoryPreset() const {
65 return BackgroundTracingConfigImpl::BENCHMARK
;
70 class NamedTriggerRule
: public BackgroundTracingRule
{
72 NamedTriggerRule(const std::string
& named_event
)
73 : named_event_(named_event
) {}
75 void IntoDict(base::DictionaryValue
* dict
) const override
{
77 dict
->SetString(kConfigRuleKey
, kPreemptiveConfigRuleMonitorNamed
);
78 dict
->SetString(kConfigRuleTriggerNameKey
, named_event_
.c_str());
81 bool ShouldTriggerNamedEvent(const std::string
& named_event
) const override
{
82 return named_event
== named_event_
;
86 std::string named_event_
;
89 class HistogramRule
: public BackgroundTracingRule
,
90 public TracingControllerImpl::TraceMessageFilterObserver
{
92 HistogramRule(const std::string
& histogram_name
, int histogram_value
)
93 : histogram_name_(histogram_name
), histogram_value_(histogram_value
) {}
95 ~HistogramRule() override
{
96 base::StatisticsRecorder::ClearCallback(histogram_name_
);
97 TracingControllerImpl::GetInstance()->RemoveTraceMessageFilterObserver(
101 // BackgroundTracingRule implementation
102 void Install() override
{
103 base::StatisticsRecorder::SetCallback(
105 base::Bind(&HistogramRule::OnHistogramChangedCallback
,
106 base::Unretained(this), histogram_name_
, histogram_value_
));
108 TracingControllerImpl::GetInstance()->AddTraceMessageFilterObserver(this);
111 void IntoDict(base::DictionaryValue
* dict
) const override
{
113 dict
->SetString(kConfigRuleKey
, kPreemptiveConfigRuleMonitorHistogram
);
114 dict
->SetString(kConfigRuleHistogramNameKey
, histogram_name_
.c_str());
115 dict
->SetInteger(kConfigRuleHistogramValueKey
, histogram_value_
);
118 void OnHistogramTrigger(const std::string
& histogram_name
) const override
{
119 if (histogram_name
!= histogram_name_
)
122 content::BrowserThread::PostTask(
123 content::BrowserThread::UI
, FROM_HERE
,
125 &BackgroundTracingManagerImpl::TriggerPreemptiveFinalization
,
126 base::Unretained(BackgroundTracingManagerImpl::GetInstance())));
129 // TracingControllerImpl::TraceMessageFilterObserver implementation
130 void OnTraceMessageFilterAdded(TraceMessageFilter
* filter
) override
{
132 new TracingMsg_SetUMACallback(histogram_name_
, histogram_value_
));
135 void OnTraceMessageFilterRemoved(TraceMessageFilter
* filter
) override
{
136 filter
->Send(new TracingMsg_ClearUMACallback(histogram_name_
));
139 void OnHistogramChangedCallback(const std::string
& histogram_name
,
140 base::Histogram::Sample reference_value
,
141 base::Histogram::Sample actual_value
) {
142 if (reference_value
> actual_value
)
145 OnHistogramTrigger(histogram_name
);
149 std::string histogram_name_
;
150 int histogram_value_
;
153 class ReactiveTraceForNSOrTriggerOrFullRule
: public BackgroundTracingRule
{
155 ReactiveTraceForNSOrTriggerOrFullRule(
156 const std::string
& named_event
,
157 BackgroundTracingConfigImpl::CategoryPreset category_preset
)
158 : named_event_(named_event
), category_preset_(category_preset
) {}
160 // BackgroundTracingRule implementation
161 void IntoDict(base::DictionaryValue
* dict
) const override
{
165 BackgroundTracingConfigImpl::CategoryPresetToString(category_preset_
));
166 dict
->SetString(kConfigRuleKey
,
167 kReactiveConfigRuleTraceOnNavigationUntilTriggerOrFull
);
168 dict
->SetString(kConfigRuleTriggerNameKey
, named_event_
.c_str());
171 bool ShouldTriggerNamedEvent(const std::string
& named_event
) const override
{
172 return named_event
== named_event_
;
175 int GetReactiveTimeout() const override
{
176 return kReactiveConfigNavigationTimeout
;
179 BackgroundTracingConfigImpl::CategoryPreset
GetCategoryPreset()
181 return category_preset_
;
185 std::string named_event_
;
186 BackgroundTracingConfigImpl::CategoryPreset category_preset_
;
189 class ReactiveTraceAtRandomIntervalsRule
: public BackgroundTracingRule
{
191 ReactiveTraceAtRandomIntervalsRule(
192 BackgroundTracingConfigImpl::CategoryPreset category_preset
,
195 : category_preset_(category_preset
),
196 timeout_min_(timeout_min
),
197 timeout_max_(timeout_max
) {
198 named_event_
= GenerateUniqueName();
201 ~ReactiveTraceAtRandomIntervalsRule() override
{}
203 void IntoDict(base::DictionaryValue
* dict
) const override
{
207 BackgroundTracingConfigImpl::CategoryPresetToString(category_preset_
));
208 dict
->SetString(kConfigRuleKey
, kReactiveConfigRuleTraceAtRandomIntervals
);
209 dict
->SetInteger(kConfigRuleRandomIntervalTimeoutMin
, timeout_min_
);
210 dict
->SetInteger(kConfigRuleRandomIntervalTimeoutMax
, timeout_max_
);
213 void Install() override
{
214 handle_
= BackgroundTracingManagerImpl::GetInstance()->RegisterTriggerType(
215 named_event_
.c_str());
220 void OnStartedFinalizing(bool success
) {
227 void OnTriggerTimer() {
228 BackgroundTracingManagerImpl::GetInstance()->TriggerNamedEvent(
230 base::Bind(&ReactiveTraceAtRandomIntervalsRule::OnStartedFinalizing
,
231 base::Unretained(this)));
235 int time_to_wait
= base::RandInt(kReactiveTraceRandomStartTimeMin
,
236 kReactiveTraceRandomStartTimeMax
);
237 trigger_timer_
.Start(
238 FROM_HERE
, base::TimeDelta::FromSeconds(time_to_wait
),
239 base::Bind(&ReactiveTraceAtRandomIntervalsRule::OnTriggerTimer
,
240 base::Unretained(this)));
243 int GetReactiveTimeout() const override
{
244 return base::RandInt(timeout_min_
, timeout_max_
);
247 bool ShouldTriggerNamedEvent(const std::string
& named_event
) const override
{
248 return named_event
== named_event_
;
251 BackgroundTracingConfigImpl::CategoryPreset
GetCategoryPreset()
253 return category_preset_
;
256 std::string
GenerateUniqueName() const {
258 char work_buffer
[256];
259 base::strings::SafeSNPrintf(work_buffer
, sizeof(work_buffer
), "%s_%d",
260 kTraceAtRandomIntervalsEventName
, ids
++);
265 std::string named_event_
;
266 base::OneShotTimer
<ReactiveTraceAtRandomIntervalsRule
> trigger_timer_
;
267 BackgroundTracingConfigImpl::CategoryPreset category_preset_
;
268 BackgroundTracingManagerImpl::TriggerHandle handle_
;
275 int BackgroundTracingRule::GetReactiveTimeout() const {
279 scoped_ptr
<BackgroundTracingRule
> BackgroundTracingRule::PreemptiveRuleFromDict(
280 const base::DictionaryValue
* dict
) {
284 if (!dict
->GetString(kConfigRuleKey
, &type
))
287 if (type
== kPreemptiveConfigRuleMonitorNamed
) {
288 std::string trigger_name
;
289 if (!dict
->GetString(kConfigRuleTriggerNameKey
, &trigger_name
))
292 return scoped_ptr
<BackgroundTracingRule
>(
293 new NamedTriggerRule(trigger_name
));
296 if (type
== kPreemptiveConfigRuleMonitorHistogram
) {
297 std::string histogram_name
;
298 if (!dict
->GetString(kConfigRuleHistogramNameKey
, &histogram_name
))
302 if (!dict
->GetInteger(kConfigRuleHistogramValueKey
, &histogram_value
))
305 return scoped_ptr
<BackgroundTracingRule
>(
306 new HistogramRule(histogram_name
, histogram_value
));
312 scoped_ptr
<BackgroundTracingRule
> BackgroundTracingRule::ReactiveRuleFromDict(
313 const base::DictionaryValue
* dict
,
314 BackgroundTracingConfigImpl::CategoryPreset category_preset
) {
318 if (!dict
->GetString(kConfigRuleKey
, &type
))
321 if (type
== kReactiveConfigRuleTraceOnNavigationUntilTriggerOrFull
) {
322 std::string trigger_name
;
323 if (!dict
->GetString(kConfigRuleTriggerNameKey
, &trigger_name
))
326 return scoped_ptr
<BackgroundTracingRule
>(
327 new ReactiveTraceForNSOrTriggerOrFullRule(trigger_name
,
331 if (type
== kReactiveConfigRuleTraceAtRandomIntervals
) {
333 if (!dict
->GetInteger(kConfigRuleRandomIntervalTimeoutMin
, &timeout_min
))
337 if (!dict
->GetInteger(kConfigRuleRandomIntervalTimeoutMax
, &timeout_max
))
340 if (timeout_min
> timeout_max
)
343 return scoped_ptr
<BackgroundTracingRule
>(
344 new ReactiveTraceAtRandomIntervalsRule(category_preset
, timeout_min
,
351 } // namespace content