Roll src/third_party/WebKit eac3800:0237a66 (svn 202606:202607)
[chromium-blink-merge.git] / content / browser / tracing / background_tracing_rule.cc
blob473e3d3d943365b97ec85e631c3d8455bbb07829
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"
6 #include <string>
8 #include "base/bind.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"
19 namespace {
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;
52 } // namespace
54 namespace content {
56 BackgroundTracingRule::BackgroundTracingRule() {}
58 BackgroundTracingRule::~BackgroundTracingRule() {}
60 bool BackgroundTracingRule::ShouldTriggerNamedEvent(
61 const std::string& named_event) const {
62 return false;
65 BackgroundTracingConfigImpl::CategoryPreset
66 BackgroundTracingRule::GetCategoryPreset() const {
67 return BackgroundTracingConfigImpl::BENCHMARK;
70 namespace {
72 class NamedTriggerRule : public BackgroundTracingRule {
73 public:
74 NamedTriggerRule(const std::string& named_event)
75 : named_event_(named_event) {}
77 void IntoDict(base::DictionaryValue* dict) const override {
78 DCHECK(dict);
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_;
87 private:
88 std::string named_event_;
91 class HistogramRule : public BackgroundTracingRule,
92 public TracingControllerImpl::TraceMessageFilterObserver {
93 public:
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(
104 this);
107 // BackgroundTracingRule implementation
108 void Install() override {
109 base::StatisticsRecorder::SetCallback(
110 histogram_name_,
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 {
119 DCHECK(dict);
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_)
128 return;
130 content::BrowserThread::PostTask(
131 content::BrowserThread::UI, FROM_HERE,
132 base::Bind(
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)
153 return;
155 OnHistogramTrigger(histogram_name);
158 private:
159 std::string histogram_name_;
160 int histogram_lower_value_;
161 int histogram_upper_value_;
164 class ReactiveTraceForNSOrTriggerOrFullRule : public BackgroundTracingRule {
165 public:
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 {
173 DCHECK(dict);
174 dict->SetString(
175 kConfigCategoryKey,
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()
191 const override {
192 return category_preset_;
195 private:
196 std::string named_event_;
197 BackgroundTracingConfigImpl::CategoryPreset category_preset_;
200 class ReactiveTraceAtRandomIntervalsRule : public BackgroundTracingRule {
201 public:
202 ReactiveTraceAtRandomIntervalsRule(
203 BackgroundTracingConfigImpl::CategoryPreset category_preset,
204 int timeout_min,
205 int timeout_max)
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 {
215 DCHECK(dict);
216 dict->SetString(
217 kConfigCategoryKey,
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());
228 StartTimer();
231 void OnStartedFinalizing(bool success) {
232 if (!success)
233 return;
235 StartTimer();
238 void OnTriggerTimer() {
239 BackgroundTracingManagerImpl::GetInstance()->TriggerNamedEvent(
240 handle_,
241 base::Bind(&ReactiveTraceAtRandomIntervalsRule::OnStartedFinalizing,
242 base::Unretained(this)));
245 void StartTimer() {
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()
263 const override {
264 return category_preset_;
267 std::string GenerateUniqueName() const {
268 static int ids = 0;
269 char work_buffer[256];
270 base::strings::SafeSNPrintf(work_buffer, sizeof(work_buffer), "%s_%d",
271 kTraceAtRandomIntervalsEventName, ids++);
272 return work_buffer;
275 private:
276 std::string named_event_;
277 base::OneShotTimer<ReactiveTraceAtRandomIntervalsRule> trigger_timer_;
278 BackgroundTracingConfigImpl::CategoryPreset category_preset_;
279 BackgroundTracingManagerImpl::TriggerHandle handle_;
280 int timeout_min_;
281 int timeout_max_;
284 } // namespace
286 int BackgroundTracingRule::GetReactiveTimeout() const {
287 return -1;
290 scoped_ptr<BackgroundTracingRule> BackgroundTracingRule::PreemptiveRuleFromDict(
291 const base::DictionaryValue* dict) {
292 DCHECK(dict);
294 std::string type;
295 if (!dict->GetString(kConfigRuleKey, &type))
296 return nullptr;
298 if (type == kPreemptiveConfigRuleMonitorNamed) {
299 std::string trigger_name;
300 if (!dict->GetString(kConfigRuleTriggerNameKey, &trigger_name))
301 return nullptr;
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))
310 return nullptr;
312 // Check for the old naming.
313 int histogram_value;
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))
321 return nullptr;
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)
329 return nullptr;
331 return scoped_ptr<BackgroundTracingRule>(new HistogramRule(
332 histogram_name, histogram_lower_value, histogram_upper_value));
335 return nullptr;
338 scoped_ptr<BackgroundTracingRule> BackgroundTracingRule::ReactiveRuleFromDict(
339 const base::DictionaryValue* dict,
340 BackgroundTracingConfigImpl::CategoryPreset category_preset) {
341 DCHECK(dict);
343 std::string type;
344 if (!dict->GetString(kConfigRuleKey, &type))
345 return nullptr;
347 if (type == kReactiveConfigRuleTraceOnNavigationUntilTriggerOrFull) {
348 std::string trigger_name;
349 if (!dict->GetString(kConfigRuleTriggerNameKey, &trigger_name))
350 return nullptr;
352 return scoped_ptr<BackgroundTracingRule>(
353 new ReactiveTraceForNSOrTriggerOrFullRule(trigger_name,
354 category_preset));
357 if (type == kReactiveConfigRuleTraceAtRandomIntervals) {
358 int timeout_min;
359 if (!dict->GetInteger(kConfigRuleRandomIntervalTimeoutMin, &timeout_min))
360 return nullptr;
362 int timeout_max;
363 if (!dict->GetInteger(kConfigRuleRandomIntervalTimeoutMax, &timeout_max))
364 return nullptr;
366 if (timeout_min > timeout_max)
367 return nullptr;
369 return scoped_ptr<BackgroundTracingRule>(
370 new ReactiveTraceAtRandomIntervalsRule(category_preset, timeout_min,
371 timeout_max));
374 return nullptr;
377 } // namespace content