| OLD | NEW |
| 1 // Copyright 2014 The Chromium Authors. All rights reserved. | 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 | 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 "components/metrics/metrics_log.h" | 5 #include "components/metrics/metrics_log.h" |
| 6 | 6 |
| 7 #include <stddef.h> | 7 #include <stddef.h> |
| 8 | 8 |
| 9 #include <algorithm> | 9 #include <algorithm> |
| 10 #include <memory> | 10 #include <memory> |
| 11 #include <string> | 11 #include <string> |
| 12 #include <vector> | 12 #include <vector> |
| 13 | 13 |
| 14 #include "base/base64.h" | |
| 15 #include "base/build_time.h" | 14 #include "base/build_time.h" |
| 16 #include "base/cpu.h" | 15 #include "base/cpu.h" |
| 17 #include "base/metrics/histogram_macros.h" | 16 #include "base/metrics/histogram_macros.h" |
| 18 #include "base/metrics/histogram_samples.h" | 17 #include "base/metrics/histogram_samples.h" |
| 19 #include "base/metrics/metrics_hashes.h" | 18 #include "base/metrics/metrics_hashes.h" |
| 20 #include "base/sha1.h" | |
| 21 #include "base/strings/string_number_conversions.h" | |
| 22 #include "base/strings/string_util.h" | |
| 23 #include "base/strings/utf_string_conversions.h" | |
| 24 #include "base/sys_info.h" | 19 #include "base/sys_info.h" |
| 25 #include "base/time/time.h" | 20 #include "base/time/time.h" |
| 26 #include "build/build_config.h" | 21 #include "build/build_config.h" |
| 22 #include "components/metrics/environment_recorder.h" |
| 27 #include "components/metrics/histogram_encoder.h" | 23 #include "components/metrics/histogram_encoder.h" |
| 28 #include "components/metrics/metrics_pref_names.h" | 24 #include "components/metrics/metrics_pref_names.h" |
| 29 #include "components/metrics/metrics_provider.h" | 25 #include "components/metrics/metrics_provider.h" |
| 30 #include "components/metrics/metrics_service_client.h" | 26 #include "components/metrics/metrics_service_client.h" |
| 31 #include "components/metrics/proto/histogram_event.pb.h" | 27 #include "components/metrics/proto/histogram_event.pb.h" |
| 32 #include "components/metrics/proto/system_profile.pb.h" | 28 #include "components/metrics/proto/system_profile.pb.h" |
| 33 #include "components/metrics/proto/user_action_event.pb.h" | 29 #include "components/metrics/proto/user_action_event.pb.h" |
| 34 #include "components/prefs/pref_registry_simple.h" | 30 #include "components/prefs/pref_registry_simple.h" |
| 35 #include "components/prefs/pref_service.h" | 31 #include "components/prefs/pref_service.h" |
| 36 #include "components/variations/active_field_trials.h" | 32 #include "components/variations/active_field_trials.h" |
| (...skipping 11 matching lines...) Expand all Loading... |
| 48 | 44 |
| 49 namespace metrics { | 45 namespace metrics { |
| 50 | 46 |
| 51 namespace { | 47 namespace { |
| 52 | 48 |
| 53 // Any id less than 16 bytes is considered to be a testing id. | 49 // Any id less than 16 bytes is considered to be a testing id. |
| 54 bool IsTestingID(const std::string& id) { | 50 bool IsTestingID(const std::string& id) { |
| 55 return id.size() < 16; | 51 return id.size() < 16; |
| 56 } | 52 } |
| 57 | 53 |
| 58 // Computes a SHA-1 hash of |data| and returns it as a hex string. | |
| 59 std::string ComputeSHA1(const std::string& data) { | |
| 60 const std::string sha1 = base::SHA1HashString(data); | |
| 61 return base::HexEncode(sha1.data(), sha1.size()); | |
| 62 } | |
| 63 | |
| 64 void WriteFieldTrials(const std::vector<ActiveGroupId>& field_trial_ids, | 54 void WriteFieldTrials(const std::vector<ActiveGroupId>& field_trial_ids, |
| 65 SystemProfileProto* system_profile) { | 55 SystemProfileProto* system_profile) { |
| 66 for (std::vector<ActiveGroupId>::const_iterator it = | 56 for (std::vector<ActiveGroupId>::const_iterator it = |
| 67 field_trial_ids.begin(); it != field_trial_ids.end(); ++it) { | 57 field_trial_ids.begin(); it != field_trial_ids.end(); ++it) { |
| 68 SystemProfileProto::FieldTrial* field_trial = | 58 SystemProfileProto::FieldTrial* field_trial = |
| 69 system_profile->add_field_trial(); | 59 system_profile->add_field_trial(); |
| 70 field_trial->set_name_id(it->name); | 60 field_trial->set_name_id(it->name); |
| 71 field_trial->set_group_id(it->group); | 61 field_trial->set_group_id(it->group); |
| 72 } | 62 } |
| 73 } | 63 } |
| (...skipping 29 matching lines...) Expand all Loading... |
| 103 if (product != uma_proto_.product()) | 93 if (product != uma_proto_.product()) |
| 104 uma_proto_.set_product(product); | 94 uma_proto_.set_product(product); |
| 105 | 95 |
| 106 RecordCoreSystemProfile(client_, uma_proto_.mutable_system_profile()); | 96 RecordCoreSystemProfile(client_, uma_proto_.mutable_system_profile()); |
| 107 } | 97 } |
| 108 | 98 |
| 109 MetricsLog::~MetricsLog() { | 99 MetricsLog::~MetricsLog() { |
| 110 } | 100 } |
| 111 | 101 |
| 112 // static | 102 // static |
| 113 void MetricsLog::RegisterPrefs(PrefRegistrySimple* registry) { | |
| 114 registry->RegisterIntegerPref(prefs::kStabilityCrashCount, 0); | |
| 115 registry->RegisterIntegerPref(prefs::kStabilityIncompleteSessionEndCount, 0); | |
| 116 registry->RegisterIntegerPref(prefs::kStabilityLaunchCount, 0); | |
| 117 registry->RegisterIntegerPref(prefs::kStabilityBreakpadRegistrationFail, 0); | |
| 118 registry->RegisterIntegerPref( | |
| 119 prefs::kStabilityBreakpadRegistrationSuccess, 0); | |
| 120 registry->RegisterIntegerPref(prefs::kStabilityDebuggerPresent, 0); | |
| 121 registry->RegisterIntegerPref(prefs::kStabilityDebuggerNotPresent, 0); | |
| 122 registry->RegisterStringPref(prefs::kStabilitySavedSystemProfile, | |
| 123 std::string()); | |
| 124 registry->RegisterStringPref(prefs::kStabilitySavedSystemProfileHash, | |
| 125 std::string()); | |
| 126 registry->RegisterIntegerPref(prefs::kStabilityDeferredCount, 0); | |
| 127 registry->RegisterIntegerPref(prefs::kStabilityDiscardCount, 0); | |
| 128 registry->RegisterIntegerPref(prefs::kStabilityVersionMismatchCount, 0); | |
| 129 } | |
| 130 | |
| 131 // static | |
| 132 uint64_t MetricsLog::Hash(const std::string& value) { | 103 uint64_t MetricsLog::Hash(const std::string& value) { |
| 133 uint64_t hash = base::HashMetricName(value); | 104 uint64_t hash = base::HashMetricName(value); |
| 134 | 105 |
| 135 // The following log is VERY helpful when folks add some named histogram into | 106 // The following log is VERY helpful when folks add some named histogram into |
| 136 // the code, but forgot to update the descriptive list of histograms. When | 107 // the code, but forgot to update the descriptive list of histograms. When |
| 137 // that happens, all we get to see (server side) is a hash of the histogram | 108 // that happens, all we get to see (server side) is a hash of the histogram |
| 138 // name. We can then use this logging to find out what histogram name was | 109 // name. We can then use this logging to find out what histogram name was |
| 139 // being hashed to a given MD5 value by just running the version of Chromium | 110 // being hashed to a given MD5 value by just running the version of Chromium |
| 140 // in question with --enable-logging. | 111 // in question with --enable-logging. |
| 141 DVLOG(1) << "Metrics: Hash numeric [" << value << "]=[" << hash << "]"; | 112 DVLOG(1) << "Metrics: Hash numeric [" << value << "]=[" << hash << "]"; |
| (...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 205 } | 176 } |
| 206 | 177 |
| 207 void MetricsLog::RecordStabilityMetrics( | 178 void MetricsLog::RecordStabilityMetrics( |
| 208 const std::vector<MetricsProvider*>& metrics_providers, | 179 const std::vector<MetricsProvider*>& metrics_providers, |
| 209 base::TimeDelta incremental_uptime, | 180 base::TimeDelta incremental_uptime, |
| 210 base::TimeDelta uptime) { | 181 base::TimeDelta uptime) { |
| 211 DCHECK(!closed_); | 182 DCHECK(!closed_); |
| 212 DCHECK(HasEnvironment()); | 183 DCHECK(HasEnvironment()); |
| 213 DCHECK(!HasStabilityMetrics()); | 184 DCHECK(!HasStabilityMetrics()); |
| 214 | 185 |
| 215 PrefService* pref = local_state_; | |
| 216 DCHECK(pref); | |
| 217 | |
| 218 // Get stability attributes out of Local State, zeroing out stored values. | |
| 219 // NOTE: This could lead to some data loss if this report isn't successfully | |
| 220 // sent, but that's true for all the metrics. | |
| 221 | |
| 222 WriteRequiredStabilityAttributes(pref); | |
| 223 | |
| 224 // Record recent delta for critical stability metrics. We can't wait for a | 186 // Record recent delta for critical stability metrics. We can't wait for a |
| 225 // restart to gather these, as that delay biases our observation away from | 187 // restart to gather these, as that delay biases our observation away from |
| 226 // users that run happily for a looooong time. We send increments with each | 188 // users that run happily for a looooong time. We send increments with each |
| 227 // uma log upload, just as we send histogram data. | 189 // uma log upload, just as we send histogram data. |
| 228 WriteRealtimeStabilityAttributes(pref, incremental_uptime, uptime); | 190 WriteRealtimeStabilityAttributes(incremental_uptime, uptime); |
| 229 | 191 |
| 230 SystemProfileProto* system_profile = uma_proto()->mutable_system_profile(); | 192 SystemProfileProto* system_profile = uma_proto()->mutable_system_profile(); |
| 231 for (size_t i = 0; i < metrics_providers.size(); ++i) { | 193 for (size_t i = 0; i < metrics_providers.size(); ++i) { |
| 232 if (log_type() == INITIAL_STABILITY_LOG) | 194 if (log_type() == INITIAL_STABILITY_LOG) |
| 233 metrics_providers[i]->ProvideInitialStabilityMetrics(system_profile); | 195 metrics_providers[i]->ProvideInitialStabilityMetrics(system_profile); |
| 234 metrics_providers[i]->ProvideStabilityMetrics(system_profile); | 196 metrics_providers[i]->ProvideStabilityMetrics(system_profile); |
| 235 } | 197 } |
| 236 | |
| 237 SystemProfileProto::Stability* stability = | |
| 238 system_profile->mutable_stability(); | |
| 239 | |
| 240 int incomplete_shutdown_count = | |
| 241 pref->GetInteger(prefs::kStabilityIncompleteSessionEndCount); | |
| 242 if (incomplete_shutdown_count) { | |
| 243 pref->SetInteger(prefs::kStabilityIncompleteSessionEndCount, 0); | |
| 244 stability->set_incomplete_shutdown_count(incomplete_shutdown_count); | |
| 245 } | |
| 246 | |
| 247 int breakpad_registration_success_count = | |
| 248 pref->GetInteger(prefs::kStabilityBreakpadRegistrationSuccess); | |
| 249 if (breakpad_registration_success_count) { | |
| 250 pref->SetInteger(prefs::kStabilityBreakpadRegistrationSuccess, 0); | |
| 251 stability->set_breakpad_registration_success_count( | |
| 252 breakpad_registration_success_count); | |
| 253 } | |
| 254 | |
| 255 int breakpad_registration_failure_count = | |
| 256 pref->GetInteger(prefs::kStabilityBreakpadRegistrationFail); | |
| 257 if (breakpad_registration_failure_count) { | |
| 258 pref->SetInteger(prefs::kStabilityBreakpadRegistrationFail, 0); | |
| 259 stability->set_breakpad_registration_failure_count( | |
| 260 breakpad_registration_failure_count); | |
| 261 } | |
| 262 | |
| 263 int debugger_present_count = | |
| 264 pref->GetInteger(prefs::kStabilityDebuggerPresent); | |
| 265 if (debugger_present_count) { | |
| 266 pref->SetInteger(prefs::kStabilityDebuggerPresent, 0); | |
| 267 stability->set_debugger_present_count(debugger_present_count); | |
| 268 } | |
| 269 | |
| 270 int debugger_not_present_count = | |
| 271 pref->GetInteger(prefs::kStabilityDebuggerNotPresent); | |
| 272 if (debugger_not_present_count) { | |
| 273 pref->SetInteger(prefs::kStabilityDebuggerNotPresent, 0); | |
| 274 stability->set_debugger_not_present_count(debugger_not_present_count); | |
| 275 } | |
| 276 | |
| 277 // Note: only logging the following histograms for non-zero values. | |
| 278 | |
| 279 int deferred_count = pref->GetInteger(prefs::kStabilityDeferredCount); | |
| 280 if (deferred_count) { | |
| 281 local_state_->SetInteger(prefs::kStabilityDeferredCount, 0); | |
| 282 UMA_STABILITY_HISTOGRAM_COUNTS_100( | |
| 283 "Stability.Internals.InitialStabilityLogDeferredCount", deferred_count); | |
| 284 } | |
| 285 | |
| 286 int discard_count = local_state_->GetInteger(prefs::kStabilityDiscardCount); | |
| 287 if (discard_count) { | |
| 288 local_state_->SetInteger(prefs::kStabilityDiscardCount, 0); | |
| 289 UMA_STABILITY_HISTOGRAM_COUNTS_100("Stability.Internals.DataDiscardCount", | |
| 290 discard_count); | |
| 291 } | |
| 292 | |
| 293 int version_mismatch_count = | |
| 294 local_state_->GetInteger(prefs::kStabilityVersionMismatchCount); | |
| 295 if (version_mismatch_count) { | |
| 296 local_state_->SetInteger(prefs::kStabilityVersionMismatchCount, 0); | |
| 297 UMA_STABILITY_HISTOGRAM_COUNTS_100( | |
| 298 "Stability.Internals.VersionMismatchCount", | |
| 299 version_mismatch_count); | |
| 300 } | |
| 301 } | 198 } |
| 302 | 199 |
| 303 void MetricsLog::RecordGeneralMetrics( | 200 void MetricsLog::RecordGeneralMetrics( |
| 304 const std::vector<MetricsProvider*>& metrics_providers) { | 201 const std::vector<MetricsProvider*>& metrics_providers) { |
| 305 if (local_state_->GetBoolean(prefs::kMetricsResetIds)) | 202 if (local_state_->GetBoolean(prefs::kMetricsResetIds)) |
| 306 UMA_HISTOGRAM_BOOLEAN("UMA.IsClonedInstall", true); | 203 UMA_HISTOGRAM_BOOLEAN("UMA.IsClonedInstall", true); |
| 307 | 204 |
| 308 for (size_t i = 0; i < metrics_providers.size(); ++i) | 205 for (size_t i = 0; i < metrics_providers.size(); ++i) |
| 309 metrics_providers[i]->ProvideGeneralMetrics(uma_proto()); | 206 metrics_providers[i]->ProvideGeneralMetrics(uma_proto()); |
| 310 } | 207 } |
| (...skipping 28 matching lines...) Expand all Loading... |
| 339 case EnableMetricsDefault::OPT_OUT: | 236 case EnableMetricsDefault::OPT_OUT: |
| 340 system_profile->set_uma_default_state( | 237 system_profile->set_uma_default_state( |
| 341 SystemProfileProto_UmaDefaultState_OPT_OUT); | 238 SystemProfileProto_UmaDefaultState_OPT_OUT); |
| 342 } | 239 } |
| 343 } | 240 } |
| 344 | 241 |
| 345 bool MetricsLog::HasStabilityMetrics() const { | 242 bool MetricsLog::HasStabilityMetrics() const { |
| 346 return uma_proto()->system_profile().stability().has_launch_count(); | 243 return uma_proto()->system_profile().stability().has_launch_count(); |
| 347 } | 244 } |
| 348 | 245 |
| 349 // The server refuses data that doesn't have certain values. crashcount and | |
| 350 // launchcount are currently "required" in the "stability" group. | |
| 351 // TODO(isherman): Stop writing these attributes specially once the migration to | |
| 352 // protobufs is complete. | |
| 353 void MetricsLog::WriteRequiredStabilityAttributes(PrefService* pref) { | |
| 354 int launch_count = pref->GetInteger(prefs::kStabilityLaunchCount); | |
| 355 if (launch_count) | |
| 356 pref->SetInteger(prefs::kStabilityLaunchCount, 0); | |
| 357 int crash_count = pref->GetInteger(prefs::kStabilityCrashCount); | |
| 358 if (crash_count) | |
| 359 pref->SetInteger(prefs::kStabilityCrashCount, 0); | |
| 360 | |
| 361 SystemProfileProto::Stability* stability = | |
| 362 uma_proto()->mutable_system_profile()->mutable_stability(); | |
| 363 stability->set_launch_count(launch_count); | |
| 364 stability->set_crash_count(crash_count); | |
| 365 } | |
| 366 | |
| 367 void MetricsLog::WriteRealtimeStabilityAttributes( | 246 void MetricsLog::WriteRealtimeStabilityAttributes( |
| 368 PrefService* pref, | |
| 369 base::TimeDelta incremental_uptime, | 247 base::TimeDelta incremental_uptime, |
| 370 base::TimeDelta uptime) { | 248 base::TimeDelta uptime) { |
| 371 // Update the stats which are critical for real-time stability monitoring. | 249 // Update the stats which are critical for real-time stability monitoring. |
| 372 // Since these are "optional," only list ones that are non-zero, as the counts | 250 // Since these are "optional," only list ones that are non-zero, as the counts |
| 373 // are aggregated (summed) server side. | 251 // are aggregated (summed) server side. |
| 374 | 252 |
| 375 SystemProfileProto::Stability* stability = | 253 SystemProfileProto::Stability* stability = |
| 376 uma_proto()->mutable_system_profile()->mutable_stability(); | 254 uma_proto()->mutable_system_profile()->mutable_stability(); |
| 377 | 255 |
| 378 const uint64_t incremental_uptime_sec = incremental_uptime.InSeconds(); | 256 const uint64_t incremental_uptime_sec = incremental_uptime.InSeconds(); |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 414 cpu->set_num_cores(base::SysInfo::NumberOfProcessors()); | 292 cpu->set_num_cores(base::SysInfo::NumberOfProcessors()); |
| 415 | 293 |
| 416 std::vector<ActiveGroupId> field_trial_ids; | 294 std::vector<ActiveGroupId> field_trial_ids; |
| 417 GetFieldTrialIds(&field_trial_ids); | 295 GetFieldTrialIds(&field_trial_ids); |
| 418 WriteFieldTrials(field_trial_ids, system_profile); | 296 WriteFieldTrials(field_trial_ids, system_profile); |
| 419 WriteFieldTrials(synthetic_trials, system_profile); | 297 WriteFieldTrials(synthetic_trials, system_profile); |
| 420 | 298 |
| 421 for (size_t i = 0; i < metrics_providers.size(); ++i) | 299 for (size_t i = 0; i < metrics_providers.size(); ++i) |
| 422 metrics_providers[i]->ProvideSystemProfileMetrics(system_profile); | 300 metrics_providers[i]->ProvideSystemProfileMetrics(system_profile); |
| 423 | 301 |
| 424 std::string serialized_system_profile; | 302 EnvironmentRecorder recorder(local_state_); |
| 425 std::string base64_system_profile; | 303 return recorder.RecordEnvironmentToPrefs(*system_profile); |
| 426 if (system_profile->SerializeToString(&serialized_system_profile)) { | |
| 427 // Persist the system profile to disk. In the event of an unclean shutdown, | |
| 428 // it will be used as part of the initial stability report. | |
| 429 base::Base64Encode(serialized_system_profile, &base64_system_profile); | |
| 430 PrefService* local_state = local_state_; | |
| 431 local_state->SetString(prefs::kStabilitySavedSystemProfile, | |
| 432 base64_system_profile); | |
| 433 local_state->SetString(prefs::kStabilitySavedSystemProfileHash, | |
| 434 ComputeSHA1(serialized_system_profile)); | |
| 435 } | |
| 436 | |
| 437 return serialized_system_profile; | |
| 438 } | 304 } |
| 439 | 305 |
| 440 bool MetricsLog::LoadSavedEnvironmentFromPrefs(std::string* app_version) { | 306 bool MetricsLog::LoadSavedEnvironmentFromPrefs(std::string* app_version) { |
| 441 DCHECK(app_version); | 307 DCHECK(app_version); |
| 442 app_version->clear(); | 308 app_version->clear(); |
| 443 | 309 |
| 444 PrefService* local_state = local_state_; | |
| 445 const std::string base64_system_profile = | |
| 446 local_state->GetString(prefs::kStabilitySavedSystemProfile); | |
| 447 if (base64_system_profile.empty()) | |
| 448 return false; | |
| 449 const std::string system_profile_hash = | |
| 450 local_state->GetString(prefs::kStabilitySavedSystemProfileHash); | |
| 451 | |
| 452 SystemProfileProto* system_profile = uma_proto()->mutable_system_profile(); | 310 SystemProfileProto* system_profile = uma_proto()->mutable_system_profile(); |
| 453 std::string serialized_system_profile; | 311 EnvironmentRecorder recorder(local_state_); |
| 454 | 312 bool success = recorder.LoadEnvironmentFromPrefs(system_profile); |
| 455 bool success = | |
| 456 base::Base64Decode(base64_system_profile, &serialized_system_profile) && | |
| 457 ComputeSHA1(serialized_system_profile) == system_profile_hash && | |
| 458 system_profile->ParseFromString(serialized_system_profile); | |
| 459 if (success) | 313 if (success) |
| 460 *app_version = system_profile->app_version(); | 314 *app_version = system_profile->app_version(); |
| 461 return success; | 315 return success; |
| 462 } | 316 } |
| 463 | 317 |
| 464 void MetricsLog::CloseLog() { | 318 void MetricsLog::CloseLog() { |
| 465 DCHECK(!closed_); | 319 DCHECK(!closed_); |
| 466 closed_ = true; | 320 closed_ = true; |
| 467 } | 321 } |
| 468 | 322 |
| 469 void MetricsLog::GetEncodedLog(std::string* encoded_log) { | 323 void MetricsLog::GetEncodedLog(std::string* encoded_log) { |
| 470 DCHECK(closed_); | 324 DCHECK(closed_); |
| 471 uma_proto_.SerializeToString(encoded_log); | 325 uma_proto_.SerializeToString(encoded_log); |
| 472 } | 326 } |
| 473 | 327 |
| 474 } // namespace metrics | 328 } // namespace metrics |
| OLD | NEW |