1*6777b538SAndroid Build Coastguard Worker // Copyright 2017 The Chromium Authors
2*6777b538SAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be
3*6777b538SAndroid Build Coastguard Worker // found in the LICENSE file.
4*6777b538SAndroid Build Coastguard Worker
5*6777b538SAndroid Build Coastguard Worker #include "components/metrics/stability_metrics_provider.h"
6*6777b538SAndroid Build Coastguard Worker
7*6777b538SAndroid Build Coastguard Worker #include <string>
8*6777b538SAndroid Build Coastguard Worker
9*6777b538SAndroid Build Coastguard Worker #include "base/logging.h"
10*6777b538SAndroid Build Coastguard Worker #include "base/metrics/histogram_macros.h"
11*6777b538SAndroid Build Coastguard Worker #include "build/build_config.h"
12*6777b538SAndroid Build Coastguard Worker #include "components/metrics/metrics_pref_names.h"
13*6777b538SAndroid Build Coastguard Worker #include "components/metrics/stability_metrics_helper.h"
14*6777b538SAndroid Build Coastguard Worker #include "components/prefs/pref_registry_simple.h"
15*6777b538SAndroid Build Coastguard Worker #include "components/prefs/pref_service.h"
16*6777b538SAndroid Build Coastguard Worker #include "components/prefs/scoped_user_pref_update.h"
17*6777b538SAndroid Build Coastguard Worker #include "third_party/metrics_proto/system_profile.pb.h"
18*6777b538SAndroid Build Coastguard Worker
19*6777b538SAndroid Build Coastguard Worker #if BUILDFLAG(IS_ANDROID)
20*6777b538SAndroid Build Coastguard Worker #include "base/android/build_info.h"
21*6777b538SAndroid Build Coastguard Worker #endif
22*6777b538SAndroid Build Coastguard Worker #if BUILDFLAG(IS_WIN)
23*6777b538SAndroid Build Coastguard Worker #include "components/metrics/system_session_analyzer/system_session_analyzer_win.h"
24*6777b538SAndroid Build Coastguard Worker #endif
25*6777b538SAndroid Build Coastguard Worker
26*6777b538SAndroid Build Coastguard Worker namespace metrics {
27*6777b538SAndroid Build Coastguard Worker
28*6777b538SAndroid Build Coastguard Worker namespace {
29*6777b538SAndroid Build Coastguard Worker
30*6777b538SAndroid Build Coastguard Worker #if BUILDFLAG(IS_ANDROID)
HasGmsCoreVersionChanged(PrefService * local_state)31*6777b538SAndroid Build Coastguard Worker bool HasGmsCoreVersionChanged(PrefService* local_state) {
32*6777b538SAndroid Build Coastguard Worker std::string previous_version =
33*6777b538SAndroid Build Coastguard Worker local_state->GetString(prefs::kStabilityGmsCoreVersion);
34*6777b538SAndroid Build Coastguard Worker std::string current_version =
35*6777b538SAndroid Build Coastguard Worker base::android::BuildInfo::GetInstance()->gms_version_code();
36*6777b538SAndroid Build Coastguard Worker
37*6777b538SAndroid Build Coastguard Worker // If the last version is empty, treat it as consistent.
38*6777b538SAndroid Build Coastguard Worker if (previous_version.empty())
39*6777b538SAndroid Build Coastguard Worker return false;
40*6777b538SAndroid Build Coastguard Worker
41*6777b538SAndroid Build Coastguard Worker return previous_version != current_version;
42*6777b538SAndroid Build Coastguard Worker }
43*6777b538SAndroid Build Coastguard Worker
UpdateGmsCoreVersionPref(PrefService * local_state)44*6777b538SAndroid Build Coastguard Worker void UpdateGmsCoreVersionPref(PrefService* local_state) {
45*6777b538SAndroid Build Coastguard Worker std::string current_version =
46*6777b538SAndroid Build Coastguard Worker base::android::BuildInfo::GetInstance()->gms_version_code();
47*6777b538SAndroid Build Coastguard Worker local_state->SetString(prefs::kStabilityGmsCoreVersion, current_version);
48*6777b538SAndroid Build Coastguard Worker }
49*6777b538SAndroid Build Coastguard Worker #endif
50*6777b538SAndroid Build Coastguard Worker
51*6777b538SAndroid Build Coastguard Worker } // namespace
52*6777b538SAndroid Build Coastguard Worker
StabilityMetricsProvider(PrefService * local_state)53*6777b538SAndroid Build Coastguard Worker StabilityMetricsProvider::StabilityMetricsProvider(PrefService* local_state)
54*6777b538SAndroid Build Coastguard Worker : local_state_(local_state) {}
55*6777b538SAndroid Build Coastguard Worker
56*6777b538SAndroid Build Coastguard Worker StabilityMetricsProvider::~StabilityMetricsProvider() = default;
57*6777b538SAndroid Build Coastguard Worker
58*6777b538SAndroid Build Coastguard Worker // static
RegisterPrefs(PrefRegistrySimple * registry)59*6777b538SAndroid Build Coastguard Worker void StabilityMetricsProvider::RegisterPrefs(PrefRegistrySimple* registry) {
60*6777b538SAndroid Build Coastguard Worker registry->RegisterIntegerPref(prefs::kStabilityFileMetricsUnsentFilesCount,
61*6777b538SAndroid Build Coastguard Worker 0);
62*6777b538SAndroid Build Coastguard Worker registry->RegisterIntegerPref(prefs::kStabilityFileMetricsUnsentSamplesCount,
63*6777b538SAndroid Build Coastguard Worker 0);
64*6777b538SAndroid Build Coastguard Worker
65*6777b538SAndroid Build Coastguard Worker #if BUILDFLAG(IS_ANDROID)
66*6777b538SAndroid Build Coastguard Worker registry->RegisterIntegerPref(prefs::kStabilityLaunchCount, 0);
67*6777b538SAndroid Build Coastguard Worker registry->RegisterStringPref(prefs::kStabilityGmsCoreVersion, "");
68*6777b538SAndroid Build Coastguard Worker registry->RegisterIntegerPref(prefs::kStabilityCrashCountDueToGmsCoreUpdate,
69*6777b538SAndroid Build Coastguard Worker 0);
70*6777b538SAndroid Build Coastguard Worker #endif
71*6777b538SAndroid Build Coastguard Worker #if BUILDFLAG(IS_WIN)
72*6777b538SAndroid Build Coastguard Worker registry->RegisterIntegerPref(prefs::kStabilitySystemCrashCount, 0);
73*6777b538SAndroid Build Coastguard Worker #endif
74*6777b538SAndroid Build Coastguard Worker }
75*6777b538SAndroid Build Coastguard Worker
Init()76*6777b538SAndroid Build Coastguard Worker void StabilityMetricsProvider::Init() {
77*6777b538SAndroid Build Coastguard Worker #if BUILDFLAG(IS_ANDROID)
78*6777b538SAndroid Build Coastguard Worker // This method has to be called after HasGmsCoreVersionChanged() to avoid
79*6777b538SAndroid Build Coastguard Worker // overwriting thie result.
80*6777b538SAndroid Build Coastguard Worker UpdateGmsCoreVersionPref(local_state_);
81*6777b538SAndroid Build Coastguard Worker #endif
82*6777b538SAndroid Build Coastguard Worker }
83*6777b538SAndroid Build Coastguard Worker
ClearSavedStabilityMetrics()84*6777b538SAndroid Build Coastguard Worker void StabilityMetricsProvider::ClearSavedStabilityMetrics() {
85*6777b538SAndroid Build Coastguard Worker // The 0 is a valid value for the below prefs, clears pref instead
86*6777b538SAndroid Build Coastguard Worker // of setting to default value.
87*6777b538SAndroid Build Coastguard Worker local_state_->ClearPref(prefs::kStabilityFileMetricsUnsentFilesCount);
88*6777b538SAndroid Build Coastguard Worker local_state_->ClearPref(prefs::kStabilityFileMetricsUnsentSamplesCount);
89*6777b538SAndroid Build Coastguard Worker
90*6777b538SAndroid Build Coastguard Worker #if BUILDFLAG(IS_ANDROID)
91*6777b538SAndroid Build Coastguard Worker local_state_->SetInteger(prefs::kStabilityLaunchCount, 0);
92*6777b538SAndroid Build Coastguard Worker #endif
93*6777b538SAndroid Build Coastguard Worker #if BUILDFLAG(IS_WIN)
94*6777b538SAndroid Build Coastguard Worker local_state_->SetInteger(prefs::kStabilitySystemCrashCount, 0);
95*6777b538SAndroid Build Coastguard Worker #endif
96*6777b538SAndroid Build Coastguard Worker }
97*6777b538SAndroid Build Coastguard Worker
ProvideStabilityMetrics(SystemProfileProto * system_profile)98*6777b538SAndroid Build Coastguard Worker void StabilityMetricsProvider::ProvideStabilityMetrics(
99*6777b538SAndroid Build Coastguard Worker SystemProfileProto* system_profile) {
100*6777b538SAndroid Build Coastguard Worker #if BUILDFLAG(IS_ANDROID)
101*6777b538SAndroid Build Coastguard Worker SystemProfileProto::Stability* stability =
102*6777b538SAndroid Build Coastguard Worker system_profile->mutable_stability();
103*6777b538SAndroid Build Coastguard Worker
104*6777b538SAndroid Build Coastguard Worker int pref_value = 0;
105*6777b538SAndroid Build Coastguard Worker if (GetAndClearPrefValue(prefs::kStabilityLaunchCount, &pref_value))
106*6777b538SAndroid Build Coastguard Worker stability->set_launch_count(pref_value);
107*6777b538SAndroid Build Coastguard Worker if (GetAndClearPrefValue(prefs::kStabilityCrashCountDueToGmsCoreUpdate,
108*6777b538SAndroid Build Coastguard Worker &pref_value)) {
109*6777b538SAndroid Build Coastguard Worker stability->set_crash_count_due_to_gms_core_update(pref_value);
110*6777b538SAndroid Build Coastguard Worker }
111*6777b538SAndroid Build Coastguard Worker #endif
112*6777b538SAndroid Build Coastguard Worker
113*6777b538SAndroid Build Coastguard Worker if (local_state_->HasPrefPath(prefs::kStabilityFileMetricsUnsentFilesCount)) {
114*6777b538SAndroid Build Coastguard Worker UMA_STABILITY_HISTOGRAM_COUNTS_100(
115*6777b538SAndroid Build Coastguard Worker "Stability.Internals.FileMetricsProvider.BrowserMetrics."
116*6777b538SAndroid Build Coastguard Worker "UnsentFilesCount",
117*6777b538SAndroid Build Coastguard Worker local_state_->GetInteger(prefs::kStabilityFileMetricsUnsentFilesCount));
118*6777b538SAndroid Build Coastguard Worker local_state_->ClearPref(prefs::kStabilityFileMetricsUnsentFilesCount);
119*6777b538SAndroid Build Coastguard Worker }
120*6777b538SAndroid Build Coastguard Worker
121*6777b538SAndroid Build Coastguard Worker if (local_state_->HasPrefPath(
122*6777b538SAndroid Build Coastguard Worker prefs::kStabilityFileMetricsUnsentSamplesCount)) {
123*6777b538SAndroid Build Coastguard Worker UMA_STABILITY_HISTOGRAM_CUSTOM_COUNTS(
124*6777b538SAndroid Build Coastguard Worker "Stability.Internals.FileMetricsProvider.BrowserMetrics."
125*6777b538SAndroid Build Coastguard Worker "UnsentSamplesCount",
126*6777b538SAndroid Build Coastguard Worker local_state_->GetInteger(
127*6777b538SAndroid Build Coastguard Worker prefs::kStabilityFileMetricsUnsentSamplesCount),
128*6777b538SAndroid Build Coastguard Worker 0, 1000000, 50);
129*6777b538SAndroid Build Coastguard Worker local_state_->ClearPref(prefs::kStabilityFileMetricsUnsentSamplesCount);
130*6777b538SAndroid Build Coastguard Worker }
131*6777b538SAndroid Build Coastguard Worker
132*6777b538SAndroid Build Coastguard Worker #if BUILDFLAG(IS_WIN)
133*6777b538SAndroid Build Coastguard Worker int pref_value = 0;
134*6777b538SAndroid Build Coastguard Worker if (GetAndClearPrefValue(prefs::kStabilitySystemCrashCount, &pref_value)) {
135*6777b538SAndroid Build Coastguard Worker UMA_STABILITY_HISTOGRAM_COUNTS_100("Stability.Internals.SystemCrashCount",
136*6777b538SAndroid Build Coastguard Worker pref_value);
137*6777b538SAndroid Build Coastguard Worker }
138*6777b538SAndroid Build Coastguard Worker #endif
139*6777b538SAndroid Build Coastguard Worker }
140*6777b538SAndroid Build Coastguard Worker
LogCrash(base::Time last_live_timestamp)141*6777b538SAndroid Build Coastguard Worker void StabilityMetricsProvider::LogCrash(base::Time last_live_timestamp) {
142*6777b538SAndroid Build Coastguard Worker #if BUILDFLAG(IS_ANDROID)
143*6777b538SAndroid Build Coastguard Worker // On Android, if there is an update for GMS Core when Chrome is running,
144*6777b538SAndroid Build Coastguard Worker // Chrome will be killed, counting as a crash. This is expected and should not
145*6777b538SAndroid Build Coastguard Worker // be counted in stability crash counts. Thus these crashes are added to a
146*6777b538SAndroid Build Coastguard Worker // specific bucket for crashes caused by GMS Core updates.
147*6777b538SAndroid Build Coastguard Worker if (HasGmsCoreVersionChanged(local_state_)) {
148*6777b538SAndroid Build Coastguard Worker IncrementPrefValue(prefs::kStabilityCrashCountDueToGmsCoreUpdate);
149*6777b538SAndroid Build Coastguard Worker return;
150*6777b538SAndroid Build Coastguard Worker }
151*6777b538SAndroid Build Coastguard Worker #endif
152*6777b538SAndroid Build Coastguard Worker StabilityMetricsHelper::RecordStabilityEvent(
153*6777b538SAndroid Build Coastguard Worker StabilityEventType::kBrowserCrash);
154*6777b538SAndroid Build Coastguard Worker
155*6777b538SAndroid Build Coastguard Worker #if BUILDFLAG(IS_WIN)
156*6777b538SAndroid Build Coastguard Worker MaybeLogSystemCrash(last_live_timestamp);
157*6777b538SAndroid Build Coastguard Worker #endif
158*6777b538SAndroid Build Coastguard Worker }
159*6777b538SAndroid Build Coastguard Worker
LogLaunch()160*6777b538SAndroid Build Coastguard Worker void StabilityMetricsProvider::LogLaunch() {
161*6777b538SAndroid Build Coastguard Worker #if BUILDFLAG(IS_ANDROID)
162*6777b538SAndroid Build Coastguard Worker IncrementPrefValue(prefs::kStabilityLaunchCount);
163*6777b538SAndroid Build Coastguard Worker #endif
164*6777b538SAndroid Build Coastguard Worker StabilityMetricsHelper::RecordStabilityEvent(StabilityEventType::kLaunch);
165*6777b538SAndroid Build Coastguard Worker }
166*6777b538SAndroid Build Coastguard Worker
167*6777b538SAndroid Build Coastguard Worker #if BUILDFLAG(IS_WIN)
IsUncleanSystemSession(base::Time last_live_timestamp)168*6777b538SAndroid Build Coastguard Worker bool StabilityMetricsProvider::IsUncleanSystemSession(
169*6777b538SAndroid Build Coastguard Worker base::Time last_live_timestamp) {
170*6777b538SAndroid Build Coastguard Worker DCHECK_NE(base::Time(), last_live_timestamp);
171*6777b538SAndroid Build Coastguard Worker // There's a non-null last live timestamp, see if this occurred in
172*6777b538SAndroid Build Coastguard Worker // a Windows system session that ended uncleanly. The expectation is that
173*6777b538SAndroid Build Coastguard Worker // |last_live_timestamp| will have occurred in the immediately previous system
174*6777b538SAndroid Build Coastguard Worker // session, but if the system has been restarted many times since Chrome last
175*6777b538SAndroid Build Coastguard Worker // ran, that's not necessarily true. Log traversal can be expensive, so we
176*6777b538SAndroid Build Coastguard Worker // limit the analyzer to reaching back three previous system sessions to bound
177*6777b538SAndroid Build Coastguard Worker // the cost of the traversal.
178*6777b538SAndroid Build Coastguard Worker SystemSessionAnalyzer analyzer(3);
179*6777b538SAndroid Build Coastguard Worker
180*6777b538SAndroid Build Coastguard Worker SystemSessionAnalyzer::Status status =
181*6777b538SAndroid Build Coastguard Worker analyzer.IsSessionUnclean(last_live_timestamp);
182*6777b538SAndroid Build Coastguard Worker
183*6777b538SAndroid Build Coastguard Worker return status == SystemSessionAnalyzer::UNCLEAN;
184*6777b538SAndroid Build Coastguard Worker }
185*6777b538SAndroid Build Coastguard Worker
MaybeLogSystemCrash(base::Time last_live_timestamp)186*6777b538SAndroid Build Coastguard Worker void StabilityMetricsProvider::MaybeLogSystemCrash(
187*6777b538SAndroid Build Coastguard Worker base::Time last_live_timestamp) {
188*6777b538SAndroid Build Coastguard Worker if (last_live_timestamp != base::Time() &&
189*6777b538SAndroid Build Coastguard Worker IsUncleanSystemSession(last_live_timestamp)) {
190*6777b538SAndroid Build Coastguard Worker IncrementPrefValue(prefs::kStabilitySystemCrashCount);
191*6777b538SAndroid Build Coastguard Worker }
192*6777b538SAndroid Build Coastguard Worker }
193*6777b538SAndroid Build Coastguard Worker #endif
194*6777b538SAndroid Build Coastguard Worker
IncrementPrefValue(const char * path)195*6777b538SAndroid Build Coastguard Worker void StabilityMetricsProvider::IncrementPrefValue(const char* path) {
196*6777b538SAndroid Build Coastguard Worker int value = local_state_->GetInteger(path);
197*6777b538SAndroid Build Coastguard Worker local_state_->SetInteger(path, value + 1);
198*6777b538SAndroid Build Coastguard Worker }
199*6777b538SAndroid Build Coastguard Worker
GetAndClearPrefValue(const char * path,int * value)200*6777b538SAndroid Build Coastguard Worker int StabilityMetricsProvider::GetAndClearPrefValue(const char* path,
201*6777b538SAndroid Build Coastguard Worker int* value) {
202*6777b538SAndroid Build Coastguard Worker *value = local_state_->GetInteger(path);
203*6777b538SAndroid Build Coastguard Worker if (*value != 0)
204*6777b538SAndroid Build Coastguard Worker local_state_->SetInteger(path, 0);
205*6777b538SAndroid Build Coastguard Worker return *value;
206*6777b538SAndroid Build Coastguard Worker }
207*6777b538SAndroid Build Coastguard Worker
208*6777b538SAndroid Build Coastguard Worker } // namespace metrics
209