blob: 05bb1739dd0c2678dfe72eac4a8f8bb0383555d8 [file] [log] [blame]
[email protected]1df44b72012-01-19 05:20:341// Copyright (c) 2012 The Chromium Authors. All rights reserved.
license.botbf09a502008-08-24 00:55:552// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
initial.commit09911bf2008-07-26 23:55:294
[email protected]cd1adc22009-01-16 01:29:225#include "chrome/browser/metrics/metrics_log.h"
initial.commit09911bf2008-07-26 23:55:296
[email protected]76869ff2013-01-15 16:13:477#include <algorithm>
[email protected]1eeb5e02010-07-20 23:02:118#include <string>
9#include <vector>
10
[email protected]0f2f7792013-11-28 16:09:1411#include "base/base64.h"
[email protected]d1be67b2008-11-19 20:28:3812#include "base/basictypes.h"
[email protected]611ae29a2013-04-29 21:32:1913#include "base/bind.h"
[email protected]5c8f89f692013-07-18 11:13:2814#include "base/cpu.h"
[email protected]3b63f8f42011-03-28 01:54:1515#include "base/memory/scoped_ptr.h"
[email protected]3853a4c2013-02-11 17:15:5716#include "base/prefs/pref_registry_simple.h"
17#include "base/prefs/pref_service.h"
[email protected]ed0fd002012-04-25 23:10:3418#include "base/profiler/alternate_timer.h"
[email protected]0f2f7792013-11-28 16:09:1419#include "base/sha1.h"
[email protected]3ea1b182013-02-08 22:38:4120#include "base/strings/string_number_conversions.h"
[email protected]f9b294362013-06-10 20:22:3121#include "base/strings/string_util.h"
[email protected]112158af2013-06-07 23:46:1822#include "base/strings/utf_string_conversions.h"
[email protected]fadf97f2008-09-18 12:18:1423#include "base/sys_info.h"
[email protected]37f39e42010-01-06 17:35:1724#include "base/third_party/nspr/prtime.h"
[email protected]84813472013-06-28 00:25:1925#include "base/time/time.h"
[email protected]ed0fd002012-04-25 23:10:3426#include "base/tracked_objects.h"
initial.commit09911bf2008-07-26 23:55:2927#include "chrome/browser/browser_process.h"
[email protected]b84ee6e2014-03-15 22:51:5428#include "chrome/browser/metrics/extension_metrics.h"
[email protected]0f5e57f52012-09-20 20:53:1829#include "chrome/browser/plugins/plugin_prefs.h"
[email protected]10084982011-08-19 17:56:5630#include "chrome/browser/profiles/profile_manager.h"
initial.commit09911bf2008-07-26 23:55:2931#include "chrome/common/pref_names.h"
[email protected]85791b0b2014-05-20 15:18:5832#include "components/metrics/metrics_provider.h"
[email protected]09dee82d2014-05-22 14:00:5333#include "components/metrics/metrics_service_client.h"
[email protected]064107e2014-05-02 00:59:0634#include "components/metrics/proto/profiler_event.pb.h"
35#include "components/metrics/proto/system_profile.pb.h"
[email protected]d5d383252013-07-04 14:44:3236#include "components/nacl/common/nacl_process_type.h"
[email protected]b3610d42014-05-19 18:07:2337#include "components/variations/active_field_trials.h"
[email protected]79078df2012-02-16 01:22:3238#include "content/public/browser/gpu_data_manager.h"
[email protected]1a838cc2012-04-24 22:06:4939#include "content/public/common/content_client.h"
[email protected]d7bd3e52013-07-21 04:29:2040#include "content/public/common/webplugininfo.h"
[email protected]d7b5cc72013-05-23 20:05:0041#include "gpu/config/gpu_info.h"
[email protected]6b7d954ff2011-10-25 00:39:3542#include "ui/gfx/screen.h"
[email protected]761fa4702013-07-02 15:25:1543#include "url/gurl.h"
initial.commit09911bf2008-07-26 23:55:2944
[email protected]5106b3a2012-10-03 20:10:4445#if defined(OS_ANDROID)
46#include "base/android/build_info.h"
47#endif
48
[email protected]d1be67b2008-11-19 20:28:3849#if defined(OS_WIN)
[email protected]1bb25e02012-08-03 22:39:3950#include "base/win/metro.h"
51
52// http://blogs.msdn.com/oldnewthing/archive/2004/10/25/247180.aspx
[email protected]d1be67b2008-11-19 20:28:3853extern "C" IMAGE_DOS_HEADER __ImageBase;
54#endif
55
[email protected]afc03f02013-10-11 06:01:3556#if defined(OS_CHROMEOS)
[email protected]c9afed6e2014-02-03 22:12:2957#include "chrome/browser/metrics/metrics_log_chromeos.h"
58#endif // OS_CHROMEOS
[email protected]afc03f02013-10-11 06:01:3559
[email protected]79078df2012-02-16 01:22:3260using content::GpuDataManager;
[email protected]064107e2014-05-02 00:59:0661using metrics::MetricsLogBase;
[email protected]ed0fd002012-04-25 23:10:3462using metrics::ProfilerEventProto;
[email protected]fe58acc22012-02-29 01:29:5863using metrics::SystemProfileProto;
[email protected]ed0fd002012-04-25 23:10:3464using tracked_objects::ProcessDataSnapshot;
[email protected]b3610d42014-05-19 18:07:2365typedef variations::ActiveGroupId ActiveGroupId;
[email protected]79078df2012-02-16 01:22:3266
[email protected]1df44b72012-01-19 05:20:3467namespace {
68
69// Returns the date at which the current metrics client ID was created as
[email protected]ca5ac4b2012-12-14 07:46:4070// a string containing seconds since the epoch, or "0" if none was found.
[email protected]cc5d7f42012-10-30 00:30:0971std::string GetMetricsEnabledDate(PrefService* pref) {
[email protected]767c9d92012-03-02 16:04:3472 if (!pref) {
[email protected]1df44b72012-01-19 05:20:3473 NOTREACHED();
74 return "0";
75 }
[email protected]767c9d92012-03-02 16:04:3476
[email protected]1f74e802014-03-29 03:08:3577 return pref->GetString(prefs::kMetricsReportingEnabledTimestamp);
[email protected]1df44b72012-01-19 05:20:3478}
79
[email protected]ed0fd002012-04-25 23:10:3480ProfilerEventProto::TrackedObject::ProcessType AsProtobufProcessType(
[email protected]f3b357692013-03-22 05:16:1381 int process_type) {
[email protected]ed0fd002012-04-25 23:10:3482 switch (process_type) {
83 case content::PROCESS_TYPE_BROWSER:
84 return ProfilerEventProto::TrackedObject::BROWSER;
85 case content::PROCESS_TYPE_RENDERER:
86 return ProfilerEventProto::TrackedObject::RENDERER;
87 case content::PROCESS_TYPE_PLUGIN:
88 return ProfilerEventProto::TrackedObject::PLUGIN;
89 case content::PROCESS_TYPE_WORKER:
90 return ProfilerEventProto::TrackedObject::WORKER;
[email protected]ed0fd002012-04-25 23:10:3491 case content::PROCESS_TYPE_UTILITY:
92 return ProfilerEventProto::TrackedObject::UTILITY;
[email protected]ed0fd002012-04-25 23:10:3493 case content::PROCESS_TYPE_ZYGOTE:
94 return ProfilerEventProto::TrackedObject::ZYGOTE;
95 case content::PROCESS_TYPE_SANDBOX_HELPER:
96 return ProfilerEventProto::TrackedObject::SANDBOX_HELPER;
[email protected]ed0fd002012-04-25 23:10:3497 case content::PROCESS_TYPE_GPU:
98 return ProfilerEventProto::TrackedObject::GPU;
99 case content::PROCESS_TYPE_PPAPI_PLUGIN:
100 return ProfilerEventProto::TrackedObject::PPAPI_PLUGIN;
101 case content::PROCESS_TYPE_PPAPI_BROKER:
102 return ProfilerEventProto::TrackedObject::PPAPI_BROKER;
[email protected]f3b357692013-03-22 05:16:13103 case PROCESS_TYPE_NACL_LOADER:
104 return ProfilerEventProto::TrackedObject::NACL_LOADER;
105 case PROCESS_TYPE_NACL_BROKER:
106 return ProfilerEventProto::TrackedObject::NACL_BROKER;
[email protected]ed0fd002012-04-25 23:10:34107 default:
108 NOTREACHED();
109 return ProfilerEventProto::TrackedObject::UNKNOWN;
110 }
111}
112
[email protected]0f2f7792013-11-28 16:09:14113// Computes a SHA-1 hash of |data| and returns it as a hex string.
114std::string ComputeSHA1(const std::string& data) {
115 const std::string sha1 = base::SHA1HashString(data);
116 return base::HexEncode(sha1.data(), sha1.size());
117}
118
[email protected]1d51882f2013-11-12 01:59:02119#if defined(ENABLE_PLUGINS)
[email protected]1df44b72012-01-19 05:20:34120// Returns the plugin preferences corresponding for this user, if available.
121// If multiple user profiles are loaded, returns the preferences corresponding
122// to an arbitrary one of the profiles.
123PluginPrefs* GetPluginPrefs() {
124 ProfileManager* profile_manager = g_browser_process->profile_manager();
[email protected]fe58acc22012-02-29 01:29:58125
126 if (!profile_manager) {
127 // The profile manager can be NULL when testing.
128 return NULL;
129 }
130
[email protected]1df44b72012-01-19 05:20:34131 std::vector<Profile*> profiles = profile_manager->GetLoadedProfiles();
132 if (profiles.empty())
133 return NULL;
134
[email protected]cadac622013-06-11 16:46:36135 return PluginPrefs::GetForProfile(profiles.front()).get();
[email protected]1df44b72012-01-19 05:20:34136}
137
[email protected]fe58acc22012-02-29 01:29:58138// Fills |plugin| with the info contained in |plugin_info| and |plugin_prefs|.
[email protected]d7bd3e52013-07-21 04:29:20139void SetPluginInfo(const content::WebPluginInfo& plugin_info,
[email protected]fe58acc22012-02-29 01:29:58140 const PluginPrefs* plugin_prefs,
141 SystemProfileProto::Plugin* plugin) {
[email protected]6778fed2013-12-24 20:09:37142 plugin->set_name(base::UTF16ToUTF8(plugin_info.name));
[email protected]fe58acc22012-02-29 01:29:58143 plugin->set_filename(plugin_info.path.BaseName().AsUTF8Unsafe());
[email protected]6778fed2013-12-24 20:09:37144 plugin->set_version(base::UTF16ToUTF8(plugin_info.version));
[email protected]4e3ca1c292013-09-10 01:59:19145 plugin->set_is_pepper(plugin_info.is_pepper_plugin());
[email protected]fe58acc22012-02-29 01:29:58146 if (plugin_prefs)
147 plugin->set_is_disabled(!plugin_prefs->IsPluginEnabled(plugin_info));
148}
[email protected]1d51882f2013-11-12 01:59:02149#endif // defined(ENABLE_PLUGINS)
[email protected]fe58acc22012-02-29 01:29:58150
[email protected]0c8b7ad2012-11-06 07:08:14151void WriteFieldTrials(const std::vector<ActiveGroupId>& field_trial_ids,
[email protected]767c9d92012-03-02 16:04:34152 SystemProfileProto* system_profile) {
[email protected]0c8b7ad2012-11-06 07:08:14153 for (std::vector<ActiveGroupId>::const_iterator it =
[email protected]ad2461c2012-04-27 21:11:03154 field_trial_ids.begin(); it != field_trial_ids.end(); ++it) {
[email protected]767c9d92012-03-02 16:04:34155 SystemProfileProto::FieldTrial* field_trial =
156 system_profile->add_field_trial();
157 field_trial->set_name_id(it->name);
158 field_trial->set_group_id(it->group);
159 }
160}
161
[email protected]0018f722014-02-08 03:08:51162// Maps a thread name by replacing trailing sequence of digits with "*".
163// Examples:
164// 1. "BrowserBlockingWorker1/23857" => "BrowserBlockingWorker1/*"
165// 2. "Chrome_IOThread" => "Chrome_IOThread"
166std::string MapThreadName(const std::string& thread_name) {
167 size_t i = thread_name.length();
168
169 while (i > 0 && isdigit(thread_name[i - 1])) {
170 --i;
171 }
172
173 if (i == thread_name.length())
174 return thread_name;
175
176 return thread_name.substr(0, i) + '*';
177}
178
[email protected]87b9bf12014-04-03 15:25:00179// Normalizes a source filename (which is platform- and build-method-dependent)
180// by extracting the last component of the full file name.
181// Example: "c:\b\build\slave\win\build\src\chrome\app\chrome_main.cc" =>
182// "chrome_main.cc".
183std::string NormalizeFileName(const std::string& file_name) {
184 const size_t offset = file_name.find_last_of("\\/");
185 return offset != std::string::npos ? file_name.substr(offset + 1) : file_name;
186}
187
[email protected]ed0fd002012-04-25 23:10:34188void WriteProfilerData(const ProcessDataSnapshot& profiler_data,
[email protected]f3b357692013-03-22 05:16:13189 int process_type,
[email protected]ed0fd002012-04-25 23:10:34190 ProfilerEventProto* performance_profile) {
191 for (std::vector<tracked_objects::TaskSnapshot>::const_iterator it =
192 profiler_data.tasks.begin();
193 it != profiler_data.tasks.end(); ++it) {
[email protected]ed0fd002012-04-25 23:10:34194 const tracked_objects::DeathDataSnapshot& death_data = it->death_data;
195 ProfilerEventProto::TrackedObject* tracked_object =
196 performance_profile->add_tracked_object();
[email protected]db7fec832013-07-18 09:41:41197 tracked_object->set_birth_thread_name_hash(
[email protected]0018f722014-02-08 03:08:51198 MetricsLogBase::Hash(MapThreadName(it->birth.thread_name)));
[email protected]db7fec832013-07-18 09:41:41199 tracked_object->set_exec_thread_name_hash(
[email protected]0018f722014-02-08 03:08:51200 MetricsLogBase::Hash(MapThreadName(it->death_thread_name)));
[email protected]db7fec832013-07-18 09:41:41201 tracked_object->set_source_file_name_hash(
[email protected]87b9bf12014-04-03 15:25:00202 MetricsLogBase::Hash(NormalizeFileName(it->birth.location.file_name)));
[email protected]db7fec832013-07-18 09:41:41203 tracked_object->set_source_function_name_hash(
204 MetricsLogBase::Hash(it->birth.location.function_name));
[email protected]ed0fd002012-04-25 23:10:34205 tracked_object->set_source_line_number(it->birth.location.line_number);
206 tracked_object->set_exec_count(death_data.count);
207 tracked_object->set_exec_time_total(death_data.run_duration_sum);
208 tracked_object->set_exec_time_sampled(death_data.run_duration_sample);
209 tracked_object->set_queue_time_total(death_data.queue_duration_sum);
210 tracked_object->set_queue_time_sampled(death_data.queue_duration_sample);
211 tracked_object->set_process_type(AsProtobufProcessType(process_type));
212 tracked_object->set_process_id(profiler_data.process_id);
213 }
214}
215
[email protected]76869ff2013-01-15 16:13:47216#if defined(OS_WIN)
[email protected]ffaf7322013-05-15 00:26:11217struct ScreenDPIInformation {
[email protected]76869ff2013-01-15 16:13:47218 double max_dpi_x;
219 double max_dpi_y;
220};
221
222// Called once for each connected monitor.
223BOOL CALLBACK GetMonitorDPICallback(HMONITOR, HDC hdc, LPRECT, LPARAM dwData) {
224 const double kMillimetersPerInch = 25.4;
225 ScreenDPIInformation* screen_info =
226 reinterpret_cast<ScreenDPIInformation*>(dwData);
227 // Size of screen, in mm.
228 DWORD size_x = GetDeviceCaps(hdc, HORZSIZE);
229 DWORD size_y = GetDeviceCaps(hdc, VERTSIZE);
230 double dpi_x = (size_x > 0) ?
231 GetDeviceCaps(hdc, HORZRES) / (size_x / kMillimetersPerInch) : 0;
232 double dpi_y = (size_y > 0) ?
233 GetDeviceCaps(hdc, VERTRES) / (size_y / kMillimetersPerInch) : 0;
234 screen_info->max_dpi_x = std::max(dpi_x, screen_info->max_dpi_x);
235 screen_info->max_dpi_y = std::max(dpi_y, screen_info->max_dpi_y);
236 return TRUE;
237}
238
239void WriteScreenDPIInformationProto(SystemProfileProto::Hardware* hardware) {
240 HDC desktop_dc = GetDC(NULL);
241 if (desktop_dc) {
[email protected]ffaf7322013-05-15 00:26:11242 ScreenDPIInformation si = {0, 0};
[email protected]76869ff2013-01-15 16:13:47243 if (EnumDisplayMonitors(desktop_dc, NULL, GetMonitorDPICallback,
244 reinterpret_cast<LPARAM>(&si))) {
245 hardware->set_max_dpi_x(si.max_dpi_x);
246 hardware->set_max_dpi_y(si.max_dpi_y);
247 }
248 ReleaseDC(GetDesktopWindow(), desktop_dc);
249 }
250}
251
252#endif // defined(OS_WIN)
253
[email protected]86573d12013-07-11 19:48:32254// Round a timestamp measured in seconds since epoch to one with a granularity
255// of an hour. This can be used before uploaded potentially sensitive
256// timestamps.
257int64 RoundSecondsToHour(int64 time_in_seconds) {
258 return 3600 * (time_in_seconds / 3600);
259}
260
[email protected]1df44b72012-01-19 05:20:34261} // namespace
262
[email protected]9eae4032014-04-09 19:15:19263MetricsLog::MetricsLog(const std::string& client_id,
264 int session_id,
[email protected]09dee82d2014-05-22 14:00:53265 LogType log_type,
266 metrics::MetricsServiceClient* client)
267 : MetricsLogBase(client_id,
268 session_id,
269 log_type,
270 client->GetVersionString()),
271 client_(client),
[email protected]b84ee6e2014-03-15 22:51:54272 creation_time_(base::TimeTicks::Now()),
273 extension_metrics_(uma_proto()->client_id()) {
[email protected]09dee82d2014-05-22 14:00:53274 uma_proto()->mutable_system_profile()->set_channel(client_->GetChannel());
[email protected]064107e2014-05-02 00:59:06275
[email protected]afc03f02013-10-11 06:01:35276#if defined(OS_CHROMEOS)
[email protected]c9afed6e2014-02-03 22:12:29277 metrics_log_chromeos_.reset(new MetricsLogChromeOS(uma_proto()));
278#endif // OS_CHROMEOS
[email protected]afc03f02013-10-11 06:01:35279}
[email protected]5ed7d4572009-12-23 17:42:41280
[email protected]1226abb2010-06-10 18:01:28281MetricsLog::~MetricsLog() {}
initial.commit09911bf2008-07-26 23:55:29282
283// static
[email protected]b1de2c72013-02-06 02:45:47284void MetricsLog::RegisterPrefs(PrefRegistrySimple* registry) {
285 registry->RegisterListPref(prefs::kStabilityPluginStats);
initial.commit09911bf2008-07-26 23:55:29286}
287
[email protected]85791b0b2014-05-20 15:18:58288void MetricsLog::RecordStabilityMetrics(
289 const std::vector<metrics::MetricsProvider*>& metrics_providers,
290 base::TimeDelta incremental_uptime,
291 base::TimeDelta uptime) {
[email protected]767c9d92012-03-02 16:04:34292 DCHECK(!locked());
[email protected]0f2f7792013-11-28 16:09:14293 DCHECK(HasEnvironment());
294 DCHECK(!HasStabilityMetrics());
[email protected]0b33f80b2008-12-17 21:34:36295
[email protected]767c9d92012-03-02 16:04:34296 PrefService* pref = GetPrefService();
[email protected]0b33f80b2008-12-17 21:34:36297 DCHECK(pref);
298
initial.commit09911bf2008-07-26 23:55:29299 // Get stability attributes out of Local State, zeroing out stored values.
300 // NOTE: This could lead to some data loss if this report isn't successfully
301 // sent, but that's true for all the metrics.
302
[email protected]147bbc0b2009-01-06 19:37:40303 WriteRequiredStabilityAttributes(pref);
[email protected]250f7b662013-11-23 02:36:51304 WritePluginStabilityElements(pref);
[email protected]0edf8762013-11-21 18:33:30305
306 // Record recent delta for critical stability metrics. We can't wait for a
307 // restart to gather these, as that delay biases our observation away from
308 // users that run happily for a looooong time. We send increments with each
309 // uma log upload, just as we send histogram data.
[email protected]076961c2014-03-12 22:23:56310 WriteRealtimeStabilityAttributes(pref, incremental_uptime, uptime);
initial.commit09911bf2008-07-26 23:55:29311
[email protected]85791b0b2014-05-20 15:18:58312 SystemProfileProto::Stability* stability =
313 uma_proto()->mutable_system_profile()->mutable_stability();
314 for (size_t i = 0; i < metrics_providers.size(); ++i)
315 metrics_providers[i]->ProvideStabilityMetrics(stability);
316
[email protected]0edf8762013-11-21 18:33:30317 // Omit some stats unless this is the initial stability log.
[email protected]9eae4032014-04-09 19:15:19318 if (log_type() != INITIAL_STABILITY_LOG)
[email protected]0edf8762013-11-21 18:33:30319 return;
320
[email protected]fe58acc22012-02-29 01:29:58321 int incomplete_shutdown_count =
322 pref->GetInteger(prefs::kStabilityIncompleteSessionEndCount);
[email protected]e324f6b2012-02-28 05:43:37323 pref->SetInteger(prefs::kStabilityIncompleteSessionEndCount, 0);
[email protected]fe58acc22012-02-29 01:29:58324 int breakpad_registration_success_count =
325 pref->GetInteger(prefs::kStabilityBreakpadRegistrationSuccess);
[email protected]e324f6b2012-02-28 05:43:37326 pref->SetInteger(prefs::kStabilityBreakpadRegistrationSuccess, 0);
[email protected]fe58acc22012-02-29 01:29:58327 int breakpad_registration_failure_count =
328 pref->GetInteger(prefs::kStabilityBreakpadRegistrationFail);
[email protected]e324f6b2012-02-28 05:43:37329 pref->SetInteger(prefs::kStabilityBreakpadRegistrationFail, 0);
[email protected]fe58acc22012-02-29 01:29:58330 int debugger_present_count =
331 pref->GetInteger(prefs::kStabilityDebuggerPresent);
[email protected]e324f6b2012-02-28 05:43:37332 pref->SetInteger(prefs::kStabilityDebuggerPresent, 0);
[email protected]fe58acc22012-02-29 01:29:58333 int debugger_not_present_count =
334 pref->GetInteger(prefs::kStabilityDebuggerNotPresent);
[email protected]e324f6b2012-02-28 05:43:37335 pref->SetInteger(prefs::kStabilityDebuggerNotPresent, 0);
[email protected]b2a4812d2012-02-28 05:31:31336
[email protected]fe58acc22012-02-29 01:29:58337 // TODO(jar): The following are all optional, so we *could* optimize them for
338 // values of zero (and not include them).
[email protected]fe58acc22012-02-29 01:29:58339 stability->set_incomplete_shutdown_count(incomplete_shutdown_count);
340 stability->set_breakpad_registration_success_count(
341 breakpad_registration_success_count);
342 stability->set_breakpad_registration_failure_count(
343 breakpad_registration_failure_count);
344 stability->set_debugger_present_count(debugger_present_count);
345 stability->set_debugger_not_present_count(debugger_not_present_count);
[email protected]0edf8762013-11-21 18:33:30346}
[email protected]fe58acc22012-02-29 01:29:58347
[email protected]85791b0b2014-05-20 15:18:58348void MetricsLog::RecordGeneralMetrics(
349 const std::vector<metrics::MetricsProvider*>& metrics_providers) {
350 for (size_t i = 0; i < metrics_providers.size(); ++i)
351 metrics_providers[i]->ProvideGeneralMetrics(uma_proto());
352}
353
[email protected]0edf8762013-11-21 18:33:30354PrefService* MetricsLog::GetPrefService() {
355 return g_browser_process->local_state();
356}
357
358gfx::Size MetricsLog::GetScreenSize() const {
359 return gfx::Screen::GetNativeScreen()->GetPrimaryDisplay().GetSizeInPixel();
360}
361
362float MetricsLog::GetScreenDeviceScaleFactor() const {
363 return gfx::Screen::GetNativeScreen()->
364 GetPrimaryDisplay().device_scale_factor();
365}
366
367int MetricsLog::GetScreenCount() const {
368 // TODO(scottmg): NativeScreen maybe wrong. http://crbug.com/133312
369 return gfx::Screen::GetNativeScreen()->GetNumDisplays();
370}
371
372void MetricsLog::GetFieldTrialIds(
373 std::vector<ActiveGroupId>* field_trial_ids) const {
[email protected]b3610d42014-05-19 18:07:23374 variations::GetFieldTrialActiveGroupIds(field_trial_ids);
[email protected]147bbc0b2009-01-06 19:37:40375}
376
[email protected]0f2f7792013-11-28 16:09:14377bool MetricsLog::HasEnvironment() const {
378 return uma_proto()->system_profile().has_uma_enabled_date();
379}
380
381bool MetricsLog::HasStabilityMetrics() const {
382 return uma_proto()->system_profile().stability().has_launch_count();
383}
384
[email protected]250f7b662013-11-23 02:36:51385void MetricsLog::WritePluginStabilityElements(PrefService* pref) {
[email protected]147bbc0b2009-01-06 19:37:40386 // Now log plugin stability info.
[email protected]cb1078de2013-12-23 20:04:22387 const base::ListValue* plugin_stats_list = pref->GetList(
initial.commit09911bf2008-07-26 23:55:29388 prefs::kStabilityPluginStats);
[email protected]1df44b72012-01-19 05:20:34389 if (!plugin_stats_list)
390 return;
initial.commit09911bf2008-07-26 23:55:29391
[email protected]ebd71962012-12-20 02:56:55392#if defined(ENABLE_PLUGINS)
[email protected]fe58acc22012-02-29 01:29:58393 SystemProfileProto::Stability* stability =
[email protected]767c9d92012-03-02 16:04:34394 uma_proto()->mutable_system_profile()->mutable_stability();
[email protected]cb1078de2013-12-23 20:04:22395 for (base::ListValue::const_iterator iter = plugin_stats_list->begin();
[email protected]1df44b72012-01-19 05:20:34396 iter != plugin_stats_list->end(); ++iter) {
[email protected]cb1078de2013-12-23 20:04:22397 if (!(*iter)->IsType(base::Value::TYPE_DICTIONARY)) {
[email protected]1df44b72012-01-19 05:20:34398 NOTREACHED();
399 continue;
initial.commit09911bf2008-07-26 23:55:29400 }
[email protected]cb1078de2013-12-23 20:04:22401 base::DictionaryValue* plugin_dict =
402 static_cast<base::DictionaryValue*>(*iter);
initial.commit09911bf2008-07-26 23:55:29403
[email protected]fe58acc22012-02-29 01:29:58404 // Note that this search is potentially a quadratic operation, but given the
405 // low number of plugins installed on a "reasonable" setup, this should be
406 // fine.
407 // TODO(isherman): Verify that this does not show up as a hotspot in
408 // profiler runs.
[email protected]250f7b662013-11-23 02:36:51409 const SystemProfileProto::Plugin* system_profile_plugin = NULL;
[email protected]f31a01a2013-07-13 02:51:11410 std::string plugin_name;
411 plugin_dict->GetString(prefs::kStabilityPluginName, &plugin_name);
[email protected]250f7b662013-11-23 02:36:51412 const SystemProfileProto& system_profile = uma_proto()->system_profile();
413 for (int i = 0; i < system_profile.plugin_size(); ++i) {
414 if (system_profile.plugin(i).name() == plugin_name) {
415 system_profile_plugin = &system_profile.plugin(i);
[email protected]fe58acc22012-02-29 01:29:58416 break;
417 }
418 }
419
[email protected]250f7b662013-11-23 02:36:51420 if (!system_profile_plugin) {
[email protected]fe58acc22012-02-29 01:29:58421 NOTREACHED();
422 continue;
423 }
424
425 SystemProfileProto::Stability::PluginStability* plugin_stability =
426 stability->add_plugin_stability();
[email protected]250f7b662013-11-23 02:36:51427 *plugin_stability->mutable_plugin() = *system_profile_plugin;
[email protected]f31a01a2013-07-13 02:51:11428
429 int launches = 0;
430 plugin_dict->GetInteger(prefs::kStabilityPluginLaunches, &launches);
431 if (launches > 0)
432 plugin_stability->set_launch_count(launches);
433
434 int instances = 0;
435 plugin_dict->GetInteger(prefs::kStabilityPluginInstances, &instances);
436 if (instances > 0)
437 plugin_stability->set_instance_count(instances);
438
439 int crashes = 0;
440 plugin_dict->GetInteger(prefs::kStabilityPluginCrashes, &crashes);
441 if (crashes > 0)
442 plugin_stability->set_crash_count(crashes);
443
444 int loading_errors = 0;
445 plugin_dict->GetInteger(prefs::kStabilityPluginLoadingErrors,
446 &loading_errors);
447 if (loading_errors > 0)
448 plugin_stability->set_loading_error_count(loading_errors);
initial.commit09911bf2008-07-26 23:55:29449 }
[email protected]ebd71962012-12-20 02:56:55450#endif // defined(ENABLE_PLUGINS)
[email protected]1df44b72012-01-19 05:20:34451
452 pref->ClearPref(prefs::kStabilityPluginStats);
initial.commit09911bf2008-07-26 23:55:29453}
454
[email protected]fe58acc22012-02-29 01:29:58455// The server refuses data that doesn't have certain values. crashcount and
456// launchcount are currently "required" in the "stability" group.
457// TODO(isherman): Stop writing these attributes specially once the migration to
458// protobufs is complete.
[email protected]147bbc0b2009-01-06 19:37:40459void MetricsLog::WriteRequiredStabilityAttributes(PrefService* pref) {
[email protected]fe58acc22012-02-29 01:29:58460 int launch_count = pref->GetInteger(prefs::kStabilityLaunchCount);
[email protected]0b33f80b2008-12-17 21:34:36461 pref->SetInteger(prefs::kStabilityLaunchCount, 0);
[email protected]fe58acc22012-02-29 01:29:58462 int crash_count = pref->GetInteger(prefs::kStabilityCrashCount);
[email protected]0b33f80b2008-12-17 21:34:36463 pref->SetInteger(prefs::kStabilityCrashCount, 0);
[email protected]fe58acc22012-02-29 01:29:58464
[email protected]fe58acc22012-02-29 01:29:58465 SystemProfileProto::Stability* stability =
[email protected]767c9d92012-03-02 16:04:34466 uma_proto()->mutable_system_profile()->mutable_stability();
[email protected]fe58acc22012-02-29 01:29:58467 stability->set_launch_count(launch_count);
468 stability->set_crash_count(crash_count);
[email protected]0b33f80b2008-12-17 21:34:36469}
470
[email protected]c68a2b9b2013-10-09 18:16:36471void MetricsLog::WriteRealtimeStabilityAttributes(
472 PrefService* pref,
[email protected]076961c2014-03-12 22:23:56473 base::TimeDelta incremental_uptime,
474 base::TimeDelta uptime) {
[email protected]0b33f80b2008-12-17 21:34:36475 // Update the stats which are critical for real-time stability monitoring.
476 // Since these are "optional," only list ones that are non-zero, as the counts
[email protected]250f7b662013-11-23 02:36:51477 // are aggregated (summed) server side.
[email protected]0b33f80b2008-12-17 21:34:36478
[email protected]fe58acc22012-02-29 01:29:58479 SystemProfileProto::Stability* stability =
[email protected]767c9d92012-03-02 16:04:34480 uma_proto()->mutable_system_profile()->mutable_stability();
[email protected]0b33f80b2008-12-17 21:34:36481 int count = pref->GetInteger(prefs::kStabilityPageLoadCount);
482 if (count) {
[email protected]fe58acc22012-02-29 01:29:58483 stability->set_page_load_count(count);
[email protected]0b33f80b2008-12-17 21:34:36484 pref->SetInteger(prefs::kStabilityPageLoadCount, 0);
485 }
486
487 count = pref->GetInteger(prefs::kStabilityRendererCrashCount);
488 if (count) {
[email protected]fe58acc22012-02-29 01:29:58489 stability->set_renderer_crash_count(count);
[email protected]0b33f80b2008-12-17 21:34:36490 pref->SetInteger(prefs::kStabilityRendererCrashCount, 0);
491 }
492
[email protected]1f085622009-12-04 05:33:45493 count = pref->GetInteger(prefs::kStabilityExtensionRendererCrashCount);
494 if (count) {
[email protected]fe58acc22012-02-29 01:29:58495 stability->set_extension_renderer_crash_count(count);
[email protected]1f085622009-12-04 05:33:45496 pref->SetInteger(prefs::kStabilityExtensionRendererCrashCount, 0);
497 }
498
[email protected]0b33f80b2008-12-17 21:34:36499 count = pref->GetInteger(prefs::kStabilityRendererHangCount);
500 if (count) {
[email protected]fe58acc22012-02-29 01:29:58501 stability->set_renderer_hang_count(count);
[email protected]0b33f80b2008-12-17 21:34:36502 pref->SetInteger(prefs::kStabilityRendererHangCount, 0);
503 }
[email protected]1f085622009-12-04 05:33:45504
505 count = pref->GetInteger(prefs::kStabilityChildProcessCrashCount);
506 if (count) {
[email protected]fe58acc22012-02-29 01:29:58507 stability->set_child_process_crash_count(count);
[email protected]1f085622009-12-04 05:33:45508 pref->SetInteger(prefs::kStabilityChildProcessCrashCount, 0);
509 }
[email protected]9165f742010-03-10 22:55:01510
[email protected]c1834a92011-01-21 18:21:03511#if defined(OS_CHROMEOS)
[email protected]c9afed6e2014-02-03 22:12:29512 metrics_log_chromeos_->WriteRealtimeStabilityAttributes(pref);
[email protected]c1834a92011-01-21 18:21:03513#endif // OS_CHROMEOS
514
[email protected]076961c2014-03-12 22:23:56515 const uint64 incremental_uptime_sec = incremental_uptime.InSeconds();
516 if (incremental_uptime_sec)
517 stability->set_incremental_uptime_sec(incremental_uptime_sec);
518 const uint64 uptime_sec = uptime.InSeconds();
[email protected]c68a2b9b2013-10-09 18:16:36519 if (uptime_sec)
520 stability->set_uptime_sec(uptime_sec);
[email protected]0b33f80b2008-12-17 21:34:36521}
522
initial.commit09911bf2008-07-26 23:55:29523void MetricsLog::WritePluginList(
[email protected]d7bd3e52013-07-21 04:29:20524 const std::vector<content::WebPluginInfo>& plugin_list) {
[email protected]767c9d92012-03-02 16:04:34525 DCHECK(!locked());
initial.commit09911bf2008-07-26 23:55:29526
[email protected]ebd71962012-12-20 02:56:55527#if defined(ENABLE_PLUGINS)
528 PluginPrefs* plugin_prefs = GetPluginPrefs();
[email protected]767c9d92012-03-02 16:04:34529 SystemProfileProto* system_profile = uma_proto()->mutable_system_profile();
[email protected]d7bd3e52013-07-21 04:29:20530 for (std::vector<content::WebPluginInfo>::const_iterator iter =
[email protected]191eb3f72010-12-21 06:27:50531 plugin_list.begin();
initial.commit09911bf2008-07-26 23:55:29532 iter != plugin_list.end(); ++iter) {
[email protected]0eecc2542013-06-23 04:22:02533 SystemProfileProto::Plugin* plugin = system_profile->add_plugin();
534 SetPluginInfo(*iter, plugin_prefs, plugin);
initial.commit09911bf2008-07-26 23:55:29535 }
[email protected]ebd71962012-12-20 02:56:55536#endif // defined(ENABLE_PLUGINS)
initial.commit09911bf2008-07-26 23:55:29537}
538
539void MetricsLog::RecordEnvironment(
[email protected]85791b0b2014-05-20 15:18:58540 const std::vector<metrics::MetricsProvider*>& metrics_providers,
[email protected]c68a2b9b2013-10-09 18:16:36541 const std::vector<content::WebPluginInfo>& plugin_list,
[email protected]b3610d42014-05-19 18:07:23542 const std::vector<variations::ActiveGroupId>& synthetic_trials) {
[email protected]0f2f7792013-11-28 16:09:14543 DCHECK(!HasEnvironment());
544
[email protected]bc66d532012-03-23 01:57:05545 SystemProfileProto* system_profile = uma_proto()->mutable_system_profile();
[email protected]24b9bb392013-01-29 20:29:29546
547 std::string brand_code;
[email protected]09dee82d2014-05-22 14:00:53548 if (client_->GetBrand(&brand_code))
[email protected]24b9bb392013-01-29 20:29:29549 system_profile->set_brand_code(brand_code);
550
[email protected]cc5d7f42012-10-30 00:30:09551 int enabled_date;
552 bool success = base::StringToInt(GetMetricsEnabledDate(GetPrefService()),
553 &enabled_date);
[email protected]bc66d532012-03-23 01:57:05554 DCHECK(success);
[email protected]86573d12013-07-11 19:48:32555
556 // Reduce granularity of the enabled_date field to nearest hour.
557 system_profile->set_uma_enabled_date(RoundSecondsToHour(enabled_date));
558
559 int64 install_date = GetPrefService()->GetInt64(prefs::kInstallDate);
560
561 // Reduce granularity of the install_date field to nearest hour.
562 system_profile->set_install_date(RoundSecondsToHour(install_date));
[email protected]bc66d532012-03-23 01:57:05563
[email protected]09dee82d2014-05-22 14:00:53564 system_profile->set_application_locale(client_->GetApplicationLocale());
[email protected]bc66d532012-03-23 01:57:05565
566 SystemProfileProto::Hardware* hardware = system_profile->mutable_hardware();
[email protected]0b6a4fb2012-10-16 01:58:21567 hardware->set_cpu_architecture(base::SysInfo::OperatingSystemArchitecture());
[email protected]bc66d532012-03-23 01:57:05568 hardware->set_system_ram_mb(base::SysInfo::AmountOfPhysicalMemoryMB());
569#if defined(OS_WIN)
570 hardware->set_dll_base(reinterpret_cast<uint64>(&__ImageBase));
571#endif
572
[email protected]74b299e2013-01-29 01:24:42573 SystemProfileProto::Network* network = system_profile->mutable_network();
574 network->set_connection_type_is_ambiguous(
[email protected]5eae204c2013-02-13 15:53:42575 network_observer_.connection_type_is_ambiguous());
576 network->set_connection_type(network_observer_.connection_type());
577 network->set_wifi_phy_layer_protocol_is_ambiguous(
578 network_observer_.wifi_phy_layer_protocol_is_ambiguous());
579 network->set_wifi_phy_layer_protocol(
580 network_observer_.wifi_phy_layer_protocol());
581 network_observer_.Reset();
[email protected]74b299e2013-01-29 01:24:42582
[email protected]bc66d532012-03-23 01:57:05583 SystemProfileProto::OS* os = system_profile->mutable_os();
[email protected]1bb25e02012-08-03 22:39:39584 std::string os_name = base::SysInfo::OperatingSystemName();
585#if defined(OS_WIN)
586 // TODO(mad): This only checks whether the main process is a Metro process at
587 // upload time; not whether the collected metrics were all gathered from
588 // Metro. This is ok as an approximation for now, since users will rarely be
589 // switching from Metro to Desktop mode; but we should re-evaluate whether we
590 // can distinguish metrics more cleanly in the future: http://crbug.com/140568
591 if (base::win::IsMetroProcess())
592 os_name += " (Metro)";
593#endif
594 os->set_name(os_name);
[email protected]bc66d532012-03-23 01:57:05595 os->set_version(base::SysInfo::OperatingSystemVersion());
[email protected]5106b3a2012-10-03 20:10:44596#if defined(OS_ANDROID)
597 os->set_fingerprint(
598 base::android::BuildInfo::GetInstance()->android_build_fp());
599#endif
[email protected]bc66d532012-03-23 01:57:05600
[email protected]5c8f89f692013-07-18 11:13:28601 base::CPU cpu_info;
602 SystemProfileProto::Hardware::CPU* cpu = hardware->mutable_cpu();
603 cpu->set_vendor_name(cpu_info.vendor_name());
604 cpu->set_signature(cpu_info.signature());
605
[email protected]d7b5cc72013-05-23 20:05:00606 const gpu::GPUInfo& gpu_info =
[email protected]bc66d532012-03-23 01:57:05607 GpuDataManager::GetInstance()->GetGPUInfo();
608 SystemProfileProto::Hardware::Graphics* gpu = hardware->mutable_gpu();
[email protected]a094e2c2012-05-10 23:02:42609 gpu->set_vendor_id(gpu_info.gpu.vendor_id);
610 gpu->set_device_id(gpu_info.gpu.device_id);
[email protected]bc66d532012-03-23 01:57:05611 gpu->set_driver_version(gpu_info.driver_version);
612 gpu->set_driver_date(gpu_info.driver_date);
613 SystemProfileProto::Hardware::Graphics::PerformanceStatistics*
614 gpu_performance = gpu->mutable_performance_statistics();
615 gpu_performance->set_graphics_score(gpu_info.performance_stats.graphics);
616 gpu_performance->set_gaming_score(gpu_info.performance_stats.gaming);
617 gpu_performance->set_overall_score(gpu_info.performance_stats.overall);
[email protected]d6bdfae2013-01-18 20:23:01618 gpu->set_gl_vendor(gpu_info.gl_vendor);
619 gpu->set_gl_renderer(gpu_info.gl_renderer);
[email protected]bc66d532012-03-23 01:57:05620
621 const gfx::Size display_size = GetScreenSize();
622 hardware->set_primary_screen_width(display_size.width());
623 hardware->set_primary_screen_height(display_size.height());
[email protected]aa96417972012-08-22 03:16:44624 hardware->set_primary_screen_scale_factor(GetScreenDeviceScaleFactor());
[email protected]bc66d532012-03-23 01:57:05625 hardware->set_screen_count(GetScreenCount());
626
[email protected]76869ff2013-01-15 16:13:47627#if defined(OS_WIN)
628 WriteScreenDPIInformationProto(hardware);
629#endif
630
[email protected]0eecc2542013-06-23 04:22:02631 WritePluginList(plugin_list);
[email protected]b84ee6e2014-03-15 22:51:54632 extension_metrics_.WriteExtensionList(uma_proto()->mutable_system_profile());
[email protected]bc66d532012-03-23 01:57:05633
[email protected]0c8b7ad2012-11-06 07:08:14634 std::vector<ActiveGroupId> field_trial_ids;
[email protected]767c9d92012-03-02 16:04:34635 GetFieldTrialIds(&field_trial_ids);
636 WriteFieldTrials(field_trial_ids, system_profile);
[email protected]60677562013-11-17 15:52:55637 WriteFieldTrials(synthetic_trials, system_profile);
[email protected]f65859e2013-02-04 20:00:25638
639#if defined(OS_CHROMEOS)
[email protected]c9afed6e2014-02-03 22:12:29640 metrics_log_chromeos_->LogChromeOSMetrics();
641#endif // OS_CHROMEOS
[email protected]0f2f7792013-11-28 16:09:14642
[email protected]85791b0b2014-05-20 15:18:58643 for (size_t i = 0; i < metrics_providers.size(); ++i)
644 metrics_providers[i]->ProvideSystemProfileMetrics(system_profile);
645
[email protected]0f2f7792013-11-28 16:09:14646 std::string serialied_system_profile;
647 std::string base64_system_profile;
[email protected]33fca122013-12-11 01:48:50648 if (system_profile->SerializeToString(&serialied_system_profile)) {
649 base::Base64Encode(serialied_system_profile, &base64_system_profile);
[email protected]0f2f7792013-11-28 16:09:14650 PrefService* local_state = GetPrefService();
651 local_state->SetString(prefs::kStabilitySavedSystemProfile,
652 base64_system_profile);
653 local_state->SetString(prefs::kStabilitySavedSystemProfileHash,
654 ComputeSHA1(serialied_system_profile));
655 }
656}
657
658bool MetricsLog::LoadSavedEnvironmentFromPrefs() {
659 PrefService* local_state = GetPrefService();
660 const std::string base64_system_profile =
661 local_state->GetString(prefs::kStabilitySavedSystemProfile);
662 if (base64_system_profile.empty())
663 return false;
664
665 const std::string system_profile_hash =
666 local_state->GetString(prefs::kStabilitySavedSystemProfileHash);
667 local_state->ClearPref(prefs::kStabilitySavedSystemProfile);
668 local_state->ClearPref(prefs::kStabilitySavedSystemProfileHash);
669
670 SystemProfileProto* system_profile = uma_proto()->mutable_system_profile();
671 std::string serialied_system_profile;
672 return base::Base64Decode(base64_system_profile, &serialied_system_profile) &&
673 ComputeSHA1(serialied_system_profile) == system_profile_hash &&
674 system_profile->ParseFromString(serialied_system_profile);
initial.commit09911bf2008-07-26 23:55:29675}
676
[email protected]ed0fd002012-04-25 23:10:34677void MetricsLog::RecordProfilerData(
678 const tracked_objects::ProcessDataSnapshot& process_data,
[email protected]f3b357692013-03-22 05:16:13679 int process_type) {
[email protected]ed0fd002012-04-25 23:10:34680 DCHECK(!locked());
681
[email protected]8f829682012-04-27 00:36:49682 if (tracked_objects::GetTimeSourceType() !=
683 tracked_objects::TIME_SOURCE_TYPE_WALL_TIME) {
[email protected]ed0fd002012-04-25 23:10:34684 // We currently only support the default time source, wall clock time.
685 return;
686 }
687
688 ProfilerEventProto* profile;
689 if (!uma_proto()->profiler_event_size()) {
690 // For the first process's data, add a new field to the protocol buffer.
691 profile = uma_proto()->add_profiler_event();
692 profile->set_profile_type(ProfilerEventProto::STARTUP_PROFILE);
693 profile->set_time_source(ProfilerEventProto::WALL_CLOCK_TIME);
694 } else {
695 // For the remaining calls, re-use the existing field.
696 profile = uma_proto()->mutable_profiler_event(0);
697 }
698
699 WriteProfilerData(process_data, process_type, profile);
700}