xref: /aosp_15_r20/external/cronet/components/metrics/stability_metrics_provider.cc (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
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