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