1 // Copyright 2014 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.
5 #include "components/metrics/profiler/profiler_metrics_provider.h"
11 #include "base/tracked_objects.h"
12 #include "components/metrics/metrics_log.h"
13 #include "components/nacl/common/nacl_process_type.h"
14 #include "components/variations/variations_associated_data.h"
15 #include "content/public/common/process_type.h"
17 using tracked_objects::ProcessDataSnapshot
;
23 ProfilerEventProto::TrackedObject::ProcessType
AsProtobufProcessType(
25 switch (process_type
) {
26 case content::PROCESS_TYPE_BROWSER
:
27 return ProfilerEventProto::TrackedObject::BROWSER
;
28 case content::PROCESS_TYPE_RENDERER
:
29 return ProfilerEventProto::TrackedObject::RENDERER
;
30 case content::PROCESS_TYPE_PLUGIN
:
31 return ProfilerEventProto::TrackedObject::PLUGIN
;
32 case content::PROCESS_TYPE_UTILITY
:
33 return ProfilerEventProto::TrackedObject::UTILITY
;
34 case content::PROCESS_TYPE_ZYGOTE
:
35 return ProfilerEventProto::TrackedObject::ZYGOTE
;
36 case content::PROCESS_TYPE_SANDBOX_HELPER
:
37 return ProfilerEventProto::TrackedObject::SANDBOX_HELPER
;
38 case content::PROCESS_TYPE_GPU
:
39 return ProfilerEventProto::TrackedObject::GPU
;
40 case content::PROCESS_TYPE_PPAPI_PLUGIN
:
41 return ProfilerEventProto::TrackedObject::PPAPI_PLUGIN
;
42 case content::PROCESS_TYPE_PPAPI_BROKER
:
43 return ProfilerEventProto::TrackedObject::PPAPI_BROKER
;
44 case PROCESS_TYPE_NACL_LOADER
:
45 return ProfilerEventProto::TrackedObject::NACL_LOADER
;
46 case PROCESS_TYPE_NACL_BROKER
:
47 return ProfilerEventProto::TrackedObject::NACL_BROKER
;
50 return ProfilerEventProto::TrackedObject::UNKNOWN
;
54 // Maps a thread name by replacing trailing sequence of digits with "*".
56 // 1. "BrowserBlockingWorker1/23857" => "BrowserBlockingWorker1/*"
57 // 2. "Chrome_IOThread" => "Chrome_IOThread"
58 std::string
MapThreadName(const std::string
& thread_name
) {
59 size_t i
= thread_name
.length();
61 while (i
> 0 && isdigit(thread_name
[i
- 1])) {
65 if (i
== thread_name
.length())
68 return thread_name
.substr(0, i
) + '*';
71 // Normalizes a source filename (which is platform- and build-method-dependent)
72 // by extracting the last component of the full file name.
73 // Example: "c:\b\build\slave\win\build\src\chrome\app\chrome_main.cc" =>
75 std::string
NormalizeFileName(const std::string
& file_name
) {
76 const size_t offset
= file_name
.find_last_of("\\/");
77 return offset
!= std::string::npos
? file_name
.substr(offset
+ 1) : file_name
;
80 void WriteProfilerData(const ProcessDataSnapshot
& profiler_data
,
82 ProfilerEventProto
* performance_profile
) {
83 for (std::vector
<tracked_objects::TaskSnapshot
>::const_iterator it
=
84 profiler_data
.tasks
.begin();
85 it
!= profiler_data
.tasks
.end();
87 const tracked_objects::DeathDataSnapshot
& death_data
= it
->death_data
;
88 ProfilerEventProto::TrackedObject
* tracked_object
=
89 performance_profile
->add_tracked_object();
90 tracked_object
->set_birth_thread_name_hash(
91 MetricsLog::Hash(MapThreadName(it
->birth
.thread_name
)));
92 tracked_object
->set_exec_thread_name_hash(
93 MetricsLog::Hash(MapThreadName(it
->death_thread_name
)));
94 tracked_object
->set_source_file_name_hash(
95 MetricsLog::Hash(NormalizeFileName(
96 it
->birth
.location
.file_name
)));
97 tracked_object
->set_source_function_name_hash(
98 MetricsLog::Hash(it
->birth
.location
.function_name
));
99 tracked_object
->set_source_line_number(it
->birth
.location
.line_number
);
100 tracked_object
->set_exec_count(death_data
.count
);
101 tracked_object
->set_exec_time_total(death_data
.run_duration_sum
);
102 tracked_object
->set_exec_time_sampled(death_data
.run_duration_sample
);
103 tracked_object
->set_queue_time_total(death_data
.queue_duration_sum
);
104 tracked_object
->set_queue_time_sampled(death_data
.queue_duration_sample
);
105 tracked_object
->set_process_type(AsProtobufProcessType(process_type
));
106 tracked_object
->set_process_id(profiler_data
.process_id
);
110 // Returns true if the user is assigned to the experiment group for enabled
112 bool IsCellularEnabledByExperiment() {
113 const std::string group_name
=
114 base::FieldTrialList::FindFullName("UMA_EnableCellularLogUpload");
115 return group_name
== "Enabled";
120 ProfilerMetricsProvider::ProfilerMetricsProvider() : has_profiler_data_(false) {
123 ProfilerMetricsProvider::ProfilerMetricsProvider(
124 const base::Callback
<void(bool*)>& cellular_callback
)
125 : has_profiler_data_(false), cellular_callback_(cellular_callback
) {
128 ProfilerMetricsProvider::~ProfilerMetricsProvider() {
131 void ProfilerMetricsProvider::ProvideGeneralMetrics(
132 ChromeUserMetricsExtension
* uma_proto
) {
133 if (!has_profiler_data_
)
136 DCHECK_EQ(tracked_objects::TIME_SOURCE_TYPE_WALL_TIME
,
137 tracked_objects::GetTimeSourceType());
139 DCHECK_EQ(0, uma_proto
->profiler_event_size());
140 ProfilerEventProto
* profile
= uma_proto
->add_profiler_event();
141 profile
->Swap(&profiler_event_cache_
);
142 has_profiler_data_
= false;
145 void ProfilerMetricsProvider::RecordProfilerData(
146 const tracked_objects::ProcessDataSnapshot
& process_data
,
148 if (IsCellularConnection() && IsCellularEnabledByExperiment())
150 if (tracked_objects::GetTimeSourceType() !=
151 tracked_objects::TIME_SOURCE_TYPE_WALL_TIME
) {
152 // We currently only support the default time source, wall clock time.
156 has_profiler_data_
= true;
157 profiler_event_cache_
.set_profile_version(
158 ProfilerEventProto::VERSION_STARTUP_PROFILE
);
159 profiler_event_cache_
.set_time_source(ProfilerEventProto::WALL_CLOCK_TIME
);
160 WriteProfilerData(process_data
, process_type
, &profiler_event_cache_
);
163 bool ProfilerMetricsProvider::IsCellularConnection() {
164 bool is_cellular
= false;
165 // For android get current connection type from NetworkMetricsProvider if the
167 #if defined(OS_ANDROID)
168 if (!cellular_callback_
.is_null())
169 cellular_callback_
.Run(&is_cellular
);
174 } // namespace metrics