[email protected] | d6147bd | 2014-06-11 01:58:19 | [diff] [blame] | 1 | // Copyright 2014 The Chromium Authors. All rights reserved. |
license.bot | bf09a50 | 2008-08-24 00:55:55 | [diff] [blame] | 2 | // Use of this source code is governed by a BSD-style license that can be |
| 3 | // found in the LICENSE file. |
initial.commit | 09911bf | 2008-07-26 23:55:29 | [diff] [blame] | 4 | |
initial.commit | 09911bf | 2008-07-26 23:55:29 | [diff] [blame] | 5 | //------------------------------------------------------------------------------ |
| 6 | // Description of the life cycle of a instance of MetricsService. |
| 7 | // |
| 8 | // OVERVIEW |
| 9 | // |
[email protected] | e3eb0c4 | 2013-04-18 06:18:58 | [diff] [blame] | 10 | // A MetricsService instance is typically created at application startup. It is |
| 11 | // the central controller for the acquisition of log data, and the automatic |
initial.commit | 09911bf | 2008-07-26 23:55:29 | [diff] [blame] | 12 | // transmission of that log data to an external server. Its major job is to |
| 13 | // manage logs, grouping them for transmission, and transmitting them. As part |
| 14 | // of its grouping, MS finalizes logs by including some just-in-time gathered |
| 15 | // memory statistics, snapshotting the current stats of numerous histograms, |
[email protected] | e3eb0c4 | 2013-04-18 06:18:58 | [diff] [blame] | 16 | // closing the logs, translating to protocol buffer format, and compressing the |
| 17 | // results for transmission. Transmission includes submitting a compressed log |
| 18 | // as data in a URL-post, and retransmitting (or retaining at process |
| 19 | // termination) if the attempted transmission failed. Retention across process |
| 20 | // terminations is done using the the PrefServices facilities. The retained logs |
| 21 | // (the ones that never got transmitted) are compressed and base64-encoded |
| 22 | // before being persisted. |
initial.commit | 09911bf | 2008-07-26 23:55:29 | [diff] [blame] | 23 | // |
[email protected] | 281d288 | 2009-01-20 20:32:42 | [diff] [blame] | 24 | // Logs fall into one of two categories: "initial logs," and "ongoing logs." |
[email protected] | 80a8f31 | 2013-12-16 18:00:30 | [diff] [blame] | 25 | // There is at most one initial log sent for each complete run of Chrome (from |
| 26 | // startup, to browser shutdown). An initial log is generally transmitted some |
| 27 | // short time (1 minute?) after startup, and includes stats such as recent crash |
| 28 | // info, the number and types of plugins, etc. The external server's response |
| 29 | // to the initial log conceptually tells this MS if it should continue |
| 30 | // transmitting logs (during this session). The server response can actually be |
| 31 | // much more detailed, and always includes (at a minimum) how often additional |
| 32 | // ongoing logs should be sent. |
initial.commit | 09911bf | 2008-07-26 23:55:29 | [diff] [blame] | 33 | // |
| 34 | // After the above initial log, a series of ongoing logs will be transmitted. |
| 35 | // The first ongoing log actually begins to accumulate information stating when |
| 36 | // the MS was first constructed. Note that even though the initial log is |
| 37 | // commonly sent a full minute after startup, the initial log does not include |
| 38 | // much in the way of user stats. The most common interlog period (delay) |
[email protected] | 3a66815 | 2013-06-21 23:56:42 | [diff] [blame] | 39 | // is 30 minutes. That time period starts when the first user action causes a |
initial.commit | 09911bf | 2008-07-26 23:55:29 | [diff] [blame] | 40 | // logging event. This means that if there is no user action, there may be long |
[email protected] | 281d288 | 2009-01-20 20:32:42 | [diff] [blame] | 41 | // periods without any (ongoing) log transmissions. Ongoing logs typically |
initial.commit | 09911bf | 2008-07-26 23:55:29 | [diff] [blame] | 42 | // contain very detailed records of user activities (ex: opened tab, closed |
| 43 | // tab, fetched URL, maximized window, etc.) In addition, just before an |
| 44 | // ongoing log is closed out, a call is made to gather memory statistics. Those |
| 45 | // memory statistics are deposited into a histogram, and the log finalization |
| 46 | // code is then called. In the finalization, a call to a Histogram server |
| 47 | // acquires a list of all local histograms that have been flagged for upload |
[email protected] | 80a8f31 | 2013-12-16 18:00:30 | [diff] [blame] | 48 | // to the UMA server. The finalization also acquires the most recent number |
[email protected] | 281d288 | 2009-01-20 20:32:42 | [diff] [blame] | 49 | // of page loads, along with any counts of renderer or plugin crashes. |
initial.commit | 09911bf | 2008-07-26 23:55:29 | [diff] [blame] | 50 | // |
| 51 | // When the browser shuts down, there will typically be a fragment of an ongoing |
[email protected] | 80a8f31 | 2013-12-16 18:00:30 | [diff] [blame] | 52 | // log that has not yet been transmitted. At shutdown time, that fragment is |
| 53 | // closed (including snapshotting histograms), and persisted, for potential |
| 54 | // transmission during a future run of the product. |
initial.commit | 09911bf | 2008-07-26 23:55:29 | [diff] [blame] | 55 | // |
| 56 | // There are two slightly abnormal shutdown conditions. There is a |
| 57 | // "disconnected scenario," and a "really fast startup and shutdown" scenario. |
| 58 | // In the "never connected" situation, the user has (during the running of the |
| 59 | // process) never established an internet connection. As a result, attempts to |
| 60 | // transmit the initial log have failed, and a lot(?) of data has accumulated in |
| 61 | // the ongoing log (which didn't yet get closed, because there was never even a |
| 62 | // contemplation of sending it). There is also a kindred "lost connection" |
| 63 | // situation, where a loss of connection prevented an ongoing log from being |
| 64 | // transmitted, and a (still open) log was stuck accumulating a lot(?) of data, |
| 65 | // while the earlier log retried its transmission. In both of these |
| 66 | // disconnected situations, two logs need to be, and are, persistently stored |
| 67 | // for future transmission. |
| 68 | // |
| 69 | // The other unusual shutdown condition, termed "really fast startup and |
| 70 | // shutdown," involves the deliberate user termination of the process before |
| 71 | // the initial log is even formed or transmitted. In that situation, no logging |
| 72 | // is done, but the historical crash statistics remain (unlogged) for inclusion |
| 73 | // in a future run's initial log. (i.e., we don't lose crash stats). |
| 74 | // |
| 75 | // With the above overview, we can now describe the state machine's various |
[email protected] | 80a8f31 | 2013-12-16 18:00:30 | [diff] [blame] | 76 | // states, based on the State enum specified in the state_ member. Those states |
initial.commit | 09911bf | 2008-07-26 23:55:29 | [diff] [blame] | 77 | // are: |
| 78 | // |
Steven Holte | 2c294a3 | 2015-03-12 21:45:03 | [diff] [blame] | 79 | // INITIALIZED, // Constructor was called. |
| 80 | // INIT_TASK_SCHEDULED, // Waiting for deferred init tasks to finish. |
| 81 | // INIT_TASK_DONE, // Waiting for timer to send initial log. |
| 82 | // SENDING_LOGS, // Sending logs and creating new ones when we run out. |
initial.commit | 09911bf | 2008-07-26 23:55:29 | [diff] [blame] | 83 | // |
| 84 | // In more detail, we have: |
| 85 | // |
| 86 | // INITIALIZED, // Constructor was called. |
| 87 | // The MS has been constructed, but has taken no actions to compose the |
| 88 | // initial log. |
| 89 | // |
[email protected] | 80a8f31 | 2013-12-16 18:00:30 | [diff] [blame] | 90 | // INIT_TASK_SCHEDULED, // Waiting for deferred init tasks to finish. |
initial.commit | 09911bf | 2008-07-26 23:55:29 | [diff] [blame] | 91 | // Typically about 30 seconds after startup, a task is sent to a second thread |
[email protected] | 85ed9d4 | 2010-06-08 22:37:44 | [diff] [blame] | 92 | // (the file thread) to perform deferred (lower priority and slower) |
| 93 | // initialization steps such as getting the list of plugins. That task will |
| 94 | // (when complete) make an async callback (via a Task) to indicate the |
| 95 | // completion. |
initial.commit | 09911bf | 2008-07-26 23:55:29 | [diff] [blame] | 96 | // |
[email protected] | 85ed9d4 | 2010-06-08 22:37:44 | [diff] [blame] | 97 | // INIT_TASK_DONE, // Waiting for timer to send initial log. |
initial.commit | 09911bf | 2008-07-26 23:55:29 | [diff] [blame] | 98 | // The callback has arrived, and it is now possible for an initial log to be |
| 99 | // created. This callback typically arrives back less than one second after |
[email protected] | 85ed9d4 | 2010-06-08 22:37:44 | [diff] [blame] | 100 | // the deferred init task is dispatched. |
initial.commit | 09911bf | 2008-07-26 23:55:29 | [diff] [blame] | 101 | // |
Steven Holte | 2c294a3 | 2015-03-12 21:45:03 | [diff] [blame] | 102 | // SENDING_LOGS, // Sending logs an creating new ones when we run out. |
| 103 | // Logs from previous sessions have been loaded, and initial logs have been |
| 104 | // created (an optional stability log and the first metrics log). We will |
| 105 | // send all of these logs, and when run out, we will start cutting new logs |
| 106 | // to send. We will also cut a new log if we expect a shutdown. |
[email protected] | 80a8f31 | 2013-12-16 18:00:30 | [diff] [blame] | 107 | // |
Steven Holte | 2c294a3 | 2015-03-12 21:45:03 | [diff] [blame] | 108 | // The progression through the above states is simple, and sequential. |
| 109 | // States proceed from INITIAL to SENDING_LOGS, and remain in the latter until |
| 110 | // shutdown. |
initial.commit | 09911bf | 2008-07-26 23:55:29 | [diff] [blame] | 111 | // |
Steven Holte | 2c294a3 | 2015-03-12 21:45:03 | [diff] [blame] | 112 | // Also note that whenever we successfully send a log, we mirror the list |
[email protected] | cac267c | 2011-09-29 15:18:10 | [diff] [blame] | 113 | // of logs into the PrefService. This ensures that IF we crash, we won't start |
| 114 | // up and retransmit our old logs again. |
initial.commit | 09911bf | 2008-07-26 23:55:29 | [diff] [blame] | 115 | // |
| 116 | // Due to race conditions, it is always possible that a log file could be sent |
| 117 | // twice. For example, if a log file is sent, but not yet acknowledged by |
| 118 | // the external server, and the user shuts down, then a copy of the log may be |
| 119 | // saved for re-transmission. These duplicates could be filtered out server |
[email protected] | 281d288 | 2009-01-20 20:32:42 | [diff] [blame] | 120 | // side, but are not expected to be a significant problem. |
initial.commit | 09911bf | 2008-07-26 23:55:29 | [diff] [blame] | 121 | // |
| 122 | // |
| 123 | //------------------------------------------------------------------------------ |
| 124 | |
[email protected] | d6147bd | 2014-06-11 01:58:19 | [diff] [blame] | 125 | #include "components/metrics/metrics_service.h" |
[email protected] | 40bcc30 | 2009-03-02 20:50:39 | [diff] [blame] | 126 | |
avi | 2606292 | 2015-12-26 00:14:18 | [diff] [blame] | 127 | #include <stddef.h> |
dcheng | d99c42a | 2016-04-21 21:54:13 | [diff] [blame] | 128 | |
dcheng | 5160635 | 2015-12-26 21:16:23 | [diff] [blame] | 129 | #include <algorithm> |
| 130 | #include <utility> |
avi | 2606292 | 2015-12-26 00:14:18 | [diff] [blame] | 131 | |
[email protected] | 7f7f196 | 2011-04-20 15:58:16 | [diff] [blame] | 132 | #include "base/bind.h" |
| 133 | #include "base/callback.h" |
skyostil | b0daa01 | 2015-06-02 19:03:48 | [diff] [blame] | 134 | #include "base/location.h" |
[email protected] | acc2ce551 | 2014-05-22 18:29:13 | [diff] [blame] | 135 | #include "base/metrics/histogram_base.h" |
Ilya Sherman | 1edb6f18 | 2017-12-12 04:00:42 | [diff] [blame] | 136 | #include "base/metrics/histogram_functions.h" |
asvitkine | 454600f | 2015-06-16 16:34:50 | [diff] [blame] | 137 | #include "base/metrics/histogram_macros.h" |
[email protected] | acc2ce551 | 2014-05-22 18:29:13 | [diff] [blame] | 138 | #include "base/metrics/histogram_samples.h" |
bcwhite | 33d95806a | 2016-03-16 02:37:45 | [diff] [blame] | 139 | #include "base/metrics/persistent_histogram_allocator.h" |
[email protected] | 567d30e | 2012-07-13 21:48:29 | [diff] [blame] | 140 | #include "base/metrics/statistics_recorder.h" |
skyostil | b0daa01 | 2015-06-02 19:03:48 | [diff] [blame] | 141 | #include "base/single_thread_task_runner.h" |
Robert Kaplow | d45b620 | 2017-07-20 02:01:46 | [diff] [blame] | 142 | #include "base/strings/string_piece.h" |
Steven Holte | 971b059 | 2017-10-12 15:28:26 | [diff] [blame] | 143 | #include "base/threading/sequenced_task_runner_handle.h" |
[email protected] | 64b8652c | 2014-07-16 19:14:28 | [diff] [blame] | 144 | #include "base/time/time.h" |
avi | 2606292 | 2015-12-26 00:14:18 | [diff] [blame] | 145 | #include "build/build_config.h" |
holte | 1bf273c | 2017-02-23 00:22:28 | [diff] [blame] | 146 | #include "components/metrics/environment_recorder.h" |
Steven Holte | 5c6dd63 | 2017-07-19 23:25:49 | [diff] [blame] | 147 | #include "components/metrics/field_trials_provider.h" |
[email protected] | 91b1d91 | 2014-06-05 10:52:08 | [diff] [blame] | 148 | #include "components/metrics/metrics_log.h" |
[email protected] | 064107e | 2014-05-02 00:59:06 | [diff] [blame] | 149 | #include "components/metrics/metrics_log_manager.h" |
[email protected] | 0d5a61a8 | 2014-05-31 22:28:34 | [diff] [blame] | 150 | #include "components/metrics/metrics_log_uploader.h" |
[email protected] | 7f07db6 | 2014-05-15 01:12:45 | [diff] [blame] | 151 | #include "components/metrics/metrics_pref_names.h" |
holte | 6839585 | 2017-01-10 20:40:21 | [diff] [blame] | 152 | #include "components/metrics/metrics_rotation_scheduler.h" |
[email protected] | 7392942 | 2014-05-22 08:19:05 | [diff] [blame] | 153 | #include "components/metrics/metrics_service_client.h" |
[email protected] | 16a3091 | 2014-06-04 00:20:04 | [diff] [blame] | 154 | #include "components/metrics/metrics_state_manager.h" |
Steven Holte | d0429a70 | 2017-08-03 08:56:17 | [diff] [blame] | 155 | #include "components/metrics/persistent_system_profile.h" |
holte | 1bf273c | 2017-02-23 00:22:28 | [diff] [blame] | 156 | #include "components/metrics/stability_metrics_provider.h" |
holte | 567a16f2 | 2017-01-06 01:53:45 | [diff] [blame] | 157 | #include "components/metrics/url_constants.h" |
brettw | f00b9b4 | 2016-02-01 22:11:38 | [diff] [blame] | 158 | #include "components/prefs/pref_registry_simple.h" |
| 159 | #include "components/prefs/pref_service.h" |
[email protected] | 50ae9f1 | 2013-08-29 18:03:22 | [diff] [blame] | 160 | #include "components/variations/entropy_provider.h" |
initial.commit | 09911bf | 2008-07-26 23:55:29 | [diff] [blame] | 161 | |
asvitkine | cbd42073 | 2014-08-26 22:15:40 | [diff] [blame] | 162 | namespace metrics { |
[email protected] | e1acf6f | 2008-10-27 20:43:33 | [diff] [blame] | 163 | |
holte | 6e36a3d | 2017-02-02 22:41:10 | [diff] [blame] | 164 | namespace { |
| 165 | |
[email protected] | 7f7f196 | 2011-04-20 15:58:16 | [diff] [blame] | 166 | // The delay, in seconds, after starting recording before doing expensive |
| 167 | // initialization work. |
[email protected] | 12180f8 | 2012-10-10 21:13:30 | [diff] [blame] | 168 | #if defined(OS_ANDROID) || defined(OS_IOS) |
| 169 | // On mobile devices, a significant portion of sessions last less than a minute. |
| 170 | // Use a shorter timer on these platforms to avoid losing data. |
| 171 | // TODO(dfalcantara): To avoid delaying startup, tighten up initialization so |
| 172 | // that it occurs after the user gets their initial page. |
| 173 | const int kInitializationDelaySeconds = 5; |
| 174 | #else |
[email protected] | fe58acc2 | 2012-02-29 01:29:58 | [diff] [blame] | 175 | const int kInitializationDelaySeconds = 30; |
[email protected] | 12180f8 | 2012-10-10 21:13:30 | [diff] [blame] | 176 | #endif |
[email protected] | 252873ef | 2008-08-04 21:59:45 | [diff] [blame] | 177 | |
Sigurdur Asgeirsson | 5795250 | 2018-01-29 16:15:08 | [diff] [blame] | 178 | // The browser last live timestamp is updated every 15 minutes. |
| 179 | const int kUpdateAliveTimestampSeconds = 15 * 60; |
| 180 | |
hashimoto | a5c00e28d | 2015-03-27 06:28:37 | [diff] [blame] | 181 | #if defined(OS_ANDROID) || defined(OS_IOS) |
erikwright | 65b58df | 2014-09-12 00:05:28 | [diff] [blame] | 182 | void MarkAppCleanShutdownAndCommit(CleanExitBeacon* clean_exit_beacon, |
| 183 | PrefService* local_state) { |
| 184 | clean_exit_beacon->WriteBeaconValue(true); |
[email protected] | 84c384e | 2013-03-01 23:20:19 | [diff] [blame] | 185 | // Start writing right away (write happens on a different thread). |
[email protected] | 24f81ca | 2014-05-26 15:59:34 | [diff] [blame] | 186 | local_state->CommitPendingWrite(); |
[email protected] | 84c384e | 2013-03-01 23:20:19 | [diff] [blame] | 187 | } |
hashimoto | a5c00e28d | 2015-03-27 06:28:37 | [diff] [blame] | 188 | #endif // defined(OS_ANDROID) || defined(OS_IOS) |
[email protected] | 84c384e | 2013-03-01 23:20:19 | [diff] [blame] | 189 | |
[email protected] | 20f999b5 | 2012-08-24 22:32:59 | [diff] [blame] | 190 | } // namespace |
initial.commit | 09911bf | 2008-07-26 23:55:29 | [diff] [blame] | 191 | |
[email protected] | c0c55e9 | 2011-09-10 18:47:30 | [diff] [blame] | 192 | // static |
| 193 | MetricsService::ShutdownCleanliness MetricsService::clean_shutdown_status_ = |
| 194 | MetricsService::CLEANLY_SHUTDOWN; |
| 195 | |
initial.commit | 09911bf | 2008-07-26 23:55:29 | [diff] [blame] | 196 | // static |
[email protected] | b1de2c7 | 2013-02-06 02:45:47 | [diff] [blame] | 197 | void MetricsService::RegisterPrefs(PrefRegistrySimple* registry) { |
holte | 1bf273c | 2017-02-23 00:22:28 | [diff] [blame] | 198 | CleanExitBeacon::RegisterPrefs(registry); |
asvitkine | a63d19e | 2014-10-24 16:19:39 | [diff] [blame] | 199 | MetricsStateManager::RegisterPrefs(registry); |
[email protected] | 91b1d91 | 2014-06-05 10:52:08 | [diff] [blame] | 200 | MetricsLog::RegisterPrefs(registry); |
holte | 1bf273c | 2017-02-23 00:22:28 | [diff] [blame] | 201 | StabilityMetricsProvider::RegisterPrefs(registry); |
holte | 77d815b | 2017-03-27 21:27:37 | [diff] [blame] | 202 | MetricsReportingService::RegisterPrefs(registry); |
[email protected] | 3907664 | 2014-05-05 20:32:55 | [diff] [blame] | 203 | |
asvitkine | a63d19e | 2014-10-24 16:19:39 | [diff] [blame] | 204 | registry->RegisterIntegerPref(prefs::kMetricsSessionID, -1); |
[email protected] | 0f2f779 | 2013-11-28 16:09:14 | [diff] [blame] | 205 | |
asvitkine | a63d19e | 2014-10-24 16:19:39 | [diff] [blame] | 206 | registry->RegisterInt64Pref(prefs::kUninstallLaunchCount, 0); |
| 207 | registry->RegisterInt64Pref(prefs::kUninstallMetricsUptimeSec, 0); |
initial.commit | 09911bf | 2008-07-26 23:55:29 | [diff] [blame] | 208 | } |
| 209 | |
asvitkine | a63d19e | 2014-10-24 16:19:39 | [diff] [blame] | 210 | MetricsService::MetricsService(MetricsStateManager* state_manager, |
| 211 | MetricsServiceClient* client, |
[email protected] | 24f81ca | 2014-05-26 15:59:34 | [diff] [blame] | 212 | PrefService* local_state) |
holte | a3b2411 | 2017-03-14 02:08:24 | [diff] [blame] | 213 | : reporting_service_(client, local_state), |
[email protected] | acc2ce551 | 2014-05-22 18:29:13 | [diff] [blame] | 214 | histogram_snapshot_manager_(this), |
[email protected] | 7f07db6 | 2014-05-15 01:12:45 | [diff] [blame] | 215 | state_manager_(state_manager), |
[email protected] | 728de07 | 2014-05-21 09:20:32 | [diff] [blame] | 216 | client_(client), |
[email protected] | 24f81ca | 2014-05-26 15:59:34 | [diff] [blame] | 217 | local_state_(local_state), |
wittman | 622851e | 2015-07-31 18:13:40 | [diff] [blame] | 218 | recording_state_(UNSET), |
[email protected] | 410938e0 | 2012-10-24 16:33:59 | [diff] [blame] | 219 | test_mode_active_(false), |
[email protected] | d01b873 | 2008-10-16 02:18:07 | [diff] [blame] | 220 | state_(INITIALIZED), |
[email protected] | d01b873 | 2008-10-16 02:18:07 | [diff] [blame] | 221 | idle_since_last_transmission_(false), |
Jeremy Roman | 5c341f6d | 2019-07-15 15:56:10 | [diff] [blame] | 222 | session_id_(-1) { |
Steven Holte | 971b059 | 2017-10-12 15:28:26 | [diff] [blame] | 223 | DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); |
[email protected] | 3907664 | 2014-05-05 20:32:55 | [diff] [blame] | 224 | DCHECK(state_manager_); |
[email protected] | 728de07 | 2014-05-21 09:20:32 | [diff] [blame] | 225 | DCHECK(client_); |
[email protected] | 24f81ca | 2014-05-26 15:59:34 | [diff] [blame] | 226 | DCHECK(local_state_); |
[email protected] | 64b8652c | 2014-07-16 19:14:28 | [diff] [blame] | 227 | |
Steven Holte | 5c6dd63 | 2017-07-19 23:25:49 | [diff] [blame] | 228 | RegisterMetricsProvider( |
Gyuyoung Kim | 6afb508 | 2018-01-19 13:35:57 | [diff] [blame] | 229 | std::make_unique<StabilityMetricsProvider>(local_state_)); |
Steven Holte | 5c6dd63 | 2017-07-19 23:25:49 | [diff] [blame] | 230 | |
Steven Holte | d0429a70 | 2017-08-03 08:56:17 | [diff] [blame] | 231 | RegisterMetricsProvider(state_manager_->GetProvider()); |
| 232 | |
Gyuyoung Kim | 6afb508 | 2018-01-19 13:35:57 | [diff] [blame] | 233 | RegisterMetricsProvider(std::make_unique<variations::FieldTrialsProvider>( |
Robert Kaplow | d45b620 | 2017-07-20 02:01:46 | [diff] [blame] | 234 | &synthetic_trial_registry_, base::StringPiece())); |
initial.commit | 09911bf | 2008-07-26 23:55:29 | [diff] [blame] | 235 | } |
| 236 | |
| 237 | MetricsService::~MetricsService() { |
[email protected] | 410938e0 | 2012-10-24 16:33:59 | [diff] [blame] | 238 | DisableRecording(); |
initial.commit | 09911bf | 2008-07-26 23:55:29 | [diff] [blame] | 239 | } |
| 240 | |
[email protected] | 3907664 | 2014-05-05 20:32:55 | [diff] [blame] | 241 | void MetricsService::InitializeMetricsRecordingState() { |
holte | a3b2411 | 2017-03-14 02:08:24 | [diff] [blame] | 242 | reporting_service_.Initialize(); |
[email protected] | 3907664 | 2014-05-05 20:32:55 | [diff] [blame] | 243 | InitializeMetricsState(); |
[email protected] | 80a8f31 | 2013-12-16 18:00:30 | [diff] [blame] | 244 | |
gayane | d52ca40 | 2015-02-23 21:23:06 | [diff] [blame] | 245 | base::Closure upload_callback = |
| 246 | base::Bind(&MetricsService::StartScheduledUpload, |
| 247 | self_ptr_factory_.GetWeakPtr()); |
holte | 6839585 | 2017-01-10 20:40:21 | [diff] [blame] | 248 | |
holte | c1b9731 | 2017-02-24 21:37:10 | [diff] [blame] | 249 | rotation_scheduler_.reset(new MetricsRotationScheduler( |
| 250 | upload_callback, |
| 251 | // MetricsServiceClient outlives MetricsService, and |
| 252 | // MetricsRotationScheduler is tied to the lifetime of |this|. |
Nate Fischer | 5764f2f | 2019-09-13 23:00:02 | [diff] [blame] | 253 | base::Bind(&MetricsServiceClient::GetUploadInterval, |
Nate Fischer | e823643 | 2019-10-25 02:36:32 | [diff] [blame] | 254 | base::Unretained(client_)), |
| 255 | client_->ShouldStartUpFastForTesting())); |
dhsharp | b0073a2 | 2016-02-18 21:54:09 | [diff] [blame] | 256 | |
Ran Ji | b5891ad | 2018-03-21 23:12:16 | [diff] [blame] | 257 | // Init() has to be called after LogCrash() in order for LogCrash() to work. |
Steven Holte | c35411dc | 2017-07-28 04:22:14 | [diff] [blame] | 258 | delegating_provider_.Init(); |
[email protected] | 80a8f31 | 2013-12-16 18:00:30 | [diff] [blame] | 259 | } |
| 260 | |
[email protected] | d01b873 | 2008-10-16 02:18:07 | [diff] [blame] | 261 | void MetricsService::Start() { |
[email protected] | b1c8dc0 | 2011-04-13 18:32:04 | [diff] [blame] | 262 | HandleIdleSinceLastTransmission(false); |
[email protected] | 410938e0 | 2012-10-24 16:33:59 | [diff] [blame] | 263 | EnableRecording(); |
| 264 | EnableReporting(); |
[email protected] | d01b873 | 2008-10-16 02:18:07 | [diff] [blame] | 265 | } |
| 266 | |
[email protected] | 410938e0 | 2012-10-24 16:33:59 | [diff] [blame] | 267 | void MetricsService::StartRecordingForTests() { |
| 268 | test_mode_active_ = true; |
| 269 | EnableRecording(); |
| 270 | DisableReporting(); |
[email protected] | d01b873 | 2008-10-16 02:18:07 | [diff] [blame] | 271 | } |
| 272 | |
Sigurdur Asgeirsson | 5795250 | 2018-01-29 16:15:08 | [diff] [blame] | 273 | void MetricsService::StartUpdatingLastLiveTimestamp() { |
| 274 | base::SequencedTaskRunnerHandle::Get()->PostDelayedTask( |
| 275 | FROM_HERE, |
| 276 | base::BindOnce(&MetricsService::UpdateLastLiveTimestampTask, |
| 277 | self_ptr_factory_.GetWeakPtr()), |
| 278 | base::TimeDelta::FromSeconds(kUpdateAliveTimestampSeconds)); |
| 279 | } |
| 280 | |
[email protected] | d01b873 | 2008-10-16 02:18:07 | [diff] [blame] | 281 | void MetricsService::Stop() { |
[email protected] | b1c8dc0 | 2011-04-13 18:32:04 | [diff] [blame] | 282 | HandleIdleSinceLastTransmission(false); |
[email protected] | 410938e0 | 2012-10-24 16:33:59 | [diff] [blame] | 283 | DisableReporting(); |
| 284 | DisableRecording(); |
| 285 | } |
| 286 | |
| 287 | void MetricsService::EnableReporting() { |
holte | a3b2411 | 2017-03-14 02:08:24 | [diff] [blame] | 288 | if (reporting_service_.reporting_active()) |
[email protected] | 410938e0 | 2012-10-24 16:33:59 | [diff] [blame] | 289 | return; |
holte | a3b2411 | 2017-03-14 02:08:24 | [diff] [blame] | 290 | reporting_service_.EnableReporting(); |
[email protected] | 410938e0 | 2012-10-24 16:33:59 | [diff] [blame] | 291 | StartSchedulerIfNecessary(); |
| 292 | } |
| 293 | |
| 294 | void MetricsService::DisableReporting() { |
holte | a3b2411 | 2017-03-14 02:08:24 | [diff] [blame] | 295 | reporting_service_.DisableReporting(); |
[email protected] | d01b873 | 2008-10-16 02:18:07 | [diff] [blame] | 296 | } |
| 297 | |
[email protected] | edafd4c | 2011-05-10 17:18:53 | [diff] [blame] | 298 | std::string MetricsService::GetClientId() { |
[email protected] | 3907664 | 2014-05-05 20:32:55 | [diff] [blame] | 299 | return state_manager_->client_id(); |
[email protected] | edafd4c | 2011-05-10 17:18:53 | [diff] [blame] | 300 | } |
| 301 | |
avi | 2606292 | 2015-12-26 00:14:18 | [diff] [blame] | 302 | int64_t MetricsService::GetInstallDate() { |
Steven Holte | 8e9db0ca | 2017-08-11 01:20:08 | [diff] [blame] | 303 | return state_manager_->GetInstallDate(); |
olivierrobin | c3dfc5b | 2015-04-07 19:12:00 | [diff] [blame] | 304 | } |
| 305 | |
droger | b8d286e4 | 2015-07-08 09:07:09 | [diff] [blame] | 306 | bool MetricsService::WasLastShutdownClean() const { |
Ilya Sherman | 6c6c833 | 2017-07-11 22:39:22 | [diff] [blame] | 307 | return state_manager_->clean_exit_beacon()->exited_cleanly(); |
droger | b8d286e4 | 2015-07-08 09:07:09 | [diff] [blame] | 308 | } |
| 309 | |
[email protected] | 410938e0 | 2012-10-24 16:33:59 | [diff] [blame] | 310 | void MetricsService::EnableRecording() { |
Steven Holte | 971b059 | 2017-10-12 15:28:26 | [diff] [blame] | 311 | DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); |
initial.commit | 09911bf | 2008-07-26 23:55:29 | [diff] [blame] | 312 | |
wittman | 622851e | 2015-07-31 18:13:40 | [diff] [blame] | 313 | if (recording_state_ == ACTIVE) |
initial.commit | 09911bf | 2008-07-26 23:55:29 | [diff] [blame] | 314 | return; |
wittman | 622851e | 2015-07-31 18:13:40 | [diff] [blame] | 315 | recording_state_ = ACTIVE; |
initial.commit | 09911bf | 2008-07-26 23:55:29 | [diff] [blame] | 316 | |
[email protected] | 3907664 | 2014-05-05 20:32:55 | [diff] [blame] | 317 | state_manager_->ForceClientIdCreation(); |
[email protected] | 9d1b015 | 2014-07-09 18:53:22 | [diff] [blame] | 318 | client_->SetMetricsClientId(state_manager_->client_id()); |
Steven Holte | d0429a70 | 2017-08-03 08:56:17 | [diff] [blame] | 319 | |
[email protected] | 410938e0 | 2012-10-24 16:33:59 | [diff] [blame] | 320 | if (!log_manager_.current_log()) |
| 321 | OpenNewLog(); |
[email protected] | 005ef3e | 2009-05-22 20:55:46 | [diff] [blame] | 322 | |
Steven Holte | c35411dc | 2017-07-28 04:22:14 | [diff] [blame] | 323 | delegating_provider_.OnRecordingEnabled(); |
[email protected] | 85791b0b | 2014-05-20 15:18:58 | [diff] [blame] | 324 | |
Alexei Svitkine | 70c9502 | 2019-08-21 18:13:24 | [diff] [blame] | 325 | // Fill in the system profile in the log and persist it (to prefs, .pma and |
| 326 | // crashpad). This includes running the providers so that information like |
| 327 | // field trials and hardware info is provided. If Chrome crashes before this |
| 328 | // log is completed, the .pma file will have this system profile. |
| 329 | RecordCurrentEnvironment(log_manager_.current_log(), /*complete=*/false); |
| 330 | |
[email protected] | e6e30ac | 2014-01-13 21:24:39 | [diff] [blame] | 331 | base::RemoveActionCallback(action_callback_); |
[email protected] | dd98f39 | 2013-02-04 13:03:22 | [diff] [blame] | 332 | action_callback_ = base::Bind(&MetricsService::OnUserAction, |
| 333 | base::Unretained(this)); |
[email protected] | e6e30ac | 2014-01-13 21:24:39 | [diff] [blame] | 334 | base::AddActionCallback(action_callback_); |
[email protected] | 410938e0 | 2012-10-24 16:33:59 | [diff] [blame] | 335 | } |
| 336 | |
| 337 | void MetricsService::DisableRecording() { |
Steven Holte | 971b059 | 2017-10-12 15:28:26 | [diff] [blame] | 338 | DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); |
[email protected] | 410938e0 | 2012-10-24 16:33:59 | [diff] [blame] | 339 | |
wittman | 622851e | 2015-07-31 18:13:40 | [diff] [blame] | 340 | if (recording_state_ == INACTIVE) |
[email protected] | 410938e0 | 2012-10-24 16:33:59 | [diff] [blame] | 341 | return; |
wittman | 622851e | 2015-07-31 18:13:40 | [diff] [blame] | 342 | recording_state_ = INACTIVE; |
[email protected] | 410938e0 | 2012-10-24 16:33:59 | [diff] [blame] | 343 | |
[email protected] | e6e30ac | 2014-01-13 21:24:39 | [diff] [blame] | 344 | base::RemoveActionCallback(action_callback_); |
[email protected] | 85791b0b | 2014-05-20 15:18:58 | [diff] [blame] | 345 | |
Steven Holte | c35411dc | 2017-07-28 04:22:14 | [diff] [blame] | 346 | delegating_provider_.OnRecordingDisabled(); |
[email protected] | 85791b0b | 2014-05-20 15:18:58 | [diff] [blame] | 347 | |
[email protected] | 410938e0 | 2012-10-24 16:33:59 | [diff] [blame] | 348 | PushPendingLogsToPersistentStorage(); |
initial.commit | 09911bf | 2008-07-26 23:55:29 | [diff] [blame] | 349 | } |
| 350 | |
[email protected] | d01b873 | 2008-10-16 02:18:07 | [diff] [blame] | 351 | bool MetricsService::recording_active() const { |
Steven Holte | 971b059 | 2017-10-12 15:28:26 | [diff] [blame] | 352 | DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); |
wittman | 622851e | 2015-07-31 18:13:40 | [diff] [blame] | 353 | return recording_state_ == ACTIVE; |
initial.commit | 09911bf | 2008-07-26 23:55:29 | [diff] [blame] | 354 | } |
| 355 | |
[email protected] | d01b873 | 2008-10-16 02:18:07 | [diff] [blame] | 356 | bool MetricsService::reporting_active() const { |
Steven Holte | 971b059 | 2017-10-12 15:28:26 | [diff] [blame] | 357 | DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); |
holte | a3b2411 | 2017-03-14 02:08:24 | [diff] [blame] | 358 | return reporting_service_.reporting_active(); |
| 359 | } |
| 360 | |
| 361 | bool MetricsService::has_unsent_logs() const { |
| 362 | return reporting_service_.metrics_log_store()->has_unsent_logs(); |
initial.commit | 09911bf | 2008-07-26 23:55:29 | [diff] [blame] | 363 | } |
| 364 | |
[email protected] | acc2ce551 | 2014-05-22 18:29:13 | [diff] [blame] | 365 | void MetricsService::RecordDelta(const base::HistogramBase& histogram, |
| 366 | const base::HistogramSamples& snapshot) { |
| 367 | log_manager_.current_log()->RecordHistogramDelta(histogram.histogram_name(), |
| 368 | snapshot); |
| 369 | } |
| 370 | |
[email protected] | d01b873 | 2008-10-16 02:18:07 | [diff] [blame] | 371 | void MetricsService::HandleIdleSinceLastTransmission(bool in_idle) { |
| 372 | // If there wasn't a lot of action, maybe the computer was asleep, in which |
| 373 | // case, the log transmissions should have stopped. Here we start them up |
| 374 | // again. |
[email protected] | cac7884 | 2008-11-27 01:02:20 | [diff] [blame] | 375 | if (!in_idle && idle_since_last_transmission_) |
[email protected] | 7f7f196 | 2011-04-20 15:58:16 | [diff] [blame] | 376 | StartSchedulerIfNecessary(); |
[email protected] | cac7884 | 2008-11-27 01:02:20 | [diff] [blame] | 377 | idle_since_last_transmission_ = in_idle; |
initial.commit | 09911bf | 2008-07-26 23:55:29 | [diff] [blame] | 378 | } |
| 379 | |
[email protected] | d7ea39e | 2014-05-22 03:59:18 | [diff] [blame] | 380 | void MetricsService::OnApplicationNotIdle() { |
wittman | 622851e | 2015-07-31 18:13:40 | [diff] [blame] | 381 | if (recording_state_ == ACTIVE) |
[email protected] | d7ea39e | 2014-05-22 03:59:18 | [diff] [blame] | 382 | HandleIdleSinceLastTransmission(false); |
| 383 | } |
| 384 | |
initial.commit | 09911bf | 2008-07-26 23:55:29 | [diff] [blame] | 385 | void MetricsService::RecordStartOfSessionEnd() { |
holte | 6d34116 | 2016-12-19 21:42:42 | [diff] [blame] | 386 | LogCleanShutdown(false); |
initial.commit | 09911bf | 2008-07-26 23:55:29 | [diff] [blame] | 387 | } |
| 388 | |
| 389 | void MetricsService::RecordCompletedSessionEnd() { |
holte | 6d34116 | 2016-12-19 21:42:42 | [diff] [blame] | 390 | LogCleanShutdown(true); |
initial.commit | 09911bf | 2008-07-26 23:55:29 | [diff] [blame] | 391 | } |
| 392 | |
[email protected] | 410938e0 | 2012-10-24 16:33:59 | [diff] [blame] | 393 | #if defined(OS_ANDROID) || defined(OS_IOS) |
Dan Harrington | 1d9c110 | 2019-05-09 17:21:12 | [diff] [blame] | 394 | void MetricsService::OnAppEnterBackground(bool keep_recording_in_background) { |
| 395 | if (!keep_recording_in_background) { |
| 396 | rotation_scheduler_->Stop(); |
| 397 | reporting_service_.Stop(); |
| 398 | } |
[email protected] | 117fbdf2 | 2012-06-26 18:36:39 | [diff] [blame] | 399 | |
Ilya Sherman | 6c6c833 | 2017-07-11 22:39:22 | [diff] [blame] | 400 | MarkAppCleanShutdownAndCommit(state_manager_->clean_exit_beacon(), |
| 401 | local_state_); |
[email protected] | 117fbdf2 | 2012-06-26 18:36:39 | [diff] [blame] | 402 | |
bmcquade | 6a49bed | 2016-07-27 19:25:56 | [diff] [blame] | 403 | // Give providers a chance to persist histograms as part of being |
| 404 | // backgrounded. |
Steven Holte | c35411dc | 2017-07-28 04:22:14 | [diff] [blame] | 405 | delegating_provider_.OnAppEnterBackground(); |
bmcquade | 6a49bed | 2016-07-27 19:25:56 | [diff] [blame] | 406 | |
[email protected] | 117fbdf2 | 2012-06-26 18:36:39 | [diff] [blame] | 407 | // At this point, there's no way of knowing when the process will be |
| 408 | // killed, so this has to be treated similar to a shutdown, closing and |
| 409 | // persisting all logs. Unlinke a shutdown, the state is primed to be ready |
| 410 | // to continue logging and uploading if the process does return. |
Steven Holte | 2c294a3 | 2015-03-12 21:45:03 | [diff] [blame] | 411 | if (recording_active() && state_ >= SENDING_LOGS) { |
[email protected] | 117fbdf2 | 2012-06-26 18:36:39 | [diff] [blame] | 412 | PushPendingLogsToPersistentStorage(); |
[email protected] | 410938e0 | 2012-10-24 16:33:59 | [diff] [blame] | 413 | // Persisting logs closes the current log, so start recording a new log |
| 414 | // immediately to capture any background work that might be done before the |
| 415 | // process is killed. |
| 416 | OpenNewLog(); |
[email protected] | 117fbdf2 | 2012-06-26 18:36:39 | [diff] [blame] | 417 | } |
[email protected] | 117fbdf2 | 2012-06-26 18:36:39 | [diff] [blame] | 418 | } |
| 419 | |
Dan Harrington | 5b7dfc1 | 2019-08-21 18:14:30 | [diff] [blame] | 420 | void MetricsService::OnAppEnterForeground(bool force_open_new_log) { |
Ilya Sherman | 6c6c833 | 2017-07-11 22:39:22 | [diff] [blame] | 421 | state_manager_->clean_exit_beacon()->WriteBeaconValue(false); |
[email protected] | 117fbdf2 | 2012-06-26 18:36:39 | [diff] [blame] | 422 | StartSchedulerIfNecessary(); |
Dan Harrington | 5b7dfc1 | 2019-08-21 18:14:30 | [diff] [blame] | 423 | |
| 424 | if (force_open_new_log && recording_active() && state_ >= SENDING_LOGS) { |
| 425 | // Because state_ >= SENDING_LOGS, PushPendingLogsToPersistentStorage() |
| 426 | // will close the log, allowing a new log to be opened. |
| 427 | PushPendingLogsToPersistentStorage(); |
| 428 | OpenNewLog(); |
| 429 | } |
[email protected] | 117fbdf2 | 2012-06-26 18:36:39 | [diff] [blame] | 430 | } |
Dan Harrington | 5b7dfc1 | 2019-08-21 18:14:30 | [diff] [blame] | 431 | |
[email protected] | 84c384e | 2013-03-01 23:20:19 | [diff] [blame] | 432 | #else |
erikwright | cc98a7e0 | 2014-09-09 22:05:12 | [diff] [blame] | 433 | void MetricsService::LogNeedForCleanShutdown() { |
Ilya Sherman | 6c6c833 | 2017-07-11 22:39:22 | [diff] [blame] | 434 | state_manager_->clean_exit_beacon()->WriteBeaconValue(false); |
[email protected] | 84c384e | 2013-03-01 23:20:19 | [diff] [blame] | 435 | // Redundant setting to be sure we call for a clean shutdown. |
| 436 | clean_shutdown_status_ = NEED_TO_SHUTDOWN; |
| 437 | } |
| 438 | #endif // defined(OS_ANDROID) || defined(OS_IOS) |
[email protected] | 117fbdf2 | 2012-06-26 18:36:39 | [diff] [blame] | 439 | |
[email protected] | 7f7f196 | 2011-04-20 15:58:16 | [diff] [blame] | 440 | void MetricsService::RecordBreakpadRegistration(bool success) { |
holte | 1bf273c | 2017-02-23 00:22:28 | [diff] [blame] | 441 | StabilityMetricsProvider(local_state_).RecordBreakpadRegistration(success); |
[email protected] | e73c0197 | 2008-08-13 00:18:24 | [diff] [blame] | 442 | } |
| 443 | |
| 444 | void MetricsService::RecordBreakpadHasDebugger(bool has_debugger) { |
holte | 1bf273c | 2017-02-23 00:22:28 | [diff] [blame] | 445 | StabilityMetricsProvider(local_state_) |
| 446 | .RecordBreakpadHasDebugger(has_debugger); |
[email protected] | e73c0197 | 2008-08-13 00:18:24 | [diff] [blame] | 447 | } |
| 448 | |
yiyaoliu | 14ef3ead | 2014-11-19 02:36:50 | [diff] [blame] | 449 | void MetricsService::ClearSavedStabilityMetrics() { |
Steven Holte | c35411dc | 2017-07-28 04:22:14 | [diff] [blame] | 450 | delegating_provider_.ClearSavedStabilityMetrics(); |
yiyaoliu | 14ef3ead | 2014-11-19 02:36:50 | [diff] [blame] | 451 | } |
| 452 | |
olivierrobin | c3dfc5b | 2015-04-07 19:12:00 | [diff] [blame] | 453 | void MetricsService::PushExternalLog(const std::string& log) { |
holte | a3b2411 | 2017-03-14 02:08:24 | [diff] [blame] | 454 | log_store()->StoreLog(log, MetricsLog::ONGOING_LOG); |
olivierrobin | c3dfc5b | 2015-04-07 19:12:00 | [diff] [blame] | 455 | } |
| 456 | |
initial.commit | 09911bf | 2008-07-26 23:55:29 | [diff] [blame] | 457 | //------------------------------------------------------------------------------ |
| 458 | // private methods |
| 459 | //------------------------------------------------------------------------------ |
| 460 | |
| 461 | |
| 462 | //------------------------------------------------------------------------------ |
| 463 | // Initialization methods |
| 464 | |
[email protected] | 3907664 | 2014-05-05 20:32:55 | [diff] [blame] | 465 | void MetricsService::InitializeMetricsState() { |
avi | 2606292 | 2015-12-26 00:14:18 | [diff] [blame] | 466 | const int64_t buildtime = MetricsLog::GetBuildTime(); |
asvitkine | ff3e2a6 | 2014-09-18 22:01:49 | [diff] [blame] | 467 | const std::string version = client_->GetVersionString(); |
holte | 57fcaed | 2017-01-23 22:14:31 | [diff] [blame] | 468 | |
asvitkine | ff3e2a6 | 2014-09-18 22:01:49 | [diff] [blame] | 469 | bool version_changed = false; |
holte | 1bf273c | 2017-02-23 00:22:28 | [diff] [blame] | 470 | EnvironmentRecorder recorder(local_state_); |
| 471 | int64_t previous_buildtime = recorder.GetLastBuildtime(); |
| 472 | std::string previous_version = recorder.GetLastVersion(); |
manzagop | ea99d195 | 2016-09-08 23:40:05 | [diff] [blame] | 473 | if (previous_buildtime != buildtime || previous_version != version) { |
holte | 1bf273c | 2017-02-23 00:22:28 | [diff] [blame] | 474 | recorder.SetBuildtimeAndVersion(buildtime, version); |
asvitkine | ff3e2a6 | 2014-09-18 22:01:49 | [diff] [blame] | 475 | version_changed = true; |
| 476 | } |
initial.commit | 09911bf | 2008-07-26 23:55:29 | [diff] [blame] | 477 | |
asvitkine | a63d19e | 2014-10-24 16:19:39 | [diff] [blame] | 478 | session_id_ = local_state_->GetInteger(prefs::kMetricsSessionID); |
erikwright | 65b58df | 2014-09-12 00:05:28 | [diff] [blame] | 479 | |
holte | 1bf273c | 2017-02-23 00:22:28 | [diff] [blame] | 480 | StabilityMetricsProvider provider(local_state_); |
Ilya Sherman | 6c6c833 | 2017-07-11 22:39:22 | [diff] [blame] | 481 | if (!state_manager_->clean_exit_beacon()->exited_cleanly()) { |
Sigurdur Asgeirsson | 8c67a59 | 2018-02-02 21:10:33 | [diff] [blame] | 482 | provider.LogCrash( |
| 483 | state_manager_->clean_exit_beacon()->browser_last_live_timestamp()); |
[email protected] | c0c55e9 | 2011-09-10 18:47:30 | [diff] [blame] | 484 | // Reset flag, and wait until we call LogNeedForCleanShutdown() before |
| 485 | // monitoring. |
Ilya Sherman | 6c6c833 | 2017-07-11 22:39:22 | [diff] [blame] | 486 | state_manager_->clean_exit_beacon()->WriteBeaconValue(true); |
siggi | c179dd06 | 2014-09-10 17:02:31 | [diff] [blame] | 487 | } |
[email protected] | 6a6d0d1 | 2013-10-28 15:58:19 | [diff] [blame] | 488 | |
Steven Holte | c35411dc | 2017-07-28 04:22:14 | [diff] [blame] | 489 | // HasPreviousSessionData is called first to ensure it is never bypassed. |
manzagop | 780bb8b | 2016-10-21 14:21:16 | [diff] [blame] | 490 | const bool is_initial_stability_log_required = |
Steven Holte | c35411dc | 2017-07-28 04:22:14 | [diff] [blame] | 491 | delegating_provider_.HasPreviousSessionData() || |
Ilya Sherman | 6c6c833 | 2017-07-11 22:39:22 | [diff] [blame] | 492 | !state_manager_->clean_exit_beacon()->exited_cleanly(); |
Steven Holte | 2c294a3 | 2015-03-12 21:45:03 | [diff] [blame] | 493 | bool has_initial_stability_log = false; |
manzagop | 780bb8b | 2016-10-21 14:21:16 | [diff] [blame] | 494 | if (is_initial_stability_log_required) { |
siggi | c179dd06 | 2014-09-10 17:02:31 | [diff] [blame] | 495 | // If the previous session didn't exit cleanly, or if any provider |
| 496 | // explicitly requests it, prepare an initial stability log - |
| 497 | // provided UMA is enabled. |
manzagop | ea99d195 | 2016-09-08 23:40:05 | [diff] [blame] | 498 | if (state_manager_->IsMetricsReportingEnabled()) { |
| 499 | has_initial_stability_log = PrepareInitialStabilityLog(previous_version); |
| 500 | if (!has_initial_stability_log) |
holte | 1bf273c | 2017-02-23 00:22:28 | [diff] [blame] | 501 | provider.LogStabilityLogDeferred(); |
manzagop | ea99d195 | 2016-09-08 23:40:05 | [diff] [blame] | 502 | } |
initial.commit | 09911bf | 2008-07-26 23:55:29 | [diff] [blame] | 503 | } |
[email protected] | 80a8f31 | 2013-12-16 18:00:30 | [diff] [blame] | 504 | |
manzagop | 780bb8b | 2016-10-21 14:21:16 | [diff] [blame] | 505 | // If the version changed, but no initial stability log was generated, clear |
| 506 | // the stability stats from the previous version (so that they don't get |
asvitkine | ff3e2a6 | 2014-09-18 22:01:49 | [diff] [blame] | 507 | // attributed to the current version). This could otherwise happen due to a |
| 508 | // number of different edge cases, such as if the last version crashed before |
| 509 | // it could save off a system profile or if UMA reporting is disabled (which |
| 510 | // normally results in stats being accumulated). |
manzagop | 780bb8b | 2016-10-21 14:21:16 | [diff] [blame] | 511 | if (version_changed && !has_initial_stability_log) { |
yiyaoliu | 14ef3ead | 2014-11-19 02:36:50 | [diff] [blame] | 512 | ClearSavedStabilityMetrics(); |
holte | 1bf273c | 2017-02-23 00:22:28 | [diff] [blame] | 513 | provider.LogStabilityDataDiscarded(); |
manzagop | ea99d195 | 2016-09-08 23:40:05 | [diff] [blame] | 514 | } |
asvitkine | ff3e2a6 | 2014-09-18 22:01:49 | [diff] [blame] | 515 | |
manzagop | 780bb8b | 2016-10-21 14:21:16 | [diff] [blame] | 516 | // If the version changed, the system profile is obsolete and needs to be |
| 517 | // cleared. This is to avoid the stability data misattribution that could |
| 518 | // occur if the current version crashed before saving its own system profile. |
| 519 | // Note however this clearing occurs only after preparing the initial |
| 520 | // stability log, an operation that requires the previous version's system |
| 521 | // profile. At this point, stability metrics pertaining to the previous |
| 522 | // version have been cleared. |
holte | 1bf273c | 2017-02-23 00:22:28 | [diff] [blame] | 523 | if (version_changed) |
| 524 | recorder.ClearEnvironmentFromPrefs(); |
manzagop | 780bb8b | 2016-10-21 14:21:16 | [diff] [blame] | 525 | |
[email protected] | 80a8f31 | 2013-12-16 18:00:30 | [diff] [blame] | 526 | // Update session ID. |
| 527 | ++session_id_; |
asvitkine | a63d19e | 2014-10-24 16:19:39 | [diff] [blame] | 528 | local_state_->SetInteger(prefs::kMetricsSessionID, session_id_); |
[email protected] | 80a8f31 | 2013-12-16 18:00:30 | [diff] [blame] | 529 | |
holte | 1bf273c | 2017-02-23 00:22:28 | [diff] [blame] | 530 | // Notify stability metrics providers about the launch. |
| 531 | provider.LogLaunch(); |
holte | 1bf273c | 2017-02-23 00:22:28 | [diff] [blame] | 532 | provider.CheckLastSessionEndCompleted(); |
initial.commit | 09911bf | 2008-07-26 23:55:29 | [diff] [blame] | 533 | |
[email protected] | 076961c | 2014-03-12 22:23:56 | [diff] [blame] | 534 | // Call GetUptimes() for the first time, thus allowing all later calls |
| 535 | // to record incremental uptimes accurately. |
| 536 | base::TimeDelta ignored_uptime_parameter; |
| 537 | base::TimeDelta startup_uptime; |
[email protected] | 24f81ca | 2014-05-26 15:59:34 | [diff] [blame] | 538 | GetUptimes(local_state_, &startup_uptime, &ignored_uptime_parameter); |
[email protected] | c68a2b9b | 2013-10-09 18:16:36 | [diff] [blame] | 539 | DCHECK_EQ(0, startup_uptime.InMicroseconds()); |
[email protected] | 0bb1a62 | 2009-03-04 03:22:32 | [diff] [blame] | 540 | |
| 541 | // Bookkeeping for the uninstall metrics. |
asvitkine | a63d19e | 2014-10-24 16:19:39 | [diff] [blame] | 542 | IncrementLongPrefsValue(prefs::kUninstallLaunchCount); |
initial.commit | 09911bf | 2008-07-26 23:55:29 | [diff] [blame] | 543 | } |
| 544 | |
[email protected] | dd98f39 | 2013-02-04 13:03:22 | [diff] [blame] | 545 | void MetricsService::OnUserAction(const std::string& action) { |
[email protected] | 4426d2d | 2014-04-09 12:33:00 | [diff] [blame] | 546 | log_manager_.current_log()->RecordUserAction(action); |
[email protected] | dd98f39 | 2013-02-04 13:03:22 | [diff] [blame] | 547 | HandleIdleSinceLastTransmission(false); |
| 548 | } |
| 549 | |
isherman | b670568 | 2015-08-29 00:01:00 | [diff] [blame] | 550 | void MetricsService::FinishedInitTask() { |
[email protected] | ed0fd00 | 2012-04-25 23:10:34 | [diff] [blame] | 551 | DCHECK_EQ(INIT_TASK_SCHEDULED, state_); |
[email protected] | c68a2b9b | 2013-10-09 18:16:36 | [diff] [blame] | 552 | state_ = INIT_TASK_DONE; |
[email protected] | 83d09f9 | 2014-06-03 14:58:26 | [diff] [blame] | 553 | |
| 554 | // Create the initial log. |
Zinovy Nis | 3c5a779e | 2018-05-11 07:09:50 | [diff] [blame] | 555 | if (!initial_metrics_log_) { |
[email protected] | 83d09f9 | 2014-06-03 14:58:26 | [diff] [blame] | 556 | initial_metrics_log_ = CreateLog(MetricsLog::ONGOING_LOG); |
Steven Holte | c35411dc | 2017-07-28 04:22:14 | [diff] [blame] | 557 | delegating_provider_.OnDidCreateMetricsLog(); |
[email protected] | 83d09f9 | 2014-06-03 14:58:26 | [diff] [blame] | 558 | } |
| 559 | |
holte | c1b9731 | 2017-02-24 21:37:10 | [diff] [blame] | 560 | rotation_scheduler_->InitTaskComplete(); |
[email protected] | c68a2b9b | 2013-10-09 18:16:36 | [diff] [blame] | 561 | } |
| 562 | |
[email protected] | 076961c | 2014-03-12 22:23:56 | [diff] [blame] | 563 | void MetricsService::GetUptimes(PrefService* pref, |
| 564 | base::TimeDelta* incremental_uptime, |
| 565 | base::TimeDelta* uptime) { |
[email protected] | c68a2b9b | 2013-10-09 18:16:36 | [diff] [blame] | 566 | base::TimeTicks now = base::TimeTicks::Now(); |
[email protected] | 076961c | 2014-03-12 22:23:56 | [diff] [blame] | 567 | // If this is the first call, init |first_updated_time_| and |
| 568 | // |last_updated_time_|. |
| 569 | if (last_updated_time_.is_null()) { |
| 570 | first_updated_time_ = now; |
[email protected] | c68a2b9b | 2013-10-09 18:16:36 | [diff] [blame] | 571 | last_updated_time_ = now; |
[email protected] | 076961c | 2014-03-12 22:23:56 | [diff] [blame] | 572 | } |
| 573 | *incremental_uptime = now - last_updated_time_; |
| 574 | *uptime = now - first_updated_time_; |
[email protected] | c68a2b9b | 2013-10-09 18:16:36 | [diff] [blame] | 575 | last_updated_time_ = now; |
| 576 | |
avi | 2606292 | 2015-12-26 00:14:18 | [diff] [blame] | 577 | const int64_t incremental_time_secs = incremental_uptime->InSeconds(); |
[email protected] | c68a2b9b | 2013-10-09 18:16:36 | [diff] [blame] | 578 | if (incremental_time_secs > 0) { |
avi | 2606292 | 2015-12-26 00:14:18 | [diff] [blame] | 579 | int64_t metrics_uptime = pref->GetInt64(prefs::kUninstallMetricsUptimeSec); |
[email protected] | c68a2b9b | 2013-10-09 18:16:36 | [diff] [blame] | 580 | metrics_uptime += incremental_time_secs; |
asvitkine | a63d19e | 2014-10-24 16:19:39 | [diff] [blame] | 581 | pref->SetInt64(prefs::kUninstallMetricsUptimeSec, metrics_uptime); |
[email protected] | c68a2b9b | 2013-10-09 18:16:36 | [diff] [blame] | 582 | } |
initial.commit | 09911bf | 2008-07-26 23:55:29 | [diff] [blame] | 583 | } |
| 584 | |
initial.commit | 09911bf | 2008-07-26 23:55:29 | [diff] [blame] | 585 | //------------------------------------------------------------------------------ |
| 586 | // Recording control methods |
| 587 | |
[email protected] | 410938e0 | 2012-10-24 16:33:59 | [diff] [blame] | 588 | void MetricsService::OpenNewLog() { |
| 589 | DCHECK(!log_manager_.current_log()); |
initial.commit | 09911bf | 2008-07-26 23:55:29 | [diff] [blame] | 590 | |
[email protected] | bfb77b5 | 2014-06-07 01:54:01 | [diff] [blame] | 591 | log_manager_.BeginLoggingWithLog(CreateLog(MetricsLog::ONGOING_LOG)); |
Steven Holte | c35411dc | 2017-07-28 04:22:14 | [diff] [blame] | 592 | delegating_provider_.OnDidCreateMetricsLog(); |
initial.commit | 09911bf | 2008-07-26 23:55:29 | [diff] [blame] | 593 | if (state_ == INITIALIZED) { |
| 594 | // We only need to schedule that run once. |
[email protected] | 85ed9d4 | 2010-06-08 22:37:44 | [diff] [blame] | 595 | state_ = INIT_TASK_SCHEDULED; |
initial.commit | 09911bf | 2008-07-26 23:55:29 | [diff] [blame] | 596 | |
Nate Fischer | e823643 | 2019-10-25 02:36:32 | [diff] [blame] | 597 | base::TimeDelta initialization_delay = base::TimeDelta::FromSeconds( |
| 598 | client_->ShouldStartUpFastForTesting() ? 0 |
| 599 | : kInitializationDelaySeconds); |
Steven Holte | 971b059 | 2017-10-12 15:28:26 | [diff] [blame] | 600 | base::SequencedTaskRunnerHandle::Get()->PostDelayedTask( |
| 601 | FROM_HERE, |
tzik | 2bcf8e4 | 2018-07-31 11:22:15 | [diff] [blame] | 602 | base::BindOnce(&MetricsService::StartInitTask, |
| 603 | self_ptr_factory_.GetWeakPtr()), |
Nate Fischer | e823643 | 2019-10-25 02:36:32 | [diff] [blame] | 604 | initialization_delay); |
bcwhite | 8e72aa59 | 2017-06-09 18:59:18 | [diff] [blame] | 605 | |
Steven Holte | 971b059 | 2017-10-12 15:28:26 | [diff] [blame] | 606 | base::SequencedTaskRunnerHandle::Get()->PostDelayedTask( |
bcwhite | 8e72aa59 | 2017-06-09 18:59:18 | [diff] [blame] | 607 | FROM_HERE, |
tzik | 2bcf8e4 | 2018-07-31 11:22:15 | [diff] [blame] | 608 | base::BindOnce(&MetricsService::PrepareProviderMetricsTask, |
| 609 | self_ptr_factory_.GetWeakPtr()), |
Nate Fischer | e823643 | 2019-10-25 02:36:32 | [diff] [blame] | 610 | 2 * initialization_delay); |
initial.commit | 09911bf | 2008-07-26 23:55:29 | [diff] [blame] | 611 | } |
| 612 | } |
| 613 | |
isherman | b670568 | 2015-08-29 00:01:00 | [diff] [blame] | 614 | void MetricsService::StartInitTask() { |
Steven Holte | c35411dc | 2017-07-28 04:22:14 | [diff] [blame] | 615 | delegating_provider_.AsyncInit(base::Bind(&MetricsService::FinishedInitTask, |
Steven Holte | 915c99f | 2017-07-21 23:34:31 | [diff] [blame] | 616 | self_ptr_factory_.GetWeakPtr())); |
[email protected] | 51994b2 | 2014-05-30 13:24:21 | [diff] [blame] | 617 | } |
| 618 | |
[email protected] | 410938e0 | 2012-10-24 16:33:59 | [diff] [blame] | 619 | void MetricsService::CloseCurrentLog() { |
[email protected] | cac267c | 2011-09-29 15:18:10 | [diff] [blame] | 620 | if (!log_manager_.current_log()) |
initial.commit | 09911bf | 2008-07-26 23:55:29 | [diff] [blame] | 621 | return; |
| 622 | |
bcwhite | 5cb99eb | 2016-02-01 21:07:56 | [diff] [blame] | 623 | // If a persistent allocator is in use, update its internal histograms (such |
| 624 | // as how much memory is being used) before reporting. |
bcwhite | 33d95806a | 2016-03-16 02:37:45 | [diff] [blame] | 625 | base::PersistentHistogramAllocator* allocator = |
bcwhite | 5e748c6 | 2016-04-06 02:03:53 | [diff] [blame] | 626 | base::GlobalHistogramAllocator::Get(); |
bcwhite | 5cb99eb | 2016-02-01 21:07:56 | [diff] [blame] | 627 | if (allocator) |
| 628 | allocator->UpdateTrackingHistograms(); |
| 629 | |
[email protected] | 0b33f80b | 2008-12-17 21:34:36 | [diff] [blame] | 630 | // Put incremental data (histogram deltas, and realtime stats deltas) at the |
[email protected] | 147bbc0b | 2009-01-06 19:37:40 | [diff] [blame] | 631 | // end of all log transmissions (initial log handles this separately). |
[email protected] | 024b5cd | 2011-05-27 03:29:38 | [diff] [blame] | 632 | // RecordIncrementalStabilityElements only exists on the derived |
| 633 | // MetricsLog class. |
[email protected] | 94dce12 | 2014-07-16 04:20:12 | [diff] [blame] | 634 | MetricsLog* current_log = log_manager_.current_log(); |
[email protected] | 024b5cd | 2011-05-27 03:29:38 | [diff] [blame] | 635 | DCHECK(current_log); |
Alexei Svitkine | 70c9502 | 2019-08-21 18:13:24 | [diff] [blame] | 636 | RecordCurrentEnvironment(current_log, /*complete=*/true); |
[email protected] | 076961c | 2014-03-12 22:23:56 | [diff] [blame] | 637 | base::TimeDelta incremental_uptime; |
| 638 | base::TimeDelta uptime; |
[email protected] | 24f81ca | 2014-05-26 15:59:34 | [diff] [blame] | 639 | GetUptimes(local_state_, &incremental_uptime, &uptime); |
Steven Holte | c35411dc | 2017-07-28 04:22:14 | [diff] [blame] | 640 | current_log->RecordCurrentSessionData(&delegating_provider_, |
| 641 | incremental_uptime, uptime); |
mariakhomenko | 19102898 | 2014-10-20 23:22:56 | [diff] [blame] | 642 | RecordCurrentHistograms(); |
rkaplow | 78985a0 | 2017-06-05 16:13:19 | [diff] [blame] | 643 | current_log->TruncateEvents(); |
holte | 6e36a3d | 2017-02-02 22:41:10 | [diff] [blame] | 644 | DVLOG(1) << "Generated an ongoing log."; |
holte | a3b2411 | 2017-03-14 02:08:24 | [diff] [blame] | 645 | log_manager_.FinishCurrentLog(log_store()); |
initial.commit | 09911bf | 2008-07-26 23:55:29 | [diff] [blame] | 646 | } |
| 647 | |
[email protected] | cac267c | 2011-09-29 15:18:10 | [diff] [blame] | 648 | void MetricsService::PushPendingLogsToPersistentStorage() { |
Steven Holte | 2c294a3 | 2015-03-12 21:45:03 | [diff] [blame] | 649 | if (state_ < SENDING_LOGS) |
[email protected] | 28ab7f9 | 2009-01-06 21:39:04 | [diff] [blame] | 650 | return; // We didn't and still don't have time to get plugin list etc. |
initial.commit | 09911bf | 2008-07-26 23:55:29 | [diff] [blame] | 651 | |
[email protected] | 410938e0 | 2012-10-24 16:33:59 | [diff] [blame] | 652 | CloseCurrentLog(); |
holte | a3b2411 | 2017-03-14 02:08:24 | [diff] [blame] | 653 | log_store()->PersistUnsentLogs(); |
initial.commit | 09911bf | 2008-07-26 23:55:29 | [diff] [blame] | 654 | } |
| 655 | |
| 656 | //------------------------------------------------------------------------------ |
| 657 | // Transmission of logs methods |
| 658 | |
[email protected] | 7f7f196 | 2011-04-20 15:58:16 | [diff] [blame] | 659 | void MetricsService::StartSchedulerIfNecessary() { |
[email protected] | 410938e0 | 2012-10-24 16:33:59 | [diff] [blame] | 660 | // Never schedule cutting or uploading of logs in test mode. |
| 661 | if (test_mode_active_) |
| 662 | return; |
| 663 | |
| 664 | // Even if reporting is disabled, the scheduler is needed to trigger the |
| 665 | // creation of the initial log, which must be done in order for any logs to be |
| 666 | // persisted on shutdown or backgrounding. |
[email protected] | 80a8f31 | 2013-12-16 18:00:30 | [diff] [blame] | 667 | if (recording_active() && |
Steven Holte | 2c294a3 | 2015-03-12 21:45:03 | [diff] [blame] | 668 | (reporting_active() || state_ < SENDING_LOGS)) { |
holte | c1b9731 | 2017-02-24 21:37:10 | [diff] [blame] | 669 | rotation_scheduler_->Start(); |
holte | a3b2411 | 2017-03-14 02:08:24 | [diff] [blame] | 670 | reporting_service_.Start(); |
[email protected] | 80a8f31 | 2013-12-16 18:00:30 | [diff] [blame] | 671 | } |
initial.commit | 09911bf | 2008-07-26 23:55:29 | [diff] [blame] | 672 | } |
| 673 | |
[email protected] | 7f7f196 | 2011-04-20 15:58:16 | [diff] [blame] | 674 | void MetricsService::StartScheduledUpload() { |
holte | 6e36a3d | 2017-02-02 22:41:10 | [diff] [blame] | 675 | DVLOG(1) << "StartScheduledUpload"; |
holte | a6a3917 | 2015-03-25 19:57:20 | [diff] [blame] | 676 | DCHECK(state_ >= INIT_TASK_DONE); |
Brian White | 8050710b | 2017-08-30 13:58:04 | [diff] [blame] | 677 | |
[email protected] | cd1ac71 | 2012-06-26 08:26:47 | [diff] [blame] | 678 | // If we're getting no notifications, then the log won't have much in it, and |
| 679 | // it's possible the computer is about to go to sleep, so don't upload and |
| 680 | // stop the scheduler. |
[email protected] | 410938e0 | 2012-10-24 16:33:59 | [diff] [blame] | 681 | // If recording has been turned off, the scheduler doesn't need to run. |
| 682 | // If reporting is off, proceed if the initial log hasn't been created, since |
| 683 | // that has to happen in order for logs to be cut and stored when persisting. |
[email protected] | d7ea39e | 2014-05-22 03:59:18 | [diff] [blame] | 684 | // TODO(stuartmorgan): Call Stop() on the scheduler when reporting and/or |
[email protected] | cd1ac71 | 2012-06-26 08:26:47 | [diff] [blame] | 685 | // recording are turned off instead of letting it fire and then aborting. |
| 686 | if (idle_since_last_transmission_ || |
[email protected] | 410938e0 | 2012-10-24 16:33:59 | [diff] [blame] | 687 | !recording_active() || |
Steven Holte | 2c294a3 | 2015-03-12 21:45:03 | [diff] [blame] | 688 | (!reporting_active() && state_ >= SENDING_LOGS)) { |
holte | c1b9731 | 2017-02-24 21:37:10 | [diff] [blame] | 689 | rotation_scheduler_->Stop(); |
| 690 | rotation_scheduler_->RotationFinished(); |
[email protected] | 7f7f196 | 2011-04-20 15:58:16 | [diff] [blame] | 691 | return; |
| 692 | } |
| 693 | |
[email protected] | cd1ac71 | 2012-06-26 08:26:47 | [diff] [blame] | 694 | // If there are unsent logs, send the next one. If not, start the asynchronous |
| 695 | // process of finalizing the current log for upload. |
holte | a3b2411 | 2017-03-14 02:08:24 | [diff] [blame] | 696 | if (state_ == SENDING_LOGS && has_unsent_logs()) { |
| 697 | reporting_service_.Start(); |
holte | c1b9731 | 2017-02-24 21:37:10 | [diff] [blame] | 698 | rotation_scheduler_->RotationFinished(); |
[email protected] | cd1ac71 | 2012-06-26 08:26:47 | [diff] [blame] | 699 | } else { |
holte | a6a3917 | 2015-03-25 19:57:20 | [diff] [blame] | 700 | // There are no logs left to send, so start creating a new one. |
isherman | b670568 | 2015-08-29 00:01:00 | [diff] [blame] | 701 | client_->CollectFinalMetricsForLog( |
[email protected] | 4b4892b | 2014-05-22 15:06:15 | [diff] [blame] | 702 | base::Bind(&MetricsService::OnFinalLogInfoCollectionDone, |
| 703 | self_ptr_factory_.GetWeakPtr())); |
[email protected] | cd1ac71 | 2012-06-26 08:26:47 | [diff] [blame] | 704 | } |
[email protected] | 2994826 | 2012-03-01 12:15:08 | [diff] [blame] | 705 | } |
| 706 | |
[email protected] | 2994826 | 2012-03-01 12:15:08 | [diff] [blame] | 707 | void MetricsService::OnFinalLogInfoCollectionDone() { |
holte | 6e36a3d | 2017-02-02 22:41:10 | [diff] [blame] | 708 | DVLOG(1) << "OnFinalLogInfoCollectionDone"; |
Brian White | 8050710b | 2017-08-30 13:58:04 | [diff] [blame] | 709 | |
[email protected] | cd1ac71 | 2012-06-26 08:26:47 | [diff] [blame] | 710 | // Abort if metrics were turned off during the final info gathering. |
[email protected] | 410938e0 | 2012-10-24 16:33:59 | [diff] [blame] | 711 | if (!recording_active()) { |
holte | c1b9731 | 2017-02-24 21:37:10 | [diff] [blame] | 712 | rotation_scheduler_->Stop(); |
| 713 | rotation_scheduler_->RotationFinished(); |
[email protected] | d01b873 | 2008-10-16 02:18:07 | [diff] [blame] | 714 | return; |
| 715 | } |
| 716 | |
holte | a6a3917 | 2015-03-25 19:57:20 | [diff] [blame] | 717 | if (state_ == INIT_TASK_DONE) { |
| 718 | PrepareInitialMetricsLog(); |
| 719 | } else { |
| 720 | DCHECK_EQ(SENDING_LOGS, state_); |
| 721 | CloseCurrentLog(); |
| 722 | OpenNewLog(); |
| 723 | } |
holte | a3b2411 | 2017-03-14 02:08:24 | [diff] [blame] | 724 | reporting_service_.Start(); |
holte | c1b9731 | 2017-02-24 21:37:10 | [diff] [blame] | 725 | rotation_scheduler_->RotationFinished(); |
holte | a3b2411 | 2017-03-14 02:08:24 | [diff] [blame] | 726 | HandleIdleSinceLastTransmission(true); |
[email protected] | 2994826 | 2012-03-01 12:15:08 | [diff] [blame] | 727 | } |
| 728 | |
manzagop | ea99d195 | 2016-09-08 23:40:05 | [diff] [blame] | 729 | bool MetricsService::PrepareInitialStabilityLog( |
| 730 | const std::string& prefs_previous_version) { |
[email protected] | 80a8f31 | 2013-12-16 18:00:30 | [diff] [blame] | 731 | DCHECK_EQ(INITIALIZED, state_); |
[email protected] | 2994826 | 2012-03-01 12:15:08 | [diff] [blame] | 732 | |
dcheng | d99c42a | 2016-04-21 21:54:13 | [diff] [blame] | 733 | std::unique_ptr<MetricsLog> initial_stability_log( |
[email protected] | 09dee82d | 2014-05-22 14:00:53 | [diff] [blame] | 734 | CreateLog(MetricsLog::INITIAL_STABILITY_LOG)); |
[email protected] | 2a321de3 | 2014-05-10 19:59:06 | [diff] [blame] | 735 | |
Steven Holte | c35411dc | 2017-07-28 04:22:14 | [diff] [blame] | 736 | // Do not call OnDidCreateMetricsLog here because the stability |
[email protected] | 2a321de3 | 2014-05-10 19:59:06 | [diff] [blame] | 737 | // log describes stats from the _previous_ session. |
manzagop | ea99d195 | 2016-09-08 23:40:05 | [diff] [blame] | 738 | std::string system_profile_app_version; |
| 739 | if (!initial_stability_log->LoadSavedEnvironmentFromPrefs( |
Steven Holte | d0429a70 | 2017-08-03 08:56:17 | [diff] [blame] | 740 | local_state_, &system_profile_app_version)) { |
Steven Holte | 2c294a3 | 2015-03-12 21:45:03 | [diff] [blame] | 741 | return false; |
manzagop | ea99d195 | 2016-09-08 23:40:05 | [diff] [blame] | 742 | } |
| 743 | if (system_profile_app_version != prefs_previous_version) |
holte | 1bf273c | 2017-02-23 00:22:28 | [diff] [blame] | 744 | StabilityMetricsProvider(local_state_).LogStabilityVersionMismatch(); |
[email protected] | 85791b0b | 2014-05-20 15:18:58 | [diff] [blame] | 745 | |
[email protected] | 80a8f31 | 2013-12-16 18:00:30 | [diff] [blame] | 746 | log_manager_.PauseCurrentLog(); |
dcheng | 5160635 | 2015-12-26 21:16:23 | [diff] [blame] | 747 | log_manager_.BeginLoggingWithLog(std::move(initial_stability_log)); |
[email protected] | 85791b0b | 2014-05-20 15:18:58 | [diff] [blame] | 748 | |
| 749 | // Note: Some stability providers may record stability stats via histograms, |
| 750 | // so this call has to be after BeginLoggingWithLog(). |
Steven Holte | c35411dc | 2017-07-28 04:22:14 | [diff] [blame] | 751 | log_manager_.current_log()->RecordPreviousSessionData(&delegating_provider_); |
[email protected] | c778687a | 2014-02-11 14:46:45 | [diff] [blame] | 752 | RecordCurrentStabilityHistograms(); |
[email protected] | 85791b0b | 2014-05-20 15:18:58 | [diff] [blame] | 753 | |
holte | 6e36a3d | 2017-02-02 22:41:10 | [diff] [blame] | 754 | DVLOG(1) << "Generated an stability log."; |
holte | a3b2411 | 2017-03-14 02:08:24 | [diff] [blame] | 755 | log_manager_.FinishCurrentLog(log_store()); |
[email protected] | 80a8f31 | 2013-12-16 18:00:30 | [diff] [blame] | 756 | log_manager_.ResumePausedLog(); |
| 757 | |
| 758 | // Store unsent logs, including the stability log that was just saved, so |
| 759 | // that they're not lost in case of a crash before upload time. |
holte | a3b2411 | 2017-03-14 02:08:24 | [diff] [blame] | 760 | log_store()->PersistUnsentLogs(); |
[email protected] | 80a8f31 | 2013-12-16 18:00:30 | [diff] [blame] | 761 | |
Steven Holte | 2c294a3 | 2015-03-12 21:45:03 | [diff] [blame] | 762 | return true; |
[email protected] | 80a8f31 | 2013-12-16 18:00:30 | [diff] [blame] | 763 | } |
| 764 | |
[email protected] | b58b8b2 | 2014-04-08 22:40:33 | [diff] [blame] | 765 | void MetricsService::PrepareInitialMetricsLog() { |
Steven Holte | 2c294a3 | 2015-03-12 21:45:03 | [diff] [blame] | 766 | DCHECK_EQ(INIT_TASK_DONE, state_); |
[email protected] | 0edf876 | 2013-11-21 18:33:30 | [diff] [blame] | 767 | |
Alexei Svitkine | 70c9502 | 2019-08-21 18:13:24 | [diff] [blame] | 768 | RecordCurrentEnvironment(initial_metrics_log_.get(), /*complete=*/true); |
[email protected] | 076961c | 2014-03-12 22:23:56 | [diff] [blame] | 769 | base::TimeDelta incremental_uptime; |
| 770 | base::TimeDelta uptime; |
[email protected] | 24f81ca | 2014-05-26 15:59:34 | [diff] [blame] | 771 | GetUptimes(local_state_, &incremental_uptime, &uptime); |
[email protected] | 2994826 | 2012-03-01 12:15:08 | [diff] [blame] | 772 | |
| 773 | // Histograms only get written to the current log, so make the new log current |
| 774 | // before writing them. |
| 775 | log_manager_.PauseCurrentLog(); |
dcheng | 5160635 | 2015-12-26 21:16:23 | [diff] [blame] | 776 | log_manager_.BeginLoggingWithLog(std::move(initial_metrics_log_)); |
[email protected] | 85791b0b | 2014-05-20 15:18:58 | [diff] [blame] | 777 | |
| 778 | // Note: Some stability providers may record stability stats via histograms, |
| 779 | // so this call has to be after BeginLoggingWithLog(). |
Steven Holte | 631803df | 2017-07-24 23:40:34 | [diff] [blame] | 780 | log_manager_.current_log()->RecordCurrentSessionData( |
Steven Holte | c35411dc | 2017-07-28 04:22:14 | [diff] [blame] | 781 | &delegating_provider_, base::TimeDelta(), base::TimeDelta()); |
mariakhomenko | 19102898 | 2014-10-20 23:22:56 | [diff] [blame] | 782 | RecordCurrentHistograms(); |
[email protected] | 85791b0b | 2014-05-20 15:18:58 | [diff] [blame] | 783 | |
holte | 6e36a3d | 2017-02-02 22:41:10 | [diff] [blame] | 784 | DVLOG(1) << "Generated an initial log."; |
holte | a3b2411 | 2017-03-14 02:08:24 | [diff] [blame] | 785 | log_manager_.FinishCurrentLog(log_store()); |
[email protected] | 2994826 | 2012-03-01 12:15:08 | [diff] [blame] | 786 | log_manager_.ResumePausedLog(); |
| 787 | |
[email protected] | 94dce12 | 2014-07-16 04:20:12 | [diff] [blame] | 788 | // Store unsent logs, including the initial log that was just saved, so |
| 789 | // that they're not lost in case of a crash before upload time. |
holte | a3b2411 | 2017-03-14 02:08:24 | [diff] [blame] | 790 | log_store()->PersistUnsentLogs(); |
holte | a6a3917 | 2015-03-25 19:57:20 | [diff] [blame] | 791 | |
| 792 | state_ = SENDING_LOGS; |
[email protected] | 2994826 | 2012-03-01 12:15:08 | [diff] [blame] | 793 | } |
| 794 | |
[email protected] | 57ecc4b | 2010-08-11 03:02:51 | [diff] [blame] | 795 | void MetricsService::IncrementLongPrefsValue(const char* path) { |
avi | 2606292 | 2015-12-26 00:14:18 | [diff] [blame] | 796 | int64_t value = local_state_->GetInt64(path); |
[email protected] | 24f81ca | 2014-05-26 15:59:34 | [diff] [blame] | 797 | local_state_->SetInt64(path, value + 1); |
[email protected] | 0bb1a62 | 2009-03-04 03:22:32 | [diff] [blame] | 798 | } |
| 799 | |
[email protected] | c0c55e9 | 2011-09-10 18:47:30 | [diff] [blame] | 800 | bool MetricsService::UmaMetricsProperlyShutdown() { |
| 801 | CHECK(clean_shutdown_status_ == CLEANLY_SHUTDOWN || |
| 802 | clean_shutdown_status_ == NEED_TO_SHUTDOWN); |
| 803 | return clean_shutdown_status_ == CLEANLY_SHUTDOWN; |
| 804 | } |
| 805 | |
[email protected] | 85791b0b | 2014-05-20 15:18:58 | [diff] [blame] | 806 | void MetricsService::RegisterMetricsProvider( |
dcheng | d99c42a | 2016-04-21 21:54:13 | [diff] [blame] | 807 | std::unique_ptr<MetricsProvider> provider) { |
[email protected] | 85791b0b | 2014-05-20 15:18:58 | [diff] [blame] | 808 | DCHECK_EQ(INITIALIZED, state_); |
Steven Holte | c35411dc | 2017-07-28 04:22:14 | [diff] [blame] | 809 | delegating_provider_.RegisterMetricsProvider(std::move(provider)); |
[email protected] | 85791b0b | 2014-05-20 15:18:58 | [diff] [blame] | 810 | } |
| 811 | |
Gabriel Charette | 45f796f | 2017-07-12 07:00:54 | [diff] [blame] | 812 | void MetricsService::CheckForClonedInstall() { |
| 813 | state_manager_->CheckForClonedInstall(); |
[email protected] | 99c892d | 2014-03-24 18:11:21 | [diff] [blame] | 814 | } |
| 815 | |
dcheng | d99c42a | 2016-04-21 21:54:13 | [diff] [blame] | 816 | std::unique_ptr<MetricsLog> MetricsService::CreateLog( |
| 817 | MetricsLog::LogType log_type) { |
Gyuyoung Kim | 6afb508 | 2018-01-19 13:35:57 | [diff] [blame] | 818 | return std::make_unique<MetricsLog>(state_manager_->client_id(), session_id_, |
Steven Holte | d0429a70 | 2017-08-03 08:56:17 | [diff] [blame] | 819 | log_type, client_); |
| 820 | } |
| 821 | |
Alexei Svitkine | 70c9502 | 2019-08-21 18:13:24 | [diff] [blame] | 822 | void MetricsService::SetPersistentSystemProfile( |
| 823 | const std::string& serialized_proto, |
| 824 | bool complete) { |
| 825 | GlobalPersistentSystemProfile::GetInstance()->SetSystemProfile( |
| 826 | serialized_proto, complete); |
| 827 | } |
| 828 | |
| 829 | // static |
Steven Holte | d0429a70 | 2017-08-03 08:56:17 | [diff] [blame] | 830 | std::string MetricsService::RecordCurrentEnvironmentHelper( |
| 831 | MetricsLog* log, |
| 832 | PrefService* local_state, |
Steven Holte | 8e9db0ca | 2017-08-11 01:20:08 | [diff] [blame] | 833 | DelegatingProvider* delegating_provider) { |
Steven Holte | d0429a70 | 2017-08-03 08:56:17 | [diff] [blame] | 834 | const SystemProfileProto& system_profile = |
Steven Holte | 8e9db0ca | 2017-08-11 01:20:08 | [diff] [blame] | 835 | log->RecordEnvironment(delegating_provider); |
Steven Holte | d0429a70 | 2017-08-03 08:56:17 | [diff] [blame] | 836 | EnvironmentRecorder recorder(local_state); |
| 837 | return recorder.SerializeAndRecordEnvironmentToPrefs(system_profile); |
[email protected] | 09dee82d | 2014-05-22 14:00:53 | [diff] [blame] | 838 | } |
| 839 | |
Alexei Svitkine | 70c9502 | 2019-08-21 18:13:24 | [diff] [blame] | 840 | void MetricsService::RecordCurrentEnvironment(MetricsLog* log, bool complete) { |
manzagop | a5d6688d | 2016-10-25 20:16:03 | [diff] [blame] | 841 | DCHECK(client_); |
Steven Holte | 8e9db0ca | 2017-08-11 01:20:08 | [diff] [blame] | 842 | std::string serialized_proto = |
| 843 | RecordCurrentEnvironmentHelper(log, local_state_, &delegating_provider_); |
Alexei Svitkine | 70c9502 | 2019-08-21 18:13:24 | [diff] [blame] | 844 | |
| 845 | SetPersistentSystemProfile(serialized_proto, complete); |
Steven Holte | d0429a70 | 2017-08-03 08:56:17 | [diff] [blame] | 846 | client_->OnEnvironmentUpdate(&serialized_proto); |
asvitkine | 88aa933 | 2014-09-29 23:29:17 | [diff] [blame] | 847 | } |
| 848 | |
[email protected] | acc2ce551 | 2014-05-22 18:29:13 | [diff] [blame] | 849 | void MetricsService::RecordCurrentHistograms() { |
| 850 | DCHECK(log_manager_.current_log()); |
bcwhite | 05dc092 | 2016-06-03 04:59:44 | [diff] [blame] | 851 | |
Alexei Svitkine | 24a116bb | 2017-07-24 18:31:31 | [diff] [blame] | 852 | // "true" indicates that StatisticsRecorder should include histograms held in |
| 853 | // persistent storage. |
| 854 | base::StatisticsRecorder::PrepareDeltas( |
| 855 | true, base::Histogram::kNoFlags, |
| 856 | base::Histogram::kUmaTargetedHistogramFlag, &histogram_snapshot_manager_); |
Steven Holte | c35411dc | 2017-07-28 04:22:14 | [diff] [blame] | 857 | delegating_provider_.RecordHistogramSnapshots(&histogram_snapshot_manager_); |
[email protected] | acc2ce551 | 2014-05-22 18:29:13 | [diff] [blame] | 858 | } |
| 859 | |
| 860 | void MetricsService::RecordCurrentStabilityHistograms() { |
| 861 | DCHECK(log_manager_.current_log()); |
Alexei Svitkine | 24a116bb | 2017-07-24 18:31:31 | [diff] [blame] | 862 | // "true" indicates that StatisticsRecorder should include histograms held in |
bcwhite | 5cb99eb | 2016-02-01 21:07:56 | [diff] [blame] | 863 | // persistent storage. |
Alexei Svitkine | 24a116bb | 2017-07-24 18:31:31 | [diff] [blame] | 864 | base::StatisticsRecorder::PrepareDeltas( |
| 865 | true, base::Histogram::kNoFlags, |
| 866 | base::Histogram::kUmaStabilityHistogramFlag, |
| 867 | &histogram_snapshot_manager_); |
Steven Holte | c35411dc | 2017-07-28 04:22:14 | [diff] [blame] | 868 | delegating_provider_.RecordInitialHistogramSnapshots( |
| 869 | &histogram_snapshot_manager_); |
[email protected] | acc2ce551 | 2014-05-22 18:29:13 | [diff] [blame] | 870 | } |
| 871 | |
Brian White | 2868e61 | 2018-10-26 01:30:24 | [diff] [blame] | 872 | void MetricsService::PrepareProviderMetricsLogDone( |
| 873 | std::unique_ptr<MetricsLog::IndependentMetricsLoader> loader, |
| 874 | bool success) { |
| 875 | DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); |
| 876 | DCHECK(independent_loader_active_); |
| 877 | DCHECK(loader); |
| 878 | |
| 879 | if (success) { |
| 880 | log_manager_.PauseCurrentLog(); |
| 881 | log_manager_.BeginLoggingWithLog(loader->ReleaseLog()); |
| 882 | log_manager_.FinishCurrentLog(log_store()); |
| 883 | log_manager_.ResumePausedLog(); |
| 884 | } |
| 885 | |
| 886 | independent_loader_active_ = false; |
| 887 | } |
| 888 | |
bcwhite | 8e72aa59 | 2017-06-09 18:59:18 | [diff] [blame] | 889 | bool MetricsService::PrepareProviderMetricsLog() { |
Steven Holte | 971b059 | 2017-10-12 15:28:26 | [diff] [blame] | 890 | DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); |
bcwhite | 8e72aa59 | 2017-06-09 18:59:18 | [diff] [blame] | 891 | |
Brian White | 2868e61 | 2018-10-26 01:30:24 | [diff] [blame] | 892 | // If something is still pending, stop now and indicate that there is |
| 893 | // still work to do. |
| 894 | if (independent_loader_active_) |
| 895 | return true; |
bcwhite | 8e72aa59 | 2017-06-09 18:59:18 | [diff] [blame] | 896 | |
Brian White | 2868e61 | 2018-10-26 01:30:24 | [diff] [blame] | 897 | // Check each provider in turn for data. |
Steven Holte | c35411dc | 2017-07-28 04:22:14 | [diff] [blame] | 898 | for (auto& provider : delegating_provider_.GetProviders()) { |
Brian White | 2868e61 | 2018-10-26 01:30:24 | [diff] [blame] | 899 | if (provider->HasIndependentMetrics()) { |
| 900 | // Create a new log. This will have some default values injected in it |
| 901 | // but those will be overwritten when an embedded profile is extracted. |
| 902 | std::unique_ptr<MetricsLog> log = CreateLog(MetricsLog::INDEPENDENT_LOG); |
| 903 | |
Brian White | d384aee | 2018-10-29 15:41:58 | [diff] [blame] | 904 | // Note that something is happening. This must be set before the |
| 905 | // operation is requested in case the loader decides to do everything |
| 906 | // immediately rather than as a background task. |
| 907 | independent_loader_active_ = true; |
| 908 | |
Brian White | 2868e61 | 2018-10-26 01:30:24 | [diff] [blame] | 909 | // Give the new log to a loader for management and then run it on the |
| 910 | // provider that has something to give. A copy of the pointer is needed |
| 911 | // because the unique_ptr may get moved before the value can be used |
| 912 | // to call Run(). |
| 913 | std::unique_ptr<MetricsLog::IndependentMetricsLoader> loader = |
| 914 | std::make_unique<MetricsLog::IndependentMetricsLoader>( |
| 915 | std::move(log)); |
| 916 | MetricsLog::IndependentMetricsLoader* loader_ptr = loader.get(); |
| 917 | loader_ptr->Run( |
| 918 | base::BindOnce(&MetricsService::PrepareProviderMetricsLogDone, |
| 919 | self_ptr_factory_.GetWeakPtr(), std::move(loader)), |
| 920 | provider.get()); |
Brian White | 2868e61 | 2018-10-26 01:30:24 | [diff] [blame] | 921 | |
| 922 | // Something was found so there may still be more work to do. |
bcwhite | 8e72aa59 | 2017-06-09 18:59:18 | [diff] [blame] | 923 | return true; |
| 924 | } |
| 925 | } |
Brian White | 2868e61 | 2018-10-26 01:30:24 | [diff] [blame] | 926 | |
| 927 | // Nothing was found so indicate there is no more work to do. |
bcwhite | 8e72aa59 | 2017-06-09 18:59:18 | [diff] [blame] | 928 | return false; |
| 929 | } |
| 930 | |
| 931 | void MetricsService::PrepareProviderMetricsTask() { |
Steven Holte | 971b059 | 2017-10-12 15:28:26 | [diff] [blame] | 932 | DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); |
bcwhite | 8e72aa59 | 2017-06-09 18:59:18 | [diff] [blame] | 933 | bool found = PrepareProviderMetricsLog(); |
| 934 | base::TimeDelta next_check = found ? base::TimeDelta::FromSeconds(5) |
| 935 | : base::TimeDelta::FromMinutes(15); |
Steven Holte | 971b059 | 2017-10-12 15:28:26 | [diff] [blame] | 936 | base::SequencedTaskRunnerHandle::Get()->PostDelayedTask( |
bcwhite | 8e72aa59 | 2017-06-09 18:59:18 | [diff] [blame] | 937 | FROM_HERE, |
tzik | 2bcf8e4 | 2018-07-31 11:22:15 | [diff] [blame] | 938 | base::BindOnce(&MetricsService::PrepareProviderMetricsTask, |
| 939 | self_ptr_factory_.GetWeakPtr()), |
bcwhite | 8e72aa59 | 2017-06-09 18:59:18 | [diff] [blame] | 940 | next_check); |
| 941 | } |
| 942 | |
holte | 6d34116 | 2016-12-19 21:42:42 | [diff] [blame] | 943 | void MetricsService::LogCleanShutdown(bool end_completed) { |
Steven Holte | 971b059 | 2017-10-12 15:28:26 | [diff] [blame] | 944 | DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); |
[email protected] | c0c55e9 | 2011-09-10 18:47:30 | [diff] [blame] | 945 | // Redundant setting to assure that we always reset this value at shutdown |
| 946 | // (and that we don't use some alternate path, and not call LogCleanShutdown). |
| 947 | clean_shutdown_status_ = CLEANLY_SHUTDOWN; |
manzagop | 14aff5d | 2016-11-23 17:27:00 | [diff] [blame] | 948 | client_->OnLogCleanShutdown(); |
Ilya Sherman | 6c6c833 | 2017-07-11 22:39:22 | [diff] [blame] | 949 | state_manager_->clean_exit_beacon()->WriteBeaconValue(true); |
holte | 1bf273c | 2017-02-23 00:22:28 | [diff] [blame] | 950 | StabilityMetricsProvider(local_state_).MarkSessionEndCompleted(end_completed); |
initial.commit | 09911bf | 2008-07-26 23:55:29 | [diff] [blame] | 951 | } |
asvitkine | cbd42073 | 2014-08-26 22:15:40 | [diff] [blame] | 952 | |
Sigurdur Asgeirsson | 5795250 | 2018-01-29 16:15:08 | [diff] [blame] | 953 | void MetricsService::UpdateLastLiveTimestampTask() { |
| 954 | state_manager_->clean_exit_beacon()->UpdateLastLiveTimestamp(); |
| 955 | |
| 956 | // Schecule the next update. |
| 957 | StartUpdatingLastLiveTimestamp(); |
| 958 | } |
| 959 | |
asvitkine | cbd42073 | 2014-08-26 22:15:40 | [diff] [blame] | 960 | } // namespace metrics |