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