OLD | NEW |
---|---|
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "chrome/browser/metrics/metrics_log.h" | 5 #include "chrome/browser/metrics/metrics_log.h" |
6 | 6 |
7 #include <algorithm> | 7 #include <algorithm> |
8 #include <string> | 8 #include <string> |
9 #include <vector> | 9 #include <vector> |
10 | 10 |
11 #include "base/base64.h" | 11 #include "base/base64.h" |
12 #include "base/basictypes.h" | 12 #include "base/basictypes.h" |
13 #include "base/bind.h" | 13 #include "base/bind.h" |
14 #include "base/cpu.h" | 14 #include "base/cpu.h" |
15 #include "base/memory/scoped_ptr.h" | 15 #include "base/memory/scoped_ptr.h" |
16 #include "base/prefs/pref_registry_simple.h" | 16 #include "base/prefs/pref_registry_simple.h" |
17 #include "base/prefs/pref_service.h" | 17 #include "base/prefs/pref_service.h" |
18 #include "base/profiler/alternate_timer.h" | 18 #include "base/profiler/alternate_timer.h" |
Alexei Svitkine (slow)
2014/06/02 17:30:54
Can this be removed?
blundell
2014/06/02 19:56:44
Done.
| |
19 #include "base/sha1.h" | 19 #include "base/sha1.h" |
20 #include "base/strings/string_number_conversions.h" | 20 #include "base/strings/string_number_conversions.h" |
21 #include "base/strings/string_util.h" | 21 #include "base/strings/string_util.h" |
22 #include "base/strings/utf_string_conversions.h" | 22 #include "base/strings/utf_string_conversions.h" |
23 #include "base/sys_info.h" | 23 #include "base/sys_info.h" |
24 #include "base/third_party/nspr/prtime.h" | 24 #include "base/third_party/nspr/prtime.h" |
Alexei Svitkine (slow)
2014/06/02 17:30:54
Can you check if this is still needed?
blundell
2014/06/02 19:56:44
Done.
| |
25 #include "base/time/time.h" | 25 #include "base/time/time.h" |
26 #include "base/tracked_objects.h" | |
27 #include "chrome/browser/browser_process.h" | 26 #include "chrome/browser/browser_process.h" |
Alexei Svitkine (slow)
2014/06/02 17:30:54
Also, can this include be remove too while you're
blundell
2014/06/02 19:56:44
Done.
| |
28 #include "chrome/common/pref_names.h" | 27 #include "chrome/common/pref_names.h" |
29 #include "components/metrics/metrics_provider.h" | 28 #include "components/metrics/metrics_provider.h" |
30 #include "components/metrics/metrics_service_client.h" | 29 #include "components/metrics/metrics_service_client.h" |
31 #include "components/metrics/proto/profiler_event.pb.h" | 30 #include "components/metrics/proto/profiler_event.pb.h" |
Alexei Svitkine (slow)
2014/06/02 17:30:54
Still needed?
blundell
2014/06/02 19:56:44
Done.
| |
32 #include "components/metrics/proto/system_profile.pb.h" | 31 #include "components/metrics/proto/system_profile.pb.h" |
33 #include "components/nacl/common/nacl_process_type.h" | |
34 #include "components/variations/active_field_trials.h" | 32 #include "components/variations/active_field_trials.h" |
35 #include "content/public/common/content_client.h" | |
36 #include "url/gurl.h" | 33 #include "url/gurl.h" |
Alexei Svitkine (slow)
2014/06/02 15:17:06
Nit: While you're here, can you also remove this i
blundell
2014/06/02 19:56:44
Done.
| |
37 | 34 |
38 #if defined(OS_ANDROID) | 35 #if defined(OS_ANDROID) |
39 #include "base/android/build_info.h" | 36 #include "base/android/build_info.h" |
40 #endif | 37 #endif |
41 | 38 |
42 #if defined(OS_WIN) | 39 #if defined(OS_WIN) |
43 #include "base/win/metro.h" | 40 #include "base/win/metro.h" |
44 | 41 |
45 // http://blogs.msdn.com/oldnewthing/archive/2004/10/25/247180.aspx | 42 // http://blogs.msdn.com/oldnewthing/archive/2004/10/25/247180.aspx |
46 extern "C" IMAGE_DOS_HEADER __ImageBase; | 43 extern "C" IMAGE_DOS_HEADER __ImageBase; |
47 #endif | 44 #endif |
48 | 45 |
49 using metrics::MetricsLogBase; | 46 using metrics::MetricsLogBase; |
50 using metrics::ProfilerEventProto; | 47 using metrics::ProfilerEventProto; |
51 using metrics::SystemProfileProto; | 48 using metrics::SystemProfileProto; |
52 using tracked_objects::ProcessDataSnapshot; | |
53 typedef variations::ActiveGroupId ActiveGroupId; | 49 typedef variations::ActiveGroupId ActiveGroupId; |
54 | 50 |
55 namespace { | 51 namespace { |
56 | 52 |
57 // Returns the date at which the current metrics client ID was created as | 53 // Returns the date at which the current metrics client ID was created as |
58 // a string containing seconds since the epoch, or "0" if none was found. | 54 // a string containing seconds since the epoch, or "0" if none was found. |
59 std::string GetMetricsEnabledDate(PrefService* pref) { | 55 std::string GetMetricsEnabledDate(PrefService* pref) { |
60 if (!pref) { | 56 if (!pref) { |
61 NOTREACHED(); | 57 NOTREACHED(); |
62 return "0"; | 58 return "0"; |
63 } | 59 } |
64 | 60 |
65 return pref->GetString(prefs::kMetricsReportingEnabledTimestamp); | 61 return pref->GetString(prefs::kMetricsReportingEnabledTimestamp); |
66 } | 62 } |
67 | 63 |
68 ProfilerEventProto::TrackedObject::ProcessType AsProtobufProcessType( | |
69 int process_type) { | |
70 switch (process_type) { | |
71 case content::PROCESS_TYPE_BROWSER: | |
72 return ProfilerEventProto::TrackedObject::BROWSER; | |
73 case content::PROCESS_TYPE_RENDERER: | |
74 return ProfilerEventProto::TrackedObject::RENDERER; | |
75 case content::PROCESS_TYPE_PLUGIN: | |
76 return ProfilerEventProto::TrackedObject::PLUGIN; | |
77 case content::PROCESS_TYPE_WORKER: | |
78 return ProfilerEventProto::TrackedObject::WORKER; | |
79 case content::PROCESS_TYPE_UTILITY: | |
80 return ProfilerEventProto::TrackedObject::UTILITY; | |
81 case content::PROCESS_TYPE_ZYGOTE: | |
82 return ProfilerEventProto::TrackedObject::ZYGOTE; | |
83 case content::PROCESS_TYPE_SANDBOX_HELPER: | |
84 return ProfilerEventProto::TrackedObject::SANDBOX_HELPER; | |
85 case content::PROCESS_TYPE_GPU: | |
86 return ProfilerEventProto::TrackedObject::GPU; | |
87 case content::PROCESS_TYPE_PPAPI_PLUGIN: | |
88 return ProfilerEventProto::TrackedObject::PPAPI_PLUGIN; | |
89 case content::PROCESS_TYPE_PPAPI_BROKER: | |
90 return ProfilerEventProto::TrackedObject::PPAPI_BROKER; | |
91 case PROCESS_TYPE_NACL_LOADER: | |
92 return ProfilerEventProto::TrackedObject::NACL_LOADER; | |
93 case PROCESS_TYPE_NACL_BROKER: | |
94 return ProfilerEventProto::TrackedObject::NACL_BROKER; | |
95 default: | |
96 NOTREACHED(); | |
97 return ProfilerEventProto::TrackedObject::UNKNOWN; | |
98 } | |
99 } | |
100 | |
101 // Computes a SHA-1 hash of |data| and returns it as a hex string. | 64 // Computes a SHA-1 hash of |data| and returns it as a hex string. |
102 std::string ComputeSHA1(const std::string& data) { | 65 std::string ComputeSHA1(const std::string& data) { |
103 const std::string sha1 = base::SHA1HashString(data); | 66 const std::string sha1 = base::SHA1HashString(data); |
104 return base::HexEncode(sha1.data(), sha1.size()); | 67 return base::HexEncode(sha1.data(), sha1.size()); |
105 } | 68 } |
106 | 69 |
107 void WriteFieldTrials(const std::vector<ActiveGroupId>& field_trial_ids, | 70 void WriteFieldTrials(const std::vector<ActiveGroupId>& field_trial_ids, |
108 SystemProfileProto* system_profile) { | 71 SystemProfileProto* system_profile) { |
109 for (std::vector<ActiveGroupId>::const_iterator it = | 72 for (std::vector<ActiveGroupId>::const_iterator it = |
110 field_trial_ids.begin(); it != field_trial_ids.end(); ++it) { | 73 field_trial_ids.begin(); it != field_trial_ids.end(); ++it) { |
111 SystemProfileProto::FieldTrial* field_trial = | 74 SystemProfileProto::FieldTrial* field_trial = |
112 system_profile->add_field_trial(); | 75 system_profile->add_field_trial(); |
113 field_trial->set_name_id(it->name); | 76 field_trial->set_name_id(it->name); |
114 field_trial->set_group_id(it->group); | 77 field_trial->set_group_id(it->group); |
115 } | 78 } |
116 } | 79 } |
117 | 80 |
118 // Maps a thread name by replacing trailing sequence of digits with "*". | |
119 // Examples: | |
120 // 1. "BrowserBlockingWorker1/23857" => "BrowserBlockingWorker1/*" | |
121 // 2. "Chrome_IOThread" => "Chrome_IOThread" | |
122 std::string MapThreadName(const std::string& thread_name) { | |
123 size_t i = thread_name.length(); | |
124 | |
125 while (i > 0 && isdigit(thread_name[i - 1])) { | |
126 --i; | |
127 } | |
128 | |
129 if (i == thread_name.length()) | |
130 return thread_name; | |
131 | |
132 return thread_name.substr(0, i) + '*'; | |
133 } | |
134 | |
135 // Normalizes a source filename (which is platform- and build-method-dependent) | |
136 // by extracting the last component of the full file name. | |
137 // Example: "c:\b\build\slave\win\build\src\chrome\app\chrome_main.cc" => | |
138 // "chrome_main.cc". | |
139 std::string NormalizeFileName(const std::string& file_name) { | |
140 const size_t offset = file_name.find_last_of("\\/"); | |
141 return offset != std::string::npos ? file_name.substr(offset + 1) : file_name; | |
142 } | |
143 | |
144 void WriteProfilerData(const ProcessDataSnapshot& profiler_data, | |
145 int process_type, | |
146 ProfilerEventProto* performance_profile) { | |
147 for (std::vector<tracked_objects::TaskSnapshot>::const_iterator it = | |
148 profiler_data.tasks.begin(); | |
149 it != profiler_data.tasks.end(); ++it) { | |
150 const tracked_objects::DeathDataSnapshot& death_data = it->death_data; | |
151 ProfilerEventProto::TrackedObject* tracked_object = | |
152 performance_profile->add_tracked_object(); | |
153 tracked_object->set_birth_thread_name_hash( | |
154 MetricsLogBase::Hash(MapThreadName(it->birth.thread_name))); | |
155 tracked_object->set_exec_thread_name_hash( | |
156 MetricsLogBase::Hash(MapThreadName(it->death_thread_name))); | |
157 tracked_object->set_source_file_name_hash( | |
158 MetricsLogBase::Hash(NormalizeFileName(it->birth.location.file_name))); | |
159 tracked_object->set_source_function_name_hash( | |
160 MetricsLogBase::Hash(it->birth.location.function_name)); | |
161 tracked_object->set_source_line_number(it->birth.location.line_number); | |
162 tracked_object->set_exec_count(death_data.count); | |
163 tracked_object->set_exec_time_total(death_data.run_duration_sum); | |
164 tracked_object->set_exec_time_sampled(death_data.run_duration_sample); | |
165 tracked_object->set_queue_time_total(death_data.queue_duration_sum); | |
166 tracked_object->set_queue_time_sampled(death_data.queue_duration_sample); | |
167 tracked_object->set_process_type(AsProtobufProcessType(process_type)); | |
168 tracked_object->set_process_id(profiler_data.process_id); | |
169 } | |
170 } | |
171 | |
172 // Round a timestamp measured in seconds since epoch to one with a granularity | 81 // Round a timestamp measured in seconds since epoch to one with a granularity |
173 // of an hour. This can be used before uploaded potentially sensitive | 82 // of an hour. This can be used before uploaded potentially sensitive |
174 // timestamps. | 83 // timestamps. |
175 int64 RoundSecondsToHour(int64 time_in_seconds) { | 84 int64 RoundSecondsToHour(int64 time_in_seconds) { |
176 return 3600 * (time_in_seconds / 3600); | 85 return 3600 * (time_in_seconds / 3600); |
177 } | 86 } |
178 | 87 |
179 } // namespace | 88 } // namespace |
180 | 89 |
181 MetricsLog::MetricsLog(const std::string& client_id, | 90 MetricsLog::MetricsLog(const std::string& client_id, |
(...skipping 219 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
401 local_state->ClearPref(prefs::kStabilitySavedSystemProfile); | 310 local_state->ClearPref(prefs::kStabilitySavedSystemProfile); |
402 local_state->ClearPref(prefs::kStabilitySavedSystemProfileHash); | 311 local_state->ClearPref(prefs::kStabilitySavedSystemProfileHash); |
403 | 312 |
404 SystemProfileProto* system_profile = uma_proto()->mutable_system_profile(); | 313 SystemProfileProto* system_profile = uma_proto()->mutable_system_profile(); |
405 std::string serialied_system_profile; | 314 std::string serialied_system_profile; |
406 return base::Base64Decode(base64_system_profile, &serialied_system_profile) && | 315 return base::Base64Decode(base64_system_profile, &serialied_system_profile) && |
407 ComputeSHA1(serialied_system_profile) == system_profile_hash && | 316 ComputeSHA1(serialied_system_profile) == system_profile_hash && |
408 system_profile->ParseFromString(serialied_system_profile); | 317 system_profile->ParseFromString(serialied_system_profile); |
409 } | 318 } |
410 | 319 |
411 void MetricsLog::RecordProfilerData( | |
412 const tracked_objects::ProcessDataSnapshot& process_data, | |
413 int process_type) { | |
414 DCHECK(!locked()); | |
415 | |
416 if (tracked_objects::GetTimeSourceType() != | |
417 tracked_objects::TIME_SOURCE_TYPE_WALL_TIME) { | |
418 // We currently only support the default time source, wall clock time. | |
419 return; | |
420 } | |
421 | |
422 ProfilerEventProto* profile; | |
423 if (!uma_proto()->profiler_event_size()) { | |
424 // For the first process's data, add a new field to the protocol buffer. | |
425 profile = uma_proto()->add_profiler_event(); | |
426 profile->set_profile_type(ProfilerEventProto::STARTUP_PROFILE); | |
427 profile->set_time_source(ProfilerEventProto::WALL_CLOCK_TIME); | |
428 } else { | |
429 // For the remaining calls, re-use the existing field. | |
430 profile = uma_proto()->mutable_profiler_event(0); | |
431 } | |
432 | |
433 WriteProfilerData(process_data, process_type, profile); | |
434 } | |
OLD | NEW |