blob: 219d6864182d27a1fc740dc27a83f8f7f285d650 [file] [log] [blame]
[email protected]85ed9d42010-06-08 22:37:441// Copyright (c) 2010 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]978df342009-11-24 06:21:537#include "base/base64.h"
[email protected]9165f742010-03-10 22:55:018#include "base/time.h"
[email protected]d1be67b2008-11-19 20:28:389#include "base/basictypes.h"
initial.commit09911bf2008-07-26 23:55:2910#include "base/file_util.h"
11#include "base/file_version_info.h"
12#include "base/md5.h"
[email protected]85ed9d42010-06-08 22:37:4413#include "base/perftimer.h"
initial.commit09911bf2008-07-26 23:55:2914#include "base/scoped_ptr.h"
15#include "base/string_util.h"
[email protected]fadf97f2008-09-18 12:18:1416#include "base/sys_info.h"
[email protected]1cb92b82010-03-08 23:12:1517#include "base/utf_string_conversions.h"
[email protected]37f39e42010-01-06 17:35:1718#include "base/third_party/nspr/prtime.h"
[email protected]bcff05a2010-04-14 01:46:4319#include "chrome/app/chrome_version_info.h"
initial.commit09911bf2008-07-26 23:55:2920#include "chrome/browser/autocomplete/autocomplete.h"
21#include "chrome/browser/browser_process.h"
[email protected]052313b2010-02-19 09:43:0822#include "chrome/browser/pref_service.h"
initial.commit09911bf2008-07-26 23:55:2923#include "chrome/common/logging_chrome.h"
24#include "chrome/common/pref_names.h"
[email protected]46072d42008-07-28 14:49:3525#include "googleurl/src/gurl.h"
initial.commit09911bf2008-07-26 23:55:2926
27#define OPEN_ELEMENT_FOR_SCOPE(name) ScopedElement scoped_element(this, name)
28
[email protected]d1be67b2008-11-19 20:28:3829// http://blogs.msdn.com/oldnewthing/archive/2004/10/25/247180.aspx
30#if defined(OS_WIN)
31extern "C" IMAGE_DOS_HEADER __ImageBase;
32#endif
33
[email protected]1226abb2010-06-10 18:01:2834MetricsLog::MetricsLog(const std::string& client_id, int session_id)
35 : MetricsLogBase(client_id, session_id, MetricsLog::GetVersionString()) {}
[email protected]5ed7d4572009-12-23 17:42:4136
[email protected]1226abb2010-06-10 18:01:2837MetricsLog::~MetricsLog() {}
initial.commit09911bf2008-07-26 23:55:2938
39// static
40void MetricsLog::RegisterPrefs(PrefService* local_state) {
41 local_state->RegisterListPref(prefs::kStabilityPluginStats);
initial.commit09911bf2008-07-26 23:55:2942}
43
[email protected]9165f742010-03-10 22:55:0144int64 MetricsLog::GetIncrementalUptime(PrefService* pref) {
45 base::TimeTicks now = base::TimeTicks::Now();
46 static base::TimeTicks last_updated_time(now);
47 int64 incremental_time = (now - last_updated_time).InSeconds();
48 last_updated_time = now;
49
50 if (incremental_time > 0) {
51 int64 metrics_uptime = pref->GetInt64(prefs::kUninstallMetricsUptimeSec);
52 metrics_uptime += incremental_time;
53 pref->SetInt64(prefs::kUninstallMetricsUptimeSec, metrics_uptime);
54 }
55
56 return incremental_time;
57}
58
initial.commit09911bf2008-07-26 23:55:2959std::string MetricsLog::GetInstallDate() const {
60 PrefService* pref = g_browser_process->local_state();
61 if (pref) {
62 return WideToUTF8(pref->GetString(prefs::kMetricsClientIDTimestamp));
63 } else {
64 NOTREACHED();
65 return "0";
66 }
67}
68
[email protected]1226abb2010-06-10 18:01:2869// static
70std::string MetricsLog::GetVersionString() {
71 scoped_ptr<FileVersionInfo> version_info(
72 chrome_app::GetChromeVersionInfo());
73 if (version_info.get()) {
74 std::string version = WideToUTF8(version_info->product_version());
75 if (!version_extension_.empty())
76 version += version_extension_;
77 if (!version_info->is_official_build())
78 version.append("-devel");
79 return version;
80 } else {
81 NOTREACHED() << "Unable to retrieve version string.";
82 }
83
84 return std::string();
85}
86
[email protected]0b33f80b2008-12-17 21:34:3687void MetricsLog::RecordIncrementalStabilityElements() {
88 DCHECK(!locked_);
89
90 PrefService* pref = g_browser_process->local_state();
91 DCHECK(pref);
92
[email protected]147bbc0b2009-01-06 19:37:4093 OPEN_ELEMENT_FOR_SCOPE("profile");
94 WriteCommonEventAttributes();
95
96 WriteInstallElement(); // Supply appversion.
97
98 {
99 OPEN_ELEMENT_FOR_SCOPE("stability"); // Minimal set of stability elements.
100 WriteRequiredStabilityAttributes(pref);
101 WriteRealtimeStabilityAttributes(pref);
102
103 WritePluginStabilityElements(pref);
104 }
[email protected]0b33f80b2008-12-17 21:34:36105}
106
initial.commit09911bf2008-07-26 23:55:29107void MetricsLog::WriteStabilityElement() {
108 DCHECK(!locked_);
109
110 PrefService* pref = g_browser_process->local_state();
111 DCHECK(pref);
112
113 // Get stability attributes out of Local State, zeroing out stored values.
114 // NOTE: This could lead to some data loss if this report isn't successfully
115 // sent, but that's true for all the metrics.
116
[email protected]ffaf78a2008-11-12 17:38:33117 OPEN_ELEMENT_FOR_SCOPE("stability");
[email protected]147bbc0b2009-01-06 19:37:40118 WriteRequiredStabilityAttributes(pref);
119 WriteRealtimeStabilityAttributes(pref);
initial.commit09911bf2008-07-26 23:55:29120
[email protected]0b33f80b2008-12-17 21:34:36121 // TODO(jar): The following are all optional, so we *could* optimize them for
122 // values of zero (and not include them).
[email protected]8e674e42008-07-30 16:05:48123 WriteIntAttribute("incompleteshutdowncount",
124 pref->GetInteger(
125 prefs::kStabilityIncompleteSessionEndCount));
126 pref->SetInteger(prefs::kStabilityIncompleteSessionEndCount, 0);
[email protected]0b33f80b2008-12-17 21:34:36127
128
[email protected]e73c01972008-08-13 00:18:24129 WriteIntAttribute("breakpadregistrationok",
130 pref->GetInteger(prefs::kStabilityBreakpadRegistrationSuccess));
131 pref->SetInteger(prefs::kStabilityBreakpadRegistrationSuccess, 0);
132 WriteIntAttribute("breakpadregistrationfail",
133 pref->GetInteger(prefs::kStabilityBreakpadRegistrationFail));
134 pref->SetInteger(prefs::kStabilityBreakpadRegistrationFail, 0);
135 WriteIntAttribute("debuggerpresent",
136 pref->GetInteger(prefs::kStabilityDebuggerPresent));
137 pref->SetInteger(prefs::kStabilityDebuggerPresent, 0);
138 WriteIntAttribute("debuggernotpresent",
139 pref->GetInteger(prefs::kStabilityDebuggerNotPresent));
140 pref->SetInteger(prefs::kStabilityDebuggerNotPresent, 0);
initial.commit09911bf2008-07-26 23:55:29141
[email protected]147bbc0b2009-01-06 19:37:40142 WritePluginStabilityElements(pref);
143}
144
145void MetricsLog::WritePluginStabilityElements(PrefService* pref) {
146 // Now log plugin stability info.
initial.commit09911bf2008-07-26 23:55:29147 const ListValue* plugin_stats_list = pref->GetList(
148 prefs::kStabilityPluginStats);
149 if (plugin_stats_list) {
[email protected]ffaf78a2008-11-12 17:38:33150 OPEN_ELEMENT_FOR_SCOPE("plugins");
initial.commit09911bf2008-07-26 23:55:29151 for (ListValue::const_iterator iter = plugin_stats_list->begin();
152 iter != plugin_stats_list->end(); ++iter) {
153 if (!(*iter)->IsType(Value::TYPE_DICTIONARY)) {
154 NOTREACHED();
155 continue;
156 }
157 DictionaryValue* plugin_dict = static_cast<DictionaryValue*>(*iter);
158
[email protected]8e50b602009-03-03 22:59:43159 std::wstring plugin_name;
160 plugin_dict->GetString(prefs::kStabilityPluginName, &plugin_name);
initial.commit09911bf2008-07-26 23:55:29161
[email protected]ffaf78a2008-11-12 17:38:33162 OPEN_ELEMENT_FOR_SCOPE("pluginstability");
[email protected]a27a9382009-02-11 23:55:10163 // Use "filename" instead of "name", otherwise we need to update the
164 // UMA servers.
[email protected]8e50b602009-03-03 22:59:43165 WriteAttribute("filename", CreateBase64Hash(WideToUTF8(plugin_name)));
initial.commit09911bf2008-07-26 23:55:29166
167 int launches = 0;
[email protected]8e50b602009-03-03 22:59:43168 plugin_dict->GetInteger(prefs::kStabilityPluginLaunches, &launches);
initial.commit09911bf2008-07-26 23:55:29169 WriteIntAttribute("launchcount", launches);
170
171 int instances = 0;
[email protected]8e50b602009-03-03 22:59:43172 plugin_dict->GetInteger(prefs::kStabilityPluginInstances, &instances);
initial.commit09911bf2008-07-26 23:55:29173 WriteIntAttribute("instancecount", instances);
174
175 int crashes = 0;
[email protected]8e50b602009-03-03 22:59:43176 plugin_dict->GetInteger(prefs::kStabilityPluginCrashes, &crashes);
initial.commit09911bf2008-07-26 23:55:29177 WriteIntAttribute("crashcount", crashes);
initial.commit09911bf2008-07-26 23:55:29178 }
179
180 pref->ClearPref(prefs::kStabilityPluginStats);
initial.commit09911bf2008-07-26 23:55:29181 }
initial.commit09911bf2008-07-26 23:55:29182}
183
[email protected]147bbc0b2009-01-06 19:37:40184void MetricsLog::WriteRequiredStabilityAttributes(PrefService* pref) {
[email protected]0b33f80b2008-12-17 21:34:36185 // The server refuses data that doesn't have certain values. crashcount and
186 // launchcount are currently "required" in the "stability" group.
187 WriteIntAttribute("launchcount",
188 pref->GetInteger(prefs::kStabilityLaunchCount));
189 pref->SetInteger(prefs::kStabilityLaunchCount, 0);
190 WriteIntAttribute("crashcount",
191 pref->GetInteger(prefs::kStabilityCrashCount));
192 pref->SetInteger(prefs::kStabilityCrashCount, 0);
193}
194
[email protected]147bbc0b2009-01-06 19:37:40195void MetricsLog::WriteRealtimeStabilityAttributes(PrefService* pref) {
[email protected]0b33f80b2008-12-17 21:34:36196 // Update the stats which are critical for real-time stability monitoring.
197 // Since these are "optional," only list ones that are non-zero, as the counts
198 // are aggergated (summed) server side.
199
200 int count = pref->GetInteger(prefs::kStabilityPageLoadCount);
201 if (count) {
202 WriteIntAttribute("pageloadcount", count);
203 pref->SetInteger(prefs::kStabilityPageLoadCount, 0);
204 }
205
206 count = pref->GetInteger(prefs::kStabilityRendererCrashCount);
207 if (count) {
208 WriteIntAttribute("renderercrashcount", count);
209 pref->SetInteger(prefs::kStabilityRendererCrashCount, 0);
210 }
211
[email protected]1f085622009-12-04 05:33:45212 count = pref->GetInteger(prefs::kStabilityExtensionRendererCrashCount);
213 if (count) {
214 WriteIntAttribute("extensionrenderercrashcount", count);
215 pref->SetInteger(prefs::kStabilityExtensionRendererCrashCount, 0);
216 }
217
[email protected]0b33f80b2008-12-17 21:34:36218 count = pref->GetInteger(prefs::kStabilityRendererHangCount);
219 if (count) {
220 WriteIntAttribute("rendererhangcount", count);
221 pref->SetInteger(prefs::kStabilityRendererHangCount, 0);
222 }
[email protected]1f085622009-12-04 05:33:45223
224 count = pref->GetInteger(prefs::kStabilityChildProcessCrashCount);
225 if (count) {
226 WriteIntAttribute("childprocesscrashcount", count);
227 pref->SetInteger(prefs::kStabilityChildProcessCrashCount, 0);
228 }
[email protected]9165f742010-03-10 22:55:01229
230 int64 recent_duration = GetIncrementalUptime(pref);
231 if (recent_duration)
232 WriteInt64Attribute("uptimesec", recent_duration);
[email protected]0b33f80b2008-12-17 21:34:36233}
234
initial.commit09911bf2008-07-26 23:55:29235void MetricsLog::WritePluginList(
236 const std::vector<WebPluginInfo>& plugin_list) {
237 DCHECK(!locked_);
238
[email protected]ffaf78a2008-11-12 17:38:33239 OPEN_ELEMENT_FOR_SCOPE("plugins");
initial.commit09911bf2008-07-26 23:55:29240
241 for (std::vector<WebPluginInfo>::const_iterator iter = plugin_list.begin();
242 iter != plugin_list.end(); ++iter) {
[email protected]ffaf78a2008-11-12 17:38:33243 OPEN_ELEMENT_FOR_SCOPE("plugin");
initial.commit09911bf2008-07-26 23:55:29244
245 // Plugin name and filename are hashed for the privacy of those
246 // testing unreleased new extensions.
[email protected]c9d811372010-06-23 21:44:57247 WriteAttribute("name", CreateBase64Hash(UTF16ToUTF8(iter->name)));
[email protected]046344c2009-01-13 00:54:21248 WriteAttribute("filename",
249 CreateBase64Hash(WideToUTF8(iter->path.BaseName().ToWStringHack())));
[email protected]c9d811372010-06-23 21:44:57250 WriteAttribute("version", UTF16ToUTF8(iter->version));
initial.commit09911bf2008-07-26 23:55:29251 }
initial.commit09911bf2008-07-26 23:55:29252}
253
[email protected]147bbc0b2009-01-06 19:37:40254void MetricsLog::WriteInstallElement() {
255 OPEN_ELEMENT_FOR_SCOPE("install");
256 WriteAttribute("installdate", GetInstallDate());
257 WriteIntAttribute("buildid", 0); // We're using appversion instead.
[email protected]147bbc0b2009-01-06 19:37:40258}
259
initial.commit09911bf2008-07-26 23:55:29260void MetricsLog::RecordEnvironment(
261 const std::vector<WebPluginInfo>& plugin_list,
262 const DictionaryValue* profile_metrics) {
263 DCHECK(!locked_);
264
265 PrefService* pref = g_browser_process->local_state();
266
[email protected]ffaf78a2008-11-12 17:38:33267 OPEN_ELEMENT_FOR_SCOPE("profile");
initial.commit09911bf2008-07-26 23:55:29268 WriteCommonEventAttributes();
269
[email protected]147bbc0b2009-01-06 19:37:40270 WriteInstallElement();
initial.commit09911bf2008-07-26 23:55:29271
272 WritePluginList(plugin_list);
273
274 WriteStabilityElement();
275
276 {
277 OPEN_ELEMENT_FOR_SCOPE("cpu");
[email protected]05f9b682008-09-29 22:18:01278 WriteAttribute("arch", base::SysInfo::CPUArchitecture());
initial.commit09911bf2008-07-26 23:55:29279 }
280
281 {
initial.commit09911bf2008-07-26 23:55:29282 OPEN_ELEMENT_FOR_SCOPE("memory");
[email protected]ed6fc352008-09-18 12:44:40283 WriteIntAttribute("mb", base::SysInfo::AmountOfPhysicalMemoryMB());
[email protected]d1be67b2008-11-19 20:28:38284#if defined(OS_WIN)
285 WriteIntAttribute("dllbase", reinterpret_cast<int>(&__ImageBase));
286#endif
initial.commit09911bf2008-07-26 23:55:29287 }
288
289 {
290 OPEN_ELEMENT_FOR_SCOPE("os");
291 WriteAttribute("name",
[email protected]05f9b682008-09-29 22:18:01292 base::SysInfo::OperatingSystemName());
initial.commit09911bf2008-07-26 23:55:29293 WriteAttribute("version",
[email protected]05f9b682008-09-29 22:18:01294 base::SysInfo::OperatingSystemVersion());
initial.commit09911bf2008-07-26 23:55:29295 }
296
297 {
298 OPEN_ELEMENT_FOR_SCOPE("display");
299 int width = 0;
300 int height = 0;
[email protected]05f9b682008-09-29 22:18:01301 base::SysInfo::GetPrimaryDisplayDimensions(&width, &height);
initial.commit09911bf2008-07-26 23:55:29302 WriteIntAttribute("xsize", width);
303 WriteIntAttribute("ysize", height);
[email protected]05f9b682008-09-29 22:18:01304 WriteIntAttribute("screens", base::SysInfo::DisplayCount());
initial.commit09911bf2008-07-26 23:55:29305 }
306
307 {
308 OPEN_ELEMENT_FOR_SCOPE("bookmarks");
309 int num_bookmarks_on_bookmark_bar =
310 pref->GetInteger(prefs::kNumBookmarksOnBookmarkBar);
311 int num_folders_on_bookmark_bar =
312 pref->GetInteger(prefs::kNumFoldersOnBookmarkBar);
313 int num_bookmarks_in_other_bookmarks_folder =
314 pref->GetInteger(prefs::kNumBookmarksInOtherBookmarkFolder);
315 int num_folders_in_other_bookmarks_folder =
316 pref->GetInteger(prefs::kNumFoldersInOtherBookmarkFolder);
317 {
318 OPEN_ELEMENT_FOR_SCOPE("bookmarklocation");
319 WriteAttribute("name", "full-tree");
320 WriteIntAttribute("foldercount",
321 num_folders_on_bookmark_bar + num_folders_in_other_bookmarks_folder);
322 WriteIntAttribute("itemcount",
323 num_bookmarks_on_bookmark_bar +
324 num_bookmarks_in_other_bookmarks_folder);
325 }
326 {
327 OPEN_ELEMENT_FOR_SCOPE("bookmarklocation");
328 WriteAttribute("name", "toolbar");
329 WriteIntAttribute("foldercount", num_folders_on_bookmark_bar);
330 WriteIntAttribute("itemcount", num_bookmarks_on_bookmark_bar);
331 }
332 }
333
334 {
335 OPEN_ELEMENT_FOR_SCOPE("keywords");
336 WriteIntAttribute("count", pref->GetInteger(prefs::kNumKeywords));
337 }
338
339 if (profile_metrics)
340 WriteAllProfilesMetrics(*profile_metrics);
initial.commit09911bf2008-07-26 23:55:29341}
342
343void MetricsLog::WriteAllProfilesMetrics(
344 const DictionaryValue& all_profiles_metrics) {
345 const std::wstring profile_prefix(prefs::kProfilePrefix);
346 for (DictionaryValue::key_iterator i = all_profiles_metrics.begin_keys();
347 i != all_profiles_metrics.end_keys(); ++i) {
[email protected]8e50b602009-03-03 22:59:43348 const std::wstring& key_name = *i;
initial.commit09911bf2008-07-26 23:55:29349 if (key_name.compare(0, profile_prefix.size(), profile_prefix) == 0) {
350 DictionaryValue* profile;
[email protected]4dad9ad82009-11-25 20:47:52351 if (all_profiles_metrics.GetDictionaryWithoutPathExpansion(key_name,
352 &profile))
initial.commit09911bf2008-07-26 23:55:29353 WriteProfileMetrics(key_name.substr(profile_prefix.size()), *profile);
354 }
355 }
356}
357
358void MetricsLog::WriteProfileMetrics(const std::wstring& profileidhash,
359 const DictionaryValue& profile_metrics) {
360 OPEN_ELEMENT_FOR_SCOPE("userprofile");
361 WriteAttribute("profileidhash", WideToUTF8(profileidhash));
362 for (DictionaryValue::key_iterator i = profile_metrics.begin_keys();
363 i != profile_metrics.end_keys(); ++i) {
364 Value* value;
[email protected]4dad9ad82009-11-25 20:47:52365 if (profile_metrics.GetWithoutPathExpansion(*i, &value)) {
[email protected]8e50b602009-03-03 22:59:43366 DCHECK(*i != L"id");
initial.commit09911bf2008-07-26 23:55:29367 switch (value->GetType()) {
368 case Value::TYPE_STRING: {
[email protected]5e324b72008-12-18 00:07:59369 std::string string_value;
initial.commit09911bf2008-07-26 23:55:29370 if (value->GetAsString(&string_value)) {
371 OPEN_ELEMENT_FOR_SCOPE("profileparam");
[email protected]8e50b602009-03-03 22:59:43372 WriteAttribute("name", WideToUTF8(*i));
[email protected]5e324b72008-12-18 00:07:59373 WriteAttribute("value", string_value);
initial.commit09911bf2008-07-26 23:55:29374 }
375 break;
376 }
377
378 case Value::TYPE_BOOLEAN: {
379 bool bool_value;
380 if (value->GetAsBoolean(&bool_value)) {
381 OPEN_ELEMENT_FOR_SCOPE("profileparam");
[email protected]8e50b602009-03-03 22:59:43382 WriteAttribute("name", WideToUTF8(*i));
initial.commit09911bf2008-07-26 23:55:29383 WriteIntAttribute("value", bool_value ? 1 : 0);
384 }
385 break;
386 }
387
388 case Value::TYPE_INTEGER: {
389 int int_value;
390 if (value->GetAsInteger(&int_value)) {
391 OPEN_ELEMENT_FOR_SCOPE("profileparam");
[email protected]8e50b602009-03-03 22:59:43392 WriteAttribute("name", WideToUTF8(*i));
initial.commit09911bf2008-07-26 23:55:29393 WriteIntAttribute("value", int_value);
394 }
395 break;
396 }
397
398 default:
399 NOTREACHED();
400 break;
401 }
402 }
403 }
404}
405
406void MetricsLog::RecordOmniboxOpenedURL(const AutocompleteLog& log) {
407 DCHECK(!locked_);
408
[email protected]ffaf78a2008-11-12 17:38:33409 OPEN_ELEMENT_FOR_SCOPE("uielement");
initial.commit09911bf2008-07-26 23:55:29410 WriteAttribute("action", "autocomplete");
411 WriteAttribute("targetidhash", "");
412 // TODO(kochi): Properly track windows.
413 WriteIntAttribute("window", 0);
414 WriteCommonEventAttributes();
415
[email protected]ffaf78a2008-11-12 17:38:33416 {
417 OPEN_ELEMENT_FOR_SCOPE("autocomplete");
initial.commit09911bf2008-07-26 23:55:29418
[email protected]ffaf78a2008-11-12 17:38:33419 WriteIntAttribute("typedlength", static_cast<int>(log.text.length()));
420 WriteIntAttribute("selectedindex", static_cast<int>(log.selected_index));
421 WriteIntAttribute("completedlength",
422 static_cast<int>(log.inline_autocompleted_length));
[email protected]381e2992008-12-16 01:41:00423 const std::string input_type(
424 AutocompleteInput::TypeToString(log.input_type));
425 if (!input_type.empty())
426 WriteAttribute("inputtype", input_type);
initial.commit09911bf2008-07-26 23:55:29427
[email protected]ffaf78a2008-11-12 17:38:33428 for (AutocompleteResult::const_iterator i(log.result.begin());
429 i != log.result.end(); ++i) {
430 OPEN_ELEMENT_FOR_SCOPE("autocompleteitem");
431 if (i->provider)
432 WriteAttribute("provider", i->provider->name());
[email protected]381e2992008-12-16 01:41:00433 const std::string result_type(AutocompleteMatch::TypeToString(i->type));
434 if (!result_type.empty())
435 WriteAttribute("resulttype", result_type);
[email protected]ffaf78a2008-11-12 17:38:33436 WriteIntAttribute("relevance", i->relevance);
437 WriteIntAttribute("isstarred", i->starred ? 1 : 0);
438 }
initial.commit09911bf2008-07-26 23:55:29439 }
initial.commit09911bf2008-07-26 23:55:29440
441 ++num_events_;
442}