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 kConfigRuleHistogramValueOldKey
[] = "histogram_value";
27 const char kConfigRuleHistogramValue1Key
[] = "histogram_lower_value";
28 const char kConfigRuleHistogramValue2Key
[] = "histogram_upper_value";
30 const char kConfigRuleRandomIntervalTimeoutMin
[] = "timeout_min";
31 const char kConfigRuleRandomIntervalTimeoutMax
[] = "timeout_max";
33 const char kPreemptiveConfigRuleMonitorNamed
[] =
34 "MONITOR_AND_DUMP_WHEN_TRIGGER_NAMED";
36 const char kPreemptiveConfigRuleMonitorHistogram
[] =
37 "MONITOR_AND_DUMP_WHEN_SPECIFIC_HISTOGRAM_AND_VALUE";
39 const char kReactiveConfigRuleTraceOnNavigationUntilTriggerOrFull
[] =
40 "TRACE_ON_NAVIGATION_UNTIL_TRIGGER_OR_FULL";
42 const char kReactiveConfigRuleTraceAtRandomIntervals
[] =
43 "TRACE_AT_RANDOM_INTERVALS";
45 const char kTraceAtRandomIntervalsEventName
[] =
46 "ReactiveTraceAtRandomIntervals";
48 const int kReactiveConfigNavigationTimeout
= 30;
49 const int kReactiveTraceRandomStartTimeMin
= 60;
50 const int kReactiveTraceRandomStartTimeMax
= 120;
56 BackgroundTracingRule::BackgroundTracingRule() {}
58 BackgroundTracingRule::~BackgroundTracingRule() {}
60 bool BackgroundTracingRule::ShouldTriggerNamedEvent(
61 const std::string
& named_event
) const {
65 BackgroundTracingConfigImpl::CategoryPreset
66 BackgroundTracingRule::GetCategoryPreset() const {
67 return BackgroundTracingConfigImpl::BENCHMARK
;
72 class NamedTriggerRule
: public BackgroundTracingRule
{
74 NamedTriggerRule(const std::string
& named_event
)
75 : named_event_(named_event
) {}
77 void IntoDict(base::DictionaryValue
* dict
) const override
{
79 dict
->SetString(kConfigRuleKey
, kPreemptiveConfigRuleMonitorNamed
);
80 dict
->SetString(kConfigRuleTriggerNameKey
, named_event_
.c_str());
83 bool ShouldTriggerNamedEvent(const std::string
& named_event
) const override
{
84 return named_event
== named_event_
;
88 std::string named_event_
;
91 class HistogramRule
: public BackgroundTracingRule
,
92 public TracingControllerImpl::TraceMessageFilterObserver
{
94 HistogramRule(const std::string
& histogram_name
,
95 int histogram_lower_value
,
96 int histogram_upper_value
)
97 : histogram_name_(histogram_name
),
98 histogram_lower_value_(histogram_lower_value
),
99 histogram_upper_value_(histogram_upper_value
) {}
101 ~HistogramRule() override
{
102 base::StatisticsRecorder::ClearCallback(histogram_name_
);
103 TracingControllerImpl::GetInstance()->RemoveTraceMessageFilterObserver(
107 // BackgroundTracingRule implementation
108 void Install() override
{
109 base::StatisticsRecorder::SetCallback(
111 base::Bind(&HistogramRule::OnHistogramChangedCallback
,
112 base::Unretained(this), histogram_name_
,
113 histogram_lower_value_
, histogram_upper_value_
));
115 TracingControllerImpl::GetInstance()->AddTraceMessageFilterObserver(this);
118 void IntoDict(base::DictionaryValue
* dict
) const override
{
120 dict
->SetString(kConfigRuleKey
, kPreemptiveConfigRuleMonitorHistogram
);
121 dict
->SetString(kConfigRuleHistogramNameKey
, histogram_name_
.c_str());
122 dict
->SetInteger(kConfigRuleHistogramValue1Key
, histogram_lower_value_
);
123 dict
->SetInteger(kConfigRuleHistogramValue2Key
, histogram_upper_value_
);
126 void OnHistogramTrigger(const std::string
& histogram_name
) const override
{
127 if (histogram_name
!= histogram_name_
)
130 content::BrowserThread::PostTask(
131 content::BrowserThread::UI
, FROM_HERE
,
133 &BackgroundTracingManagerImpl::TriggerPreemptiveFinalization
,
134 base::Unretained(BackgroundTracingManagerImpl::GetInstance())));
137 // TracingControllerImpl::TraceMessageFilterObserver implementation
138 void OnTraceMessageFilterAdded(TraceMessageFilter
* filter
) override
{
139 filter
->Send(new TracingMsg_SetUMACallback(
140 histogram_name_
, histogram_lower_value_
, histogram_upper_value_
));
143 void OnTraceMessageFilterRemoved(TraceMessageFilter
* filter
) override
{
144 filter
->Send(new TracingMsg_ClearUMACallback(histogram_name_
));
147 void OnHistogramChangedCallback(const std::string
& histogram_name
,
148 base::Histogram::Sample reference_lower_value
,
149 base::Histogram::Sample reference_upper_value
,
150 base::Histogram::Sample actual_value
) {
151 if (reference_lower_value
> actual_value
||
152 reference_upper_value
< actual_value
)
155 OnHistogramTrigger(histogram_name
);
159 std::string histogram_name_
;
160 int histogram_lower_value_
;
161 int histogram_upper_value_
;
164 class ReactiveTraceForNSOrTriggerOrFullRule
: public BackgroundTracingRule
{
166 ReactiveTraceForNSOrTriggerOrFullRule(
167 const std::string
& named_event
,
168 BackgroundTracingConfigImpl::CategoryPreset category_preset
)
169 : named_event_(named_event
), category_preset_(category_preset
) {}
171 // BackgroundTracingRule implementation
172 void IntoDict(base::DictionaryValue
* dict
) const override
{
176 BackgroundTracingConfigImpl::CategoryPresetToString(category_preset_
));
177 dict
->SetString(kConfigRuleKey
,
178 kReactiveConfigRuleTraceOnNavigationUntilTriggerOrFull
);
179 dict
->SetString(kConfigRuleTriggerNameKey
, named_event_
.c_str());
182 bool ShouldTriggerNamedEvent(const std::string
& named_event
) const override
{
183 return named_event
== named_event_
;
186 int GetReactiveTimeout() const override
{
187 return kReactiveConfigNavigationTimeout
;
190 BackgroundTracingConfigImpl::CategoryPreset
GetCategoryPreset()
192 return category_preset_
;
196 std::string named_event_
;
197 BackgroundTracingConfigImpl::CategoryPreset category_preset_
;
200 class ReactiveTraceAtRandomIntervalsRule
: public BackgroundTracingRule
{
202 ReactiveTraceAtRandomIntervalsRule(
203 BackgroundTracingConfigImpl::CategoryPreset category_preset
,
206 : category_preset_(category_preset
),
207 timeout_min_(timeout_min
),
208 timeout_max_(timeout_max
) {
209 named_event_
= GenerateUniqueName();
212 ~ReactiveTraceAtRandomIntervalsRule() override
{}
214 void IntoDict(base::DictionaryValue
* dict
) const override
{
218 BackgroundTracingConfigImpl::CategoryPresetToString(category_preset_
));
219 dict
->SetString(kConfigRuleKey
, kReactiveConfigRuleTraceAtRandomIntervals
);
220 dict
->SetInteger(kConfigRuleRandomIntervalTimeoutMin
, timeout_min_
);
221 dict
->SetInteger(kConfigRuleRandomIntervalTimeoutMax
, timeout_max_
);
224 void Install() override
{
225 handle_
= BackgroundTracingManagerImpl::GetInstance()->RegisterTriggerType(
226 named_event_
.c_str());
231 void OnStartedFinalizing(bool success
) {
238 void OnTriggerTimer() {
239 BackgroundTracingManagerImpl::GetInstance()->TriggerNamedEvent(
241 base::Bind(&ReactiveTraceAtRandomIntervalsRule::OnStartedFinalizing
,
242 base::Unretained(this)));
246 int time_to_wait
= base::RandInt(kReactiveTraceRandomStartTimeMin
,
247 kReactiveTraceRandomStartTimeMax
);
248 trigger_timer_
.Start(
249 FROM_HERE
, base::TimeDelta::FromSeconds(time_to_wait
),
250 base::Bind(&ReactiveTraceAtRandomIntervalsRule::OnTriggerTimer
,
251 base::Unretained(this)));
254 int GetReactiveTimeout() const override
{
255 return base::RandInt(timeout_min_
, timeout_max_
);
258 bool ShouldTriggerNamedEvent(const std::string
& named_event
) const override
{
259 return named_event
== named_event_
;
262 BackgroundTracingConfigImpl::CategoryPreset
GetCategoryPreset()
264 return category_preset_
;
267 std::string
GenerateUniqueName() const {
269 char work_buffer
[256];
270 base::strings::SafeSNPrintf(work_buffer
, sizeof(work_buffer
), "%s_%d",
271 kTraceAtRandomIntervalsEventName
, ids
++);
276 std::string named_event_
;
277 base::OneShotTimer
<ReactiveTraceAtRandomIntervalsRule
> trigger_timer_
;
278 BackgroundTracingConfigImpl::CategoryPreset category_preset_
;
279 BackgroundTracingManagerImpl::TriggerHandle handle_
;
286 int BackgroundTracingRule::GetReactiveTimeout() const {
290 scoped_ptr
<BackgroundTracingRule
> BackgroundTracingRule::PreemptiveRuleFromDict(
291 const base::DictionaryValue
* dict
) {
295 if (!dict
->GetString(kConfigRuleKey
, &type
))
298 if (type
== kPreemptiveConfigRuleMonitorNamed
) {
299 std::string trigger_name
;
300 if (!dict
->GetString(kConfigRuleTriggerNameKey
, &trigger_name
))
303 return scoped_ptr
<BackgroundTracingRule
>(
304 new NamedTriggerRule(trigger_name
));
307 if (type
== kPreemptiveConfigRuleMonitorHistogram
) {
308 std::string histogram_name
;
309 if (!dict
->GetString(kConfigRuleHistogramNameKey
, &histogram_name
))
312 // Check for the old naming.
314 if (dict
->GetInteger(kConfigRuleHistogramValueOldKey
, &histogram_value
))
315 return scoped_ptr
<BackgroundTracingRule
>(new HistogramRule(
316 histogram_name
, histogram_value
, std::numeric_limits
<int>::max()));
318 int histogram_lower_value
;
319 if (!dict
->GetInteger(kConfigRuleHistogramValue1Key
,
320 &histogram_lower_value
))
323 int histogram_upper_value
;
324 if (!dict
->GetInteger(kConfigRuleHistogramValue2Key
,
325 &histogram_upper_value
))
326 histogram_upper_value
= std::numeric_limits
<int>::max();
328 if (histogram_lower_value
>= histogram_upper_value
)
331 return scoped_ptr
<BackgroundTracingRule
>(new HistogramRule(
332 histogram_name
, histogram_lower_value
, histogram_upper_value
));
338 scoped_ptr
<BackgroundTracingRule
> BackgroundTracingRule::ReactiveRuleFromDict(
339 const base::DictionaryValue
* dict
,
340 BackgroundTracingConfigImpl::CategoryPreset category_preset
) {
344 if (!dict
->GetString(kConfigRuleKey
, &type
))
347 if (type
== kReactiveConfigRuleTraceOnNavigationUntilTriggerOrFull
) {
348 std::string trigger_name
;
349 if (!dict
->GetString(kConfigRuleTriggerNameKey
, &trigger_name
))
352 return scoped_ptr
<BackgroundTracingRule
>(
353 new ReactiveTraceForNSOrTriggerOrFullRule(trigger_name
,
357 if (type
== kReactiveConfigRuleTraceAtRandomIntervals
) {
359 if (!dict
->GetInteger(kConfigRuleRandomIntervalTimeoutMin
, &timeout_min
))
363 if (!dict
->GetInteger(kConfigRuleRandomIntervalTimeoutMax
, &timeout_max
))
366 if (timeout_min
> timeout_max
)
369 return scoped_ptr
<BackgroundTracingRule
>(
370 new ReactiveTraceAtRandomIntervalsRule(category_preset
, timeout_min
,
377 } // namespace content