[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" |
dcheng | d99c42a | 2016-04-21 21:54:13 | [diff] [blame] | 135 | #include "base/memory/ptr_util.h" |
[email protected] | acc2ce551 | 2014-05-22 18:29:13 | [diff] [blame] | 136 | #include "base/metrics/histogram_base.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] | 1026afd | 2013-03-20 14:28:54 | [diff] [blame] | 140 | #include "base/metrics/sparse_histogram.h" |
[email protected] | 567d30e | 2012-07-13 21:48:29 | [diff] [blame] | 141 | #include "base/metrics/statistics_recorder.h" |
skyostil | b0daa01 | 2015-06-02 19:03:48 | [diff] [blame] | 142 | #include "base/single_thread_task_runner.h" |
Robert Kaplow | d45b620 | 2017-07-20 02:01:46 | [diff] [blame] | 143 | #include "base/strings/string_piece.h" |
Steven Holte | 971b059 | 2017-10-12 15:28:26 | [diff] [blame] | 144 | #include "base/threading/sequenced_task_runner_handle.h" |
[email protected] | 64b8652c | 2014-07-16 19:14:28 | [diff] [blame] | 145 | #include "base/time/time.h" |
avi | 2606292 | 2015-12-26 00:14:18 | [diff] [blame] | 146 | #include "build/build_config.h" |
holte | 1bf273c | 2017-02-23 00:22:28 | [diff] [blame] | 147 | #include "components/metrics/environment_recorder.h" |
Steven Holte | 5c6dd63 | 2017-07-19 23:25:49 | [diff] [blame] | 148 | #include "components/metrics/field_trials_provider.h" |
[email protected] | 91b1d91 | 2014-06-05 10:52:08 | [diff] [blame] | 149 | #include "components/metrics/metrics_log.h" |
[email protected] | 064107e | 2014-05-02 00:59:06 | [diff] [blame] | 150 | #include "components/metrics/metrics_log_manager.h" |
[email protected] | 0d5a61a8 | 2014-05-31 22:28:34 | [diff] [blame] | 151 | #include "components/metrics/metrics_log_uploader.h" |
[email protected] | 7f07db6 | 2014-05-15 01:12:45 | [diff] [blame] | 152 | #include "components/metrics/metrics_pref_names.h" |
holte | 6839585 | 2017-01-10 20:40:21 | [diff] [blame] | 153 | #include "components/metrics/metrics_rotation_scheduler.h" |
[email protected] | 7392942 | 2014-05-22 08:19:05 | [diff] [blame] | 154 | #include "components/metrics/metrics_service_client.h" |
[email protected] | 16a3091 | 2014-06-04 00:20:04 | [diff] [blame] | 155 | #include "components/metrics/metrics_state_manager.h" |
Steven Holte | d0429a70 | 2017-08-03 08:56:17 | [diff] [blame] | 156 | #include "components/metrics/persistent_system_profile.h" |
holte | 1bf273c | 2017-02-23 00:22:28 | [diff] [blame] | 157 | #include "components/metrics/stability_metrics_provider.h" |
holte | 567a16f2 | 2017-01-06 01:53:45 | [diff] [blame] | 158 | #include "components/metrics/url_constants.h" |
brettw | f00b9b4 | 2016-02-01 22:11:38 | [diff] [blame] | 159 | #include "components/prefs/pref_registry_simple.h" |
| 160 | #include "components/prefs/pref_service.h" |
[email protected] | 50ae9f1 | 2013-08-29 18:03:22 | [diff] [blame] | 161 | #include "components/variations/entropy_provider.h" |
initial.commit | 09911bf | 2008-07-26 23:55:29 | [diff] [blame] | 162 | |
asvitkine | cbd42073 | 2014-08-26 22:15:40 | [diff] [blame] | 163 | namespace metrics { |
[email protected] | e1acf6f | 2008-10-27 20:43:33 | [diff] [blame] | 164 | |
holte | 6e36a3d | 2017-02-02 22:41:10 | [diff] [blame] | 165 | namespace { |
| 166 | |
[email protected] | 7f7f196 | 2011-04-20 15:58:16 | [diff] [blame] | 167 | // The delay, in seconds, after starting recording before doing expensive |
| 168 | // initialization work. |
[email protected] | 12180f8 | 2012-10-10 21:13:30 | [diff] [blame] | 169 | #if defined(OS_ANDROID) || defined(OS_IOS) |
| 170 | // On mobile devices, a significant portion of sessions last less than a minute. |
| 171 | // Use a shorter timer on these platforms to avoid losing data. |
| 172 | // TODO(dfalcantara): To avoid delaying startup, tighten up initialization so |
| 173 | // that it occurs after the user gets their initial page. |
| 174 | const int kInitializationDelaySeconds = 5; |
| 175 | #else |
[email protected] | fe58acc2 | 2012-02-29 01:29:58 | [diff] [blame] | 176 | const int kInitializationDelaySeconds = 30; |
[email protected] | 12180f8 | 2012-10-10 21:13:30 | [diff] [blame] | 177 | #endif |
[email protected] | 252873ef | 2008-08-04 21:59:45 | [diff] [blame] | 178 | |
hashimoto | a5c00e28d | 2015-03-27 06:28:37 | [diff] [blame] | 179 | #if defined(OS_ANDROID) || defined(OS_IOS) |
erikwright | 65b58df | 2014-09-12 00:05:28 | [diff] [blame] | 180 | void MarkAppCleanShutdownAndCommit(CleanExitBeacon* clean_exit_beacon, |
| 181 | PrefService* local_state) { |
| 182 | clean_exit_beacon->WriteBeaconValue(true); |
holte | a27eadf | 2017-01-26 01:58:59 | [diff] [blame] | 183 | ExecutionPhaseManager(local_state).OnAppEnterBackground(); |
[email protected] | 84c384e | 2013-03-01 23:20:19 | [diff] [blame] | 184 | // Start writing right away (write happens on a different thread). |
[email protected] | 24f81ca | 2014-05-26 15:59:34 | [diff] [blame] | 185 | local_state->CommitPendingWrite(); |
[email protected] | 84c384e | 2013-03-01 23:20:19 | [diff] [blame] | 186 | } |
hashimoto | a5c00e28d | 2015-03-27 06:28:37 | [diff] [blame] | 187 | #endif // defined(OS_ANDROID) || defined(OS_IOS) |
[email protected] | 84c384e | 2013-03-01 23:20:19 | [diff] [blame] | 188 | |
[email protected] | 20f999b5 | 2012-08-24 22:32:59 | [diff] [blame] | 189 | } // namespace |
initial.commit | 09911bf | 2008-07-26 23:55:29 | [diff] [blame] | 190 | |
[email protected] | c0c55e9 | 2011-09-10 18:47:30 | [diff] [blame] | 191 | // static |
| 192 | MetricsService::ShutdownCleanliness MetricsService::clean_shutdown_status_ = |
| 193 | MetricsService::CLEANLY_SHUTDOWN; |
| 194 | |
initial.commit | 09911bf | 2008-07-26 23:55:29 | [diff] [blame] | 195 | // static |
[email protected] | b1de2c7 | 2013-02-06 02:45:47 | [diff] [blame] | 196 | void MetricsService::RegisterPrefs(PrefRegistrySimple* registry) { |
holte | 1bf273c | 2017-02-23 00:22:28 | [diff] [blame] | 197 | CleanExitBeacon::RegisterPrefs(registry); |
asvitkine | a63d19e | 2014-10-24 16:19:39 | [diff] [blame] | 198 | MetricsStateManager::RegisterPrefs(registry); |
[email protected] | 91b1d91 | 2014-06-05 10:52:08 | [diff] [blame] | 199 | MetricsLog::RegisterPrefs(registry); |
holte | 1bf273c | 2017-02-23 00:22:28 | [diff] [blame] | 200 | StabilityMetricsProvider::RegisterPrefs(registry); |
holte | 1bf273c | 2017-02-23 00:22:28 | [diff] [blame] | 201 | ExecutionPhaseManager::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), |
[email protected] | 80a8f31 | 2013-12-16 18:00:30 | [diff] [blame] | 222 | session_id_(-1), |
holte | 57fcaed | 2017-01-23 22:14:31 | [diff] [blame] | 223 | self_ptr_factory_(this) { |
Steven Holte | 971b059 | 2017-10-12 15:28:26 | [diff] [blame] | 224 | DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); |
[email protected] | 3907664 | 2014-05-05 20:32:55 | [diff] [blame] | 225 | DCHECK(state_manager_); |
[email protected] | 728de07 | 2014-05-21 09:20:32 | [diff] [blame] | 226 | DCHECK(client_); |
[email protected] | 24f81ca | 2014-05-26 15:59:34 | [diff] [blame] | 227 | DCHECK(local_state_); |
[email protected] | 64b8652c | 2014-07-16 19:14:28 | [diff] [blame] | 228 | |
Steven Holte | 5c6dd63 | 2017-07-19 23:25:49 | [diff] [blame] | 229 | RegisterMetricsProvider( |
| 230 | base::MakeUnique<StabilityMetricsProvider>(local_state_)); |
| 231 | |
Steven Holte | d0429a70 | 2017-08-03 08:56:17 | [diff] [blame] | 232 | RegisterMetricsProvider(state_manager_->GetProvider()); |
| 233 | |
Steven Holte | 5c6dd63 | 2017-07-19 23:25:49 | [diff] [blame] | 234 | RegisterMetricsProvider(base::MakeUnique<variations::FieldTrialsProvider>( |
Robert Kaplow | d45b620 | 2017-07-20 02:01:46 | [diff] [blame] | 235 | &synthetic_trial_registry_, base::StringPiece())); |
initial.commit | 09911bf | 2008-07-26 23:55:29 | [diff] [blame] | 236 | } |
| 237 | |
| 238 | MetricsService::~MetricsService() { |
[email protected] | 410938e0 | 2012-10-24 16:33:59 | [diff] [blame] | 239 | DisableRecording(); |
initial.commit | 09911bf | 2008-07-26 23:55:29 | [diff] [blame] | 240 | } |
| 241 | |
[email protected] | 3907664 | 2014-05-05 20:32:55 | [diff] [blame] | 242 | void MetricsService::InitializeMetricsRecordingState() { |
holte | a3b2411 | 2017-03-14 02:08:24 | [diff] [blame] | 243 | reporting_service_.Initialize(); |
[email protected] | 3907664 | 2014-05-05 20:32:55 | [diff] [blame] | 244 | InitializeMetricsState(); |
[email protected] | 80a8f31 | 2013-12-16 18:00:30 | [diff] [blame] | 245 | |
gayane | d52ca40 | 2015-02-23 21:23:06 | [diff] [blame] | 246 | base::Closure upload_callback = |
| 247 | base::Bind(&MetricsService::StartScheduledUpload, |
| 248 | self_ptr_factory_.GetWeakPtr()); |
holte | 6839585 | 2017-01-10 20:40:21 | [diff] [blame] | 249 | |
holte | c1b9731 | 2017-02-24 21:37:10 | [diff] [blame] | 250 | rotation_scheduler_.reset(new MetricsRotationScheduler( |
| 251 | upload_callback, |
| 252 | // MetricsServiceClient outlives MetricsService, and |
| 253 | // MetricsRotationScheduler is tied to the lifetime of |this|. |
| 254 | base::Bind(&MetricsServiceClient::GetStandardUploadInterval, |
| 255 | base::Unretained(client_)))); |
dhsharp | b0073a2 | 2016-02-18 21:54:09 | [diff] [blame] | 256 | |
Steven Holte | c35411dc | 2017-07-28 04:22:14 | [diff] [blame] | 257 | delegating_provider_.Init(); |
[email protected] | 80a8f31 | 2013-12-16 18:00:30 | [diff] [blame] | 258 | } |
| 259 | |
[email protected] | d01b873 | 2008-10-16 02:18:07 | [diff] [blame] | 260 | void MetricsService::Start() { |
[email protected] | b1c8dc0 | 2011-04-13 18:32:04 | [diff] [blame] | 261 | HandleIdleSinceLastTransmission(false); |
[email protected] | 410938e0 | 2012-10-24 16:33:59 | [diff] [blame] | 262 | EnableRecording(); |
| 263 | EnableReporting(); |
[email protected] | d01b873 | 2008-10-16 02:18:07 | [diff] [blame] | 264 | } |
| 265 | |
[email protected] | 410938e0 | 2012-10-24 16:33:59 | [diff] [blame] | 266 | void MetricsService::StartRecordingForTests() { |
| 267 | test_mode_active_ = true; |
| 268 | EnableRecording(); |
| 269 | DisableReporting(); |
[email protected] | d01b873 | 2008-10-16 02:18:07 | [diff] [blame] | 270 | } |
| 271 | |
| 272 | void MetricsService::Stop() { |
[email protected] | b1c8dc0 | 2011-04-13 18:32:04 | [diff] [blame] | 273 | HandleIdleSinceLastTransmission(false); |
[email protected] | 410938e0 | 2012-10-24 16:33:59 | [diff] [blame] | 274 | DisableReporting(); |
| 275 | DisableRecording(); |
[email protected] | 410938e0 | 2012-10-24 16:33:59 | [diff] [blame] | 276 | } |
| 277 | |
| 278 | void MetricsService::EnableReporting() { |
holte | a3b2411 | 2017-03-14 02:08:24 | [diff] [blame] | 279 | if (reporting_service_.reporting_active()) |
[email protected] | 410938e0 | 2012-10-24 16:33:59 | [diff] [blame] | 280 | return; |
holte | a3b2411 | 2017-03-14 02:08:24 | [diff] [blame] | 281 | reporting_service_.EnableReporting(); |
[email protected] | 410938e0 | 2012-10-24 16:33:59 | [diff] [blame] | 282 | StartSchedulerIfNecessary(); |
| 283 | } |
| 284 | |
| 285 | void MetricsService::DisableReporting() { |
holte | a3b2411 | 2017-03-14 02:08:24 | [diff] [blame] | 286 | reporting_service_.DisableReporting(); |
[email protected] | d01b873 | 2008-10-16 02:18:07 | [diff] [blame] | 287 | } |
| 288 | |
[email protected] | edafd4c | 2011-05-10 17:18:53 | [diff] [blame] | 289 | std::string MetricsService::GetClientId() { |
[email protected] | 3907664 | 2014-05-05 20:32:55 | [diff] [blame] | 290 | return state_manager_->client_id(); |
[email protected] | edafd4c | 2011-05-10 17:18:53 | [diff] [blame] | 291 | } |
| 292 | |
avi | 2606292 | 2015-12-26 00:14:18 | [diff] [blame] | 293 | int64_t MetricsService::GetInstallDate() { |
Steven Holte | 8e9db0ca | 2017-08-11 01:20:08 | [diff] [blame] | 294 | return state_manager_->GetInstallDate(); |
olivierrobin | c3dfc5b | 2015-04-07 19:12:00 | [diff] [blame] | 295 | } |
| 296 | |
droger | b8d286e4 | 2015-07-08 09:07:09 | [diff] [blame] | 297 | bool MetricsService::WasLastShutdownClean() const { |
Ilya Sherman | 6c6c833 | 2017-07-11 22:39:22 | [diff] [blame] | 298 | return state_manager_->clean_exit_beacon()->exited_cleanly(); |
droger | b8d286e4 | 2015-07-08 09:07:09 | [diff] [blame] | 299 | } |
| 300 | |
[email protected] | 410938e0 | 2012-10-24 16:33:59 | [diff] [blame] | 301 | void MetricsService::EnableRecording() { |
Steven Holte | 971b059 | 2017-10-12 15:28:26 | [diff] [blame] | 302 | DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); |
initial.commit | 09911bf | 2008-07-26 23:55:29 | [diff] [blame] | 303 | |
wittman | 622851e | 2015-07-31 18:13:40 | [diff] [blame] | 304 | if (recording_state_ == ACTIVE) |
initial.commit | 09911bf | 2008-07-26 23:55:29 | [diff] [blame] | 305 | return; |
wittman | 622851e | 2015-07-31 18:13:40 | [diff] [blame] | 306 | recording_state_ = ACTIVE; |
initial.commit | 09911bf | 2008-07-26 23:55:29 | [diff] [blame] | 307 | |
[email protected] | 3907664 | 2014-05-05 20:32:55 | [diff] [blame] | 308 | state_manager_->ForceClientIdCreation(); |
[email protected] | 9d1b015 | 2014-07-09 18:53:22 | [diff] [blame] | 309 | client_->SetMetricsClientId(state_manager_->client_id()); |
Steven Holte | d0429a70 | 2017-08-03 08:56:17 | [diff] [blame] | 310 | |
| 311 | SystemProfileProto system_profile; |
| 312 | MetricsLog::RecordCoreSystemProfile(client_, &system_profile); |
| 313 | GlobalPersistentSystemProfile::GetInstance()->SetSystemProfile( |
| 314 | system_profile, /*complete=*/false); |
| 315 | |
[email protected] | 410938e0 | 2012-10-24 16:33:59 | [diff] [blame] | 316 | if (!log_manager_.current_log()) |
| 317 | OpenNewLog(); |
[email protected] | 005ef3e | 2009-05-22 20:55:46 | [diff] [blame] | 318 | |
Steven Holte | c35411dc | 2017-07-28 04:22:14 | [diff] [blame] | 319 | delegating_provider_.OnRecordingEnabled(); |
[email protected] | 85791b0b | 2014-05-20 15:18:58 | [diff] [blame] | 320 | |
[email protected] | e6e30ac | 2014-01-13 21:24:39 | [diff] [blame] | 321 | base::RemoveActionCallback(action_callback_); |
[email protected] | dd98f39 | 2013-02-04 13:03:22 | [diff] [blame] | 322 | action_callback_ = base::Bind(&MetricsService::OnUserAction, |
| 323 | base::Unretained(this)); |
[email protected] | e6e30ac | 2014-01-13 21:24:39 | [diff] [blame] | 324 | base::AddActionCallback(action_callback_); |
[email protected] | 410938e0 | 2012-10-24 16:33:59 | [diff] [blame] | 325 | } |
| 326 | |
| 327 | void MetricsService::DisableRecording() { |
Steven Holte | 971b059 | 2017-10-12 15:28:26 | [diff] [blame] | 328 | DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); |
[email protected] | 410938e0 | 2012-10-24 16:33:59 | [diff] [blame] | 329 | |
wittman | 622851e | 2015-07-31 18:13:40 | [diff] [blame] | 330 | if (recording_state_ == INACTIVE) |
[email protected] | 410938e0 | 2012-10-24 16:33:59 | [diff] [blame] | 331 | return; |
wittman | 622851e | 2015-07-31 18:13:40 | [diff] [blame] | 332 | recording_state_ = INACTIVE; |
[email protected] | 410938e0 | 2012-10-24 16:33:59 | [diff] [blame] | 333 | |
[email protected] | e6e30ac | 2014-01-13 21:24:39 | [diff] [blame] | 334 | base::RemoveActionCallback(action_callback_); |
[email protected] | 85791b0b | 2014-05-20 15:18:58 | [diff] [blame] | 335 | |
Steven Holte | c35411dc | 2017-07-28 04:22:14 | [diff] [blame] | 336 | delegating_provider_.OnRecordingDisabled(); |
[email protected] | 85791b0b | 2014-05-20 15:18:58 | [diff] [blame] | 337 | |
[email protected] | 410938e0 | 2012-10-24 16:33:59 | [diff] [blame] | 338 | PushPendingLogsToPersistentStorage(); |
initial.commit | 09911bf | 2008-07-26 23:55:29 | [diff] [blame] | 339 | } |
| 340 | |
[email protected] | d01b873 | 2008-10-16 02:18:07 | [diff] [blame] | 341 | bool MetricsService::recording_active() const { |
Steven Holte | 971b059 | 2017-10-12 15:28:26 | [diff] [blame] | 342 | DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); |
wittman | 622851e | 2015-07-31 18:13:40 | [diff] [blame] | 343 | return recording_state_ == ACTIVE; |
initial.commit | 09911bf | 2008-07-26 23:55:29 | [diff] [blame] | 344 | } |
| 345 | |
[email protected] | d01b873 | 2008-10-16 02:18:07 | [diff] [blame] | 346 | bool MetricsService::reporting_active() const { |
Steven Holte | 971b059 | 2017-10-12 15:28:26 | [diff] [blame] | 347 | DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); |
holte | a3b2411 | 2017-03-14 02:08:24 | [diff] [blame] | 348 | return reporting_service_.reporting_active(); |
| 349 | } |
| 350 | |
| 351 | bool MetricsService::has_unsent_logs() const { |
| 352 | return reporting_service_.metrics_log_store()->has_unsent_logs(); |
initial.commit | 09911bf | 2008-07-26 23:55:29 | [diff] [blame] | 353 | } |
| 354 | |
[email protected] | acc2ce551 | 2014-05-22 18:29:13 | [diff] [blame] | 355 | void MetricsService::RecordDelta(const base::HistogramBase& histogram, |
| 356 | const base::HistogramSamples& snapshot) { |
[email protected] | acc2ce551 | 2014-05-22 18:29:13 | [diff] [blame] | 357 | log_manager_.current_log()->RecordHistogramDelta(histogram.histogram_name(), |
| 358 | snapshot); |
[email protected] | acc2ce551 | 2014-05-22 18:29:13 | [diff] [blame] | 359 | } |
| 360 | |
[email protected] | d01b873 | 2008-10-16 02:18:07 | [diff] [blame] | 361 | void MetricsService::HandleIdleSinceLastTransmission(bool in_idle) { |
| 362 | // If there wasn't a lot of action, maybe the computer was asleep, in which |
| 363 | // case, the log transmissions should have stopped. Here we start them up |
| 364 | // again. |
[email protected] | cac7884 | 2008-11-27 01:02:20 | [diff] [blame] | 365 | if (!in_idle && idle_since_last_transmission_) |
[email protected] | 7f7f196 | 2011-04-20 15:58:16 | [diff] [blame] | 366 | StartSchedulerIfNecessary(); |
[email protected] | cac7884 | 2008-11-27 01:02:20 | [diff] [blame] | 367 | idle_since_last_transmission_ = in_idle; |
initial.commit | 09911bf | 2008-07-26 23:55:29 | [diff] [blame] | 368 | } |
| 369 | |
[email protected] | d7ea39e | 2014-05-22 03:59:18 | [diff] [blame] | 370 | void MetricsService::OnApplicationNotIdle() { |
wittman | 622851e | 2015-07-31 18:13:40 | [diff] [blame] | 371 | if (recording_state_ == ACTIVE) |
[email protected] | d7ea39e | 2014-05-22 03:59:18 | [diff] [blame] | 372 | HandleIdleSinceLastTransmission(false); |
| 373 | } |
| 374 | |
initial.commit | 09911bf | 2008-07-26 23:55:29 | [diff] [blame] | 375 | void MetricsService::RecordStartOfSessionEnd() { |
holte | 6d34116 | 2016-12-19 21:42:42 | [diff] [blame] | 376 | LogCleanShutdown(false); |
initial.commit | 09911bf | 2008-07-26 23:55:29 | [diff] [blame] | 377 | } |
| 378 | |
| 379 | void MetricsService::RecordCompletedSessionEnd() { |
holte | 6d34116 | 2016-12-19 21:42:42 | [diff] [blame] | 380 | LogCleanShutdown(true); |
initial.commit | 09911bf | 2008-07-26 23:55:29 | [diff] [blame] | 381 | } |
| 382 | |
[email protected] | 410938e0 | 2012-10-24 16:33:59 | [diff] [blame] | 383 | #if defined(OS_ANDROID) || defined(OS_IOS) |
[email protected] | 117fbdf2 | 2012-06-26 18:36:39 | [diff] [blame] | 384 | void MetricsService::OnAppEnterBackground() { |
holte | c1b9731 | 2017-02-24 21:37:10 | [diff] [blame] | 385 | rotation_scheduler_->Stop(); |
holte | a3b2411 | 2017-03-14 02:08:24 | [diff] [blame] | 386 | reporting_service_.Stop(); |
[email protected] | 117fbdf2 | 2012-06-26 18:36:39 | [diff] [blame] | 387 | |
Ilya Sherman | 6c6c833 | 2017-07-11 22:39:22 | [diff] [blame] | 388 | MarkAppCleanShutdownAndCommit(state_manager_->clean_exit_beacon(), |
| 389 | local_state_); |
[email protected] | 117fbdf2 | 2012-06-26 18:36:39 | [diff] [blame] | 390 | |
bmcquade | 6a49bed | 2016-07-27 19:25:56 | [diff] [blame] | 391 | // Give providers a chance to persist histograms as part of being |
| 392 | // backgrounded. |
Steven Holte | c35411dc | 2017-07-28 04:22:14 | [diff] [blame] | 393 | delegating_provider_.OnAppEnterBackground(); |
bmcquade | 6a49bed | 2016-07-27 19:25:56 | [diff] [blame] | 394 | |
[email protected] | 117fbdf2 | 2012-06-26 18:36:39 | [diff] [blame] | 395 | // At this point, there's no way of knowing when the process will be |
| 396 | // killed, so this has to be treated similar to a shutdown, closing and |
| 397 | // persisting all logs. Unlinke a shutdown, the state is primed to be ready |
| 398 | // to continue logging and uploading if the process does return. |
Steven Holte | 2c294a3 | 2015-03-12 21:45:03 | [diff] [blame] | 399 | if (recording_active() && state_ >= SENDING_LOGS) { |
[email protected] | 117fbdf2 | 2012-06-26 18:36:39 | [diff] [blame] | 400 | PushPendingLogsToPersistentStorage(); |
[email protected] | 410938e0 | 2012-10-24 16:33:59 | [diff] [blame] | 401 | // Persisting logs closes the current log, so start recording a new log |
| 402 | // immediately to capture any background work that might be done before the |
| 403 | // process is killed. |
| 404 | OpenNewLog(); |
[email protected] | 117fbdf2 | 2012-06-26 18:36:39 | [diff] [blame] | 405 | } |
[email protected] | 117fbdf2 | 2012-06-26 18:36:39 | [diff] [blame] | 406 | } |
| 407 | |
| 408 | void MetricsService::OnAppEnterForeground() { |
Ilya Sherman | 6c6c833 | 2017-07-11 22:39:22 | [diff] [blame] | 409 | state_manager_->clean_exit_beacon()->WriteBeaconValue(false); |
holte | a27eadf | 2017-01-26 01:58:59 | [diff] [blame] | 410 | ExecutionPhaseManager(local_state_).OnAppEnterForeground(); |
[email protected] | 117fbdf2 | 2012-06-26 18:36:39 | [diff] [blame] | 411 | StartSchedulerIfNecessary(); |
[email protected] | 117fbdf2 | 2012-06-26 18:36:39 | [diff] [blame] | 412 | } |
[email protected] | 84c384e | 2013-03-01 23:20:19 | [diff] [blame] | 413 | #else |
erikwright | cc98a7e0 | 2014-09-09 22:05:12 | [diff] [blame] | 414 | void MetricsService::LogNeedForCleanShutdown() { |
Ilya Sherman | 6c6c833 | 2017-07-11 22:39:22 | [diff] [blame] | 415 | state_manager_->clean_exit_beacon()->WriteBeaconValue(false); |
[email protected] | 84c384e | 2013-03-01 23:20:19 | [diff] [blame] | 416 | // Redundant setting to be sure we call for a clean shutdown. |
| 417 | clean_shutdown_status_ = NEED_TO_SHUTDOWN; |
| 418 | } |
| 419 | #endif // defined(OS_ANDROID) || defined(OS_IOS) |
[email protected] | 117fbdf2 | 2012-06-26 18:36:39 | [diff] [blame] | 420 | |
[email protected] | 6d67ea0d | 2013-11-14 11:02:21 | [diff] [blame] | 421 | // static |
[email protected] | 24f81ca | 2014-05-26 15:59:34 | [diff] [blame] | 422 | void MetricsService::SetExecutionPhase(ExecutionPhase execution_phase, |
| 423 | PrefService* local_state) { |
holte | a27eadf | 2017-01-26 01:58:59 | [diff] [blame] | 424 | ExecutionPhaseManager(local_state).SetExecutionPhase(execution_phase); |
[email protected] | 6d67ea0d | 2013-11-14 11:02:21 | [diff] [blame] | 425 | } |
| 426 | |
[email protected] | 7f7f196 | 2011-04-20 15:58:16 | [diff] [blame] | 427 | void MetricsService::RecordBreakpadRegistration(bool success) { |
holte | 1bf273c | 2017-02-23 00:22:28 | [diff] [blame] | 428 | StabilityMetricsProvider(local_state_).RecordBreakpadRegistration(success); |
[email protected] | e73c0197 | 2008-08-13 00:18:24 | [diff] [blame] | 429 | } |
| 430 | |
| 431 | void MetricsService::RecordBreakpadHasDebugger(bool has_debugger) { |
holte | 1bf273c | 2017-02-23 00:22:28 | [diff] [blame] | 432 | StabilityMetricsProvider(local_state_) |
| 433 | .RecordBreakpadHasDebugger(has_debugger); |
[email protected] | e73c0197 | 2008-08-13 00:18:24 | [diff] [blame] | 434 | } |
| 435 | |
yiyaoliu | 14ef3ead | 2014-11-19 02:36:50 | [diff] [blame] | 436 | void MetricsService::ClearSavedStabilityMetrics() { |
Steven Holte | c35411dc | 2017-07-28 04:22:14 | [diff] [blame] | 437 | delegating_provider_.ClearSavedStabilityMetrics(); |
yiyaoliu | 14ef3ead | 2014-11-19 02:36:50 | [diff] [blame] | 438 | } |
| 439 | |
olivierrobin | c3dfc5b | 2015-04-07 19:12:00 | [diff] [blame] | 440 | void MetricsService::PushExternalLog(const std::string& log) { |
holte | a3b2411 | 2017-03-14 02:08:24 | [diff] [blame] | 441 | log_store()->StoreLog(log, MetricsLog::ONGOING_LOG); |
olivierrobin | c3dfc5b | 2015-04-07 19:12:00 | [diff] [blame] | 442 | } |
| 443 | |
robliao | 7253fd2 | 2016-12-01 18:41:38 | [diff] [blame] | 444 | void MetricsService::UpdateMetricsUsagePrefs(const std::string& service_name, |
| 445 | int message_size, |
| 446 | bool is_cellular) { |
Steven Holte | 971b059 | 2017-10-12 15:28:26 | [diff] [blame] | 447 | DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); |
holte | a3b2411 | 2017-03-14 02:08:24 | [diff] [blame] | 448 | reporting_service_.UpdateMetricsUsagePrefs(service_name, message_size, |
| 449 | is_cellular); |
gayane | 0b46091c | 2016-04-07 21:01:05 | [diff] [blame] | 450 | } |
| 451 | |
initial.commit | 09911bf | 2008-07-26 23:55:29 | [diff] [blame] | 452 | //------------------------------------------------------------------------------ |
| 453 | // private methods |
| 454 | //------------------------------------------------------------------------------ |
| 455 | |
| 456 | |
| 457 | //------------------------------------------------------------------------------ |
| 458 | // Initialization methods |
| 459 | |
[email protected] | 3907664 | 2014-05-05 20:32:55 | [diff] [blame] | 460 | void MetricsService::InitializeMetricsState() { |
avi | 2606292 | 2015-12-26 00:14:18 | [diff] [blame] | 461 | const int64_t buildtime = MetricsLog::GetBuildTime(); |
asvitkine | ff3e2a6 | 2014-09-18 22:01:49 | [diff] [blame] | 462 | const std::string version = client_->GetVersionString(); |
holte | 57fcaed | 2017-01-23 22:14:31 | [diff] [blame] | 463 | |
asvitkine | ff3e2a6 | 2014-09-18 22:01:49 | [diff] [blame] | 464 | bool version_changed = false; |
holte | 1bf273c | 2017-02-23 00:22:28 | [diff] [blame] | 465 | EnvironmentRecorder recorder(local_state_); |
| 466 | int64_t previous_buildtime = recorder.GetLastBuildtime(); |
| 467 | std::string previous_version = recorder.GetLastVersion(); |
manzagop | ea99d195 | 2016-09-08 23:40:05 | [diff] [blame] | 468 | if (previous_buildtime != buildtime || previous_version != version) { |
holte | 1bf273c | 2017-02-23 00:22:28 | [diff] [blame] | 469 | recorder.SetBuildtimeAndVersion(buildtime, version); |
asvitkine | ff3e2a6 | 2014-09-18 22:01:49 | [diff] [blame] | 470 | version_changed = true; |
| 471 | } |
initial.commit | 09911bf | 2008-07-26 23:55:29 | [diff] [blame] | 472 | |
asvitkine | a63d19e | 2014-10-24 16:19:39 | [diff] [blame] | 473 | session_id_ = local_state_->GetInteger(prefs::kMetricsSessionID); |
erikwright | 65b58df | 2014-09-12 00:05:28 | [diff] [blame] | 474 | |
holte | 1bf273c | 2017-02-23 00:22:28 | [diff] [blame] | 475 | StabilityMetricsProvider provider(local_state_); |
Ilya Sherman | 6c6c833 | 2017-07-11 22:39:22 | [diff] [blame] | 476 | if (!state_manager_->clean_exit_beacon()->exited_cleanly()) { |
holte | 1bf273c | 2017-02-23 00:22:28 | [diff] [blame] | 477 | provider.LogCrash(); |
[email protected] | c0c55e9 | 2011-09-10 18:47:30 | [diff] [blame] | 478 | // Reset flag, and wait until we call LogNeedForCleanShutdown() before |
| 479 | // monitoring. |
Ilya Sherman | 6c6c833 | 2017-07-11 22:39:22 | [diff] [blame] | 480 | state_manager_->clean_exit_beacon()->WriteBeaconValue(true); |
holte | a27eadf | 2017-01-26 01:58:59 | [diff] [blame] | 481 | ExecutionPhaseManager manager(local_state_); |
manzagop | 7c14de2 | 2016-11-25 16:19:34 | [diff] [blame] | 482 | UMA_HISTOGRAM_SPARSE_SLOWLY("Chrome.Browser.CrashedExecutionPhase", |
holte | a27eadf | 2017-01-26 01:58:59 | [diff] [blame] | 483 | static_cast<int>(manager.GetExecutionPhase())); |
| 484 | manager.SetExecutionPhase(ExecutionPhase::UNINITIALIZED_PHASE); |
siggi | c179dd06 | 2014-09-10 17:02:31 | [diff] [blame] | 485 | } |
[email protected] | 6a6d0d1 | 2013-10-28 15:58:19 | [diff] [blame] | 486 | |
Steven Holte | c35411dc | 2017-07-28 04:22:14 | [diff] [blame] | 487 | // HasPreviousSessionData is called first to ensure it is never bypassed. |
manzagop | 780bb8b | 2016-10-21 14:21:16 | [diff] [blame] | 488 | const bool is_initial_stability_log_required = |
Steven Holte | c35411dc | 2017-07-28 04:22:14 | [diff] [blame] | 489 | delegating_provider_.HasPreviousSessionData() || |
Ilya Sherman | 6c6c833 | 2017-07-11 22:39:22 | [diff] [blame] | 490 | !state_manager_->clean_exit_beacon()->exited_cleanly(); |
Steven Holte | 2c294a3 | 2015-03-12 21:45:03 | [diff] [blame] | 491 | bool has_initial_stability_log = false; |
manzagop | 780bb8b | 2016-10-21 14:21:16 | [diff] [blame] | 492 | if (is_initial_stability_log_required) { |
siggi | c179dd06 | 2014-09-10 17:02:31 | [diff] [blame] | 493 | // If the previous session didn't exit cleanly, or if any provider |
| 494 | // explicitly requests it, prepare an initial stability log - |
| 495 | // provided UMA is enabled. |
manzagop | ea99d195 | 2016-09-08 23:40:05 | [diff] [blame] | 496 | if (state_manager_->IsMetricsReportingEnabled()) { |
| 497 | has_initial_stability_log = PrepareInitialStabilityLog(previous_version); |
| 498 | if (!has_initial_stability_log) |
holte | 1bf273c | 2017-02-23 00:22:28 | [diff] [blame] | 499 | provider.LogStabilityLogDeferred(); |
manzagop | ea99d195 | 2016-09-08 23:40:05 | [diff] [blame] | 500 | } |
initial.commit | 09911bf | 2008-07-26 23:55:29 | [diff] [blame] | 501 | } |
[email protected] | 80a8f31 | 2013-12-16 18:00:30 | [diff] [blame] | 502 | |
manzagop | 780bb8b | 2016-10-21 14:21:16 | [diff] [blame] | 503 | // If the version changed, but no initial stability log was generated, clear |
| 504 | // the stability stats from the previous version (so that they don't get |
asvitkine | ff3e2a6 | 2014-09-18 22:01:49 | [diff] [blame] | 505 | // attributed to the current version). This could otherwise happen due to a |
| 506 | // number of different edge cases, such as if the last version crashed before |
| 507 | // it could save off a system profile or if UMA reporting is disabled (which |
| 508 | // normally results in stats being accumulated). |
manzagop | 780bb8b | 2016-10-21 14:21:16 | [diff] [blame] | 509 | if (version_changed && !has_initial_stability_log) { |
yiyaoliu | 14ef3ead | 2014-11-19 02:36:50 | [diff] [blame] | 510 | ClearSavedStabilityMetrics(); |
holte | 1bf273c | 2017-02-23 00:22:28 | [diff] [blame] | 511 | provider.LogStabilityDataDiscarded(); |
manzagop | ea99d195 | 2016-09-08 23:40:05 | [diff] [blame] | 512 | } |
asvitkine | ff3e2a6 | 2014-09-18 22:01:49 | [diff] [blame] | 513 | |
manzagop | 780bb8b | 2016-10-21 14:21:16 | [diff] [blame] | 514 | // If the version changed, the system profile is obsolete and needs to be |
| 515 | // cleared. This is to avoid the stability data misattribution that could |
| 516 | // occur if the current version crashed before saving its own system profile. |
| 517 | // Note however this clearing occurs only after preparing the initial |
| 518 | // stability log, an operation that requires the previous version's system |
| 519 | // profile. At this point, stability metrics pertaining to the previous |
| 520 | // version have been cleared. |
holte | 1bf273c | 2017-02-23 00:22:28 | [diff] [blame] | 521 | if (version_changed) |
| 522 | recorder.ClearEnvironmentFromPrefs(); |
manzagop | 780bb8b | 2016-10-21 14:21:16 | [diff] [blame] | 523 | |
[email protected] | 80a8f31 | 2013-12-16 18:00:30 | [diff] [blame] | 524 | // Update session ID. |
| 525 | ++session_id_; |
asvitkine | a63d19e | 2014-10-24 16:19:39 | [diff] [blame] | 526 | local_state_->SetInteger(prefs::kMetricsSessionID, session_id_); |
[email protected] | 80a8f31 | 2013-12-16 18:00:30 | [diff] [blame] | 527 | |
holte | 1bf273c | 2017-02-23 00:22:28 | [diff] [blame] | 528 | // Notify stability metrics providers about the launch. |
| 529 | provider.LogLaunch(); |
holte | a27eadf | 2017-01-26 01:58:59 | [diff] [blame] | 530 | SetExecutionPhase(ExecutionPhase::START_METRICS_RECORDING, local_state_); |
holte | 1bf273c | 2017-02-23 00:22:28 | [diff] [blame] | 531 | provider.CheckLastSessionEndCompleted(); |
initial.commit | 09911bf | 2008-07-26 23:55:29 | [diff] [blame] | 532 | |
[email protected] | 076961c | 2014-03-12 22:23:56 | [diff] [blame] | 533 | // Call GetUptimes() for the first time, thus allowing all later calls |
| 534 | // to record incremental uptimes accurately. |
| 535 | base::TimeDelta ignored_uptime_parameter; |
| 536 | base::TimeDelta startup_uptime; |
[email protected] | 24f81ca | 2014-05-26 15:59:34 | [diff] [blame] | 537 | GetUptimes(local_state_, &startup_uptime, &ignored_uptime_parameter); |
[email protected] | c68a2b9b | 2013-10-09 18:16:36 | [diff] [blame] | 538 | DCHECK_EQ(0, startup_uptime.InMicroseconds()); |
[email protected] | 0bb1a62 | 2009-03-04 03:22:32 | [diff] [blame] | 539 | |
| 540 | // Bookkeeping for the uninstall metrics. |
asvitkine | a63d19e | 2014-10-24 16:19:39 | [diff] [blame] | 541 | IncrementLongPrefsValue(prefs::kUninstallLaunchCount); |
initial.commit | 09911bf | 2008-07-26 23:55:29 | [diff] [blame] | 542 | } |
| 543 | |
[email protected] | dd98f39 | 2013-02-04 13:03:22 | [diff] [blame] | 544 | void MetricsService::OnUserAction(const std::string& action) { |
[email protected] | 4426d2d | 2014-04-09 12:33:00 | [diff] [blame] | 545 | log_manager_.current_log()->RecordUserAction(action); |
[email protected] | dd98f39 | 2013-02-04 13:03:22 | [diff] [blame] | 546 | HandleIdleSinceLastTransmission(false); |
| 547 | } |
| 548 | |
isherman | b670568 | 2015-08-29 00:01:00 | [diff] [blame] | 549 | void MetricsService::FinishedInitTask() { |
[email protected] | ed0fd00 | 2012-04-25 23:10:34 | [diff] [blame] | 550 | DCHECK_EQ(INIT_TASK_SCHEDULED, state_); |
[email protected] | c68a2b9b | 2013-10-09 18:16:36 | [diff] [blame] | 551 | state_ = INIT_TASK_DONE; |
[email protected] | 83d09f9 | 2014-06-03 14:58:26 | [diff] [blame] | 552 | |
| 553 | // Create the initial log. |
| 554 | if (!initial_metrics_log_.get()) { |
| 555 | initial_metrics_log_ = CreateLog(MetricsLog::ONGOING_LOG); |
Steven Holte | c35411dc | 2017-07-28 04:22:14 | [diff] [blame] | 556 | delegating_provider_.OnDidCreateMetricsLog(); |
[email protected] | 83d09f9 | 2014-06-03 14:58:26 | [diff] [blame] | 557 | } |
| 558 | |
holte | c1b9731 | 2017-02-24 21:37:10 | [diff] [blame] | 559 | rotation_scheduler_->InitTaskComplete(); |
[email protected] | c68a2b9b | 2013-10-09 18:16:36 | [diff] [blame] | 560 | } |
| 561 | |
[email protected] | 076961c | 2014-03-12 22:23:56 | [diff] [blame] | 562 | void MetricsService::GetUptimes(PrefService* pref, |
| 563 | base::TimeDelta* incremental_uptime, |
| 564 | base::TimeDelta* uptime) { |
[email protected] | c68a2b9b | 2013-10-09 18:16:36 | [diff] [blame] | 565 | base::TimeTicks now = base::TimeTicks::Now(); |
[email protected] | 076961c | 2014-03-12 22:23:56 | [diff] [blame] | 566 | // If this is the first call, init |first_updated_time_| and |
| 567 | // |last_updated_time_|. |
| 568 | if (last_updated_time_.is_null()) { |
| 569 | first_updated_time_ = now; |
[email protected] | c68a2b9b | 2013-10-09 18:16:36 | [diff] [blame] | 570 | last_updated_time_ = now; |
[email protected] | 076961c | 2014-03-12 22:23:56 | [diff] [blame] | 571 | } |
| 572 | *incremental_uptime = now - last_updated_time_; |
| 573 | *uptime = now - first_updated_time_; |
[email protected] | c68a2b9b | 2013-10-09 18:16:36 | [diff] [blame] | 574 | last_updated_time_ = now; |
| 575 | |
avi | 2606292 | 2015-12-26 00:14:18 | [diff] [blame] | 576 | const int64_t incremental_time_secs = incremental_uptime->InSeconds(); |
[email protected] | c68a2b9b | 2013-10-09 18:16:36 | [diff] [blame] | 577 | if (incremental_time_secs > 0) { |
avi | 2606292 | 2015-12-26 00:14:18 | [diff] [blame] | 578 | int64_t metrics_uptime = pref->GetInt64(prefs::kUninstallMetricsUptimeSec); |
[email protected] | c68a2b9b | 2013-10-09 18:16:36 | [diff] [blame] | 579 | metrics_uptime += incremental_time_secs; |
asvitkine | a63d19e | 2014-10-24 16:19:39 | [diff] [blame] | 580 | pref->SetInt64(prefs::kUninstallMetricsUptimeSec, metrics_uptime); |
[email protected] | c68a2b9b | 2013-10-09 18:16:36 | [diff] [blame] | 581 | } |
initial.commit | 09911bf | 2008-07-26 23:55:29 | [diff] [blame] | 582 | } |
| 583 | |
initial.commit | 09911bf | 2008-07-26 23:55:29 | [diff] [blame] | 584 | //------------------------------------------------------------------------------ |
| 585 | // Recording control methods |
| 586 | |
[email protected] | 410938e0 | 2012-10-24 16:33:59 | [diff] [blame] | 587 | void MetricsService::OpenNewLog() { |
| 588 | DCHECK(!log_manager_.current_log()); |
initial.commit | 09911bf | 2008-07-26 23:55:29 | [diff] [blame] | 589 | |
[email protected] | bfb77b5 | 2014-06-07 01:54:01 | [diff] [blame] | 590 | log_manager_.BeginLoggingWithLog(CreateLog(MetricsLog::ONGOING_LOG)); |
Steven Holte | c35411dc | 2017-07-28 04:22:14 | [diff] [blame] | 591 | delegating_provider_.OnDidCreateMetricsLog(); |
initial.commit | 09911bf | 2008-07-26 23:55:29 | [diff] [blame] | 592 | if (state_ == INITIALIZED) { |
| 593 | // We only need to schedule that run once. |
[email protected] | 85ed9d4 | 2010-06-08 22:37:44 | [diff] [blame] | 594 | state_ = INIT_TASK_SCHEDULED; |
initial.commit | 09911bf | 2008-07-26 23:55:29 | [diff] [blame] | 595 | |
Steven Holte | 971b059 | 2017-10-12 15:28:26 | [diff] [blame] | 596 | base::SequencedTaskRunnerHandle::Get()->PostDelayedTask( |
| 597 | FROM_HERE, |
| 598 | base::Bind(&MetricsService::StartInitTask, |
| 599 | self_ptr_factory_.GetWeakPtr()), |
[email protected] | 7e56010 | 2012-03-08 20:58:42 | [diff] [blame] | 600 | base::TimeDelta::FromSeconds(kInitializationDelaySeconds)); |
bcwhite | 8e72aa59 | 2017-06-09 18:59:18 | [diff] [blame] | 601 | |
Steven Holte | 971b059 | 2017-10-12 15:28:26 | [diff] [blame] | 602 | base::SequencedTaskRunnerHandle::Get()->PostDelayedTask( |
bcwhite | 8e72aa59 | 2017-06-09 18:59:18 | [diff] [blame] | 603 | FROM_HERE, |
| 604 | base::Bind(&MetricsService::PrepareProviderMetricsTask, |
| 605 | self_ptr_factory_.GetWeakPtr()), |
| 606 | base::TimeDelta::FromSeconds(2 * kInitializationDelaySeconds)); |
initial.commit | 09911bf | 2008-07-26 23:55:29 | [diff] [blame] | 607 | } |
initial.commit | 09911bf | 2008-07-26 23:55:29 | [diff] [blame] | 608 | } |
| 609 | |
isherman | b670568 | 2015-08-29 00:01:00 | [diff] [blame] | 610 | void MetricsService::StartInitTask() { |
Steven Holte | c35411dc | 2017-07-28 04:22:14 | [diff] [blame] | 611 | delegating_provider_.AsyncInit(base::Bind(&MetricsService::FinishedInitTask, |
Steven Holte | 915c99f | 2017-07-21 23:34:31 | [diff] [blame] | 612 | self_ptr_factory_.GetWeakPtr())); |
[email protected] | 51994b2 | 2014-05-30 13:24:21 | [diff] [blame] | 613 | } |
| 614 | |
[email protected] | 410938e0 | 2012-10-24 16:33:59 | [diff] [blame] | 615 | void MetricsService::CloseCurrentLog() { |
[email protected] | cac267c | 2011-09-29 15:18:10 | [diff] [blame] | 616 | if (!log_manager_.current_log()) |
initial.commit | 09911bf | 2008-07-26 23:55:29 | [diff] [blame] | 617 | return; |
| 618 | |
bcwhite | 5cb99eb | 2016-02-01 21:07:56 | [diff] [blame] | 619 | // If a persistent allocator is in use, update its internal histograms (such |
| 620 | // as how much memory is being used) before reporting. |
bcwhite | 33d95806a | 2016-03-16 02:37:45 | [diff] [blame] | 621 | base::PersistentHistogramAllocator* allocator = |
bcwhite | 5e748c6 | 2016-04-06 02:03:53 | [diff] [blame] | 622 | base::GlobalHistogramAllocator::Get(); |
bcwhite | 5cb99eb | 2016-02-01 21:07:56 | [diff] [blame] | 623 | if (allocator) |
| 624 | allocator->UpdateTrackingHistograms(); |
| 625 | |
[email protected] | 0b33f80b | 2008-12-17 21:34:36 | [diff] [blame] | 626 | // Put incremental data (histogram deltas, and realtime stats deltas) at the |
[email protected] | 147bbc0b | 2009-01-06 19:37:40 | [diff] [blame] | 627 | // end of all log transmissions (initial log handles this separately). |
[email protected] | 024b5cd | 2011-05-27 03:29:38 | [diff] [blame] | 628 | // RecordIncrementalStabilityElements only exists on the derived |
| 629 | // MetricsLog class. |
[email protected] | 94dce12 | 2014-07-16 04:20:12 | [diff] [blame] | 630 | MetricsLog* current_log = log_manager_.current_log(); |
[email protected] | 024b5cd | 2011-05-27 03:29:38 | [diff] [blame] | 631 | DCHECK(current_log); |
asvitkine | 88aa933 | 2014-09-29 23:29:17 | [diff] [blame] | 632 | RecordCurrentEnvironment(current_log); |
[email protected] | 076961c | 2014-03-12 22:23:56 | [diff] [blame] | 633 | base::TimeDelta incremental_uptime; |
| 634 | base::TimeDelta uptime; |
[email protected] | 24f81ca | 2014-05-26 15:59:34 | [diff] [blame] | 635 | GetUptimes(local_state_, &incremental_uptime, &uptime); |
Steven Holte | c35411dc | 2017-07-28 04:22:14 | [diff] [blame] | 636 | current_log->RecordCurrentSessionData(&delegating_provider_, |
| 637 | incremental_uptime, uptime); |
mariakhomenko | 19102898 | 2014-10-20 23:22:56 | [diff] [blame] | 638 | RecordCurrentHistograms(); |
rkaplow | 78985a0 | 2017-06-05 16:13:19 | [diff] [blame] | 639 | current_log->TruncateEvents(); |
holte | 6e36a3d | 2017-02-02 22:41:10 | [diff] [blame] | 640 | DVLOG(1) << "Generated an ongoing log."; |
holte | a3b2411 | 2017-03-14 02:08:24 | [diff] [blame] | 641 | log_manager_.FinishCurrentLog(log_store()); |
initial.commit | 09911bf | 2008-07-26 23:55:29 | [diff] [blame] | 642 | } |
| 643 | |
[email protected] | cac267c | 2011-09-29 15:18:10 | [diff] [blame] | 644 | void MetricsService::PushPendingLogsToPersistentStorage() { |
Steven Holte | 2c294a3 | 2015-03-12 21:45:03 | [diff] [blame] | 645 | if (state_ < SENDING_LOGS) |
[email protected] | 28ab7f9 | 2009-01-06 21:39:04 | [diff] [blame] | 646 | 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] | 647 | |
[email protected] | 410938e0 | 2012-10-24 16:33:59 | [diff] [blame] | 648 | CloseCurrentLog(); |
holte | a3b2411 | 2017-03-14 02:08:24 | [diff] [blame] | 649 | log_store()->PersistUnsentLogs(); |
initial.commit | 09911bf | 2008-07-26 23:55:29 | [diff] [blame] | 650 | } |
| 651 | |
| 652 | //------------------------------------------------------------------------------ |
| 653 | // Transmission of logs methods |
| 654 | |
[email protected] | 7f7f196 | 2011-04-20 15:58:16 | [diff] [blame] | 655 | void MetricsService::StartSchedulerIfNecessary() { |
[email protected] | 410938e0 | 2012-10-24 16:33:59 | [diff] [blame] | 656 | // Never schedule cutting or uploading of logs in test mode. |
| 657 | if (test_mode_active_) |
| 658 | return; |
| 659 | |
| 660 | // Even if reporting is disabled, the scheduler is needed to trigger the |
| 661 | // creation of the initial log, which must be done in order for any logs to be |
| 662 | // persisted on shutdown or backgrounding. |
[email protected] | 80a8f31 | 2013-12-16 18:00:30 | [diff] [blame] | 663 | if (recording_active() && |
Steven Holte | 2c294a3 | 2015-03-12 21:45:03 | [diff] [blame] | 664 | (reporting_active() || state_ < SENDING_LOGS)) { |
holte | c1b9731 | 2017-02-24 21:37:10 | [diff] [blame] | 665 | rotation_scheduler_->Start(); |
holte | a3b2411 | 2017-03-14 02:08:24 | [diff] [blame] | 666 | reporting_service_.Start(); |
[email protected] | 80a8f31 | 2013-12-16 18:00:30 | [diff] [blame] | 667 | } |
initial.commit | 09911bf | 2008-07-26 23:55:29 | [diff] [blame] | 668 | } |
| 669 | |
[email protected] | 7f7f196 | 2011-04-20 15:58:16 | [diff] [blame] | 670 | void MetricsService::StartScheduledUpload() { |
holte | 6e36a3d | 2017-02-02 22:41:10 | [diff] [blame] | 671 | DVLOG(1) << "StartScheduledUpload"; |
holte | a6a3917 | 2015-03-25 19:57:20 | [diff] [blame] | 672 | DCHECK(state_ >= INIT_TASK_DONE); |
Brian White | 8050710b | 2017-08-30 13:58:04 | [diff] [blame] | 673 | |
[email protected] | cd1ac71 | 2012-06-26 08:26:47 | [diff] [blame] | 674 | // If we're getting no notifications, then the log won't have much in it, and |
| 675 | // it's possible the computer is about to go to sleep, so don't upload and |
| 676 | // stop the scheduler. |
[email protected] | 410938e0 | 2012-10-24 16:33:59 | [diff] [blame] | 677 | // If recording has been turned off, the scheduler doesn't need to run. |
| 678 | // If reporting is off, proceed if the initial log hasn't been created, since |
| 679 | // 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] | 680 | // TODO(stuartmorgan): Call Stop() on the scheduler when reporting and/or |
[email protected] | cd1ac71 | 2012-06-26 08:26:47 | [diff] [blame] | 681 | // recording are turned off instead of letting it fire and then aborting. |
| 682 | if (idle_since_last_transmission_ || |
[email protected] | 410938e0 | 2012-10-24 16:33:59 | [diff] [blame] | 683 | !recording_active() || |
Steven Holte | 2c294a3 | 2015-03-12 21:45:03 | [diff] [blame] | 684 | (!reporting_active() && state_ >= SENDING_LOGS)) { |
holte | c1b9731 | 2017-02-24 21:37:10 | [diff] [blame] | 685 | rotation_scheduler_->Stop(); |
| 686 | rotation_scheduler_->RotationFinished(); |
[email protected] | 7f7f196 | 2011-04-20 15:58:16 | [diff] [blame] | 687 | return; |
| 688 | } |
| 689 | |
[email protected] | cd1ac71 | 2012-06-26 08:26:47 | [diff] [blame] | 690 | // If there are unsent logs, send the next one. If not, start the asynchronous |
| 691 | // process of finalizing the current log for upload. |
holte | a3b2411 | 2017-03-14 02:08:24 | [diff] [blame] | 692 | if (state_ == SENDING_LOGS && has_unsent_logs()) { |
| 693 | reporting_service_.Start(); |
holte | c1b9731 | 2017-02-24 21:37:10 | [diff] [blame] | 694 | rotation_scheduler_->RotationFinished(); |
[email protected] | cd1ac71 | 2012-06-26 08:26:47 | [diff] [blame] | 695 | } else { |
holte | a6a3917 | 2015-03-25 19:57:20 | [diff] [blame] | 696 | // There are no logs left to send, so start creating a new one. |
isherman | b670568 | 2015-08-29 00:01:00 | [diff] [blame] | 697 | client_->CollectFinalMetricsForLog( |
[email protected] | 4b4892b | 2014-05-22 15:06:15 | [diff] [blame] | 698 | base::Bind(&MetricsService::OnFinalLogInfoCollectionDone, |
| 699 | self_ptr_factory_.GetWeakPtr())); |
[email protected] | cd1ac71 | 2012-06-26 08:26:47 | [diff] [blame] | 700 | } |
[email protected] | 2994826 | 2012-03-01 12:15:08 | [diff] [blame] | 701 | } |
| 702 | |
[email protected] | 2994826 | 2012-03-01 12:15:08 | [diff] [blame] | 703 | void MetricsService::OnFinalLogInfoCollectionDone() { |
holte | 6e36a3d | 2017-02-02 22:41:10 | [diff] [blame] | 704 | DVLOG(1) << "OnFinalLogInfoCollectionDone"; |
Brian White | 8050710b | 2017-08-30 13:58:04 | [diff] [blame] | 705 | |
[email protected] | cd1ac71 | 2012-06-26 08:26:47 | [diff] [blame] | 706 | // Abort if metrics were turned off during the final info gathering. |
[email protected] | 410938e0 | 2012-10-24 16:33:59 | [diff] [blame] | 707 | if (!recording_active()) { |
holte | c1b9731 | 2017-02-24 21:37:10 | [diff] [blame] | 708 | rotation_scheduler_->Stop(); |
| 709 | rotation_scheduler_->RotationFinished(); |
[email protected] | d01b873 | 2008-10-16 02:18:07 | [diff] [blame] | 710 | return; |
| 711 | } |
| 712 | |
holte | a6a3917 | 2015-03-25 19:57:20 | [diff] [blame] | 713 | if (state_ == INIT_TASK_DONE) { |
| 714 | PrepareInitialMetricsLog(); |
| 715 | } else { |
| 716 | DCHECK_EQ(SENDING_LOGS, state_); |
| 717 | CloseCurrentLog(); |
| 718 | OpenNewLog(); |
| 719 | } |
holte | a3b2411 | 2017-03-14 02:08:24 | [diff] [blame] | 720 | reporting_service_.Start(); |
holte | c1b9731 | 2017-02-24 21:37:10 | [diff] [blame] | 721 | rotation_scheduler_->RotationFinished(); |
holte | a3b2411 | 2017-03-14 02:08:24 | [diff] [blame] | 722 | HandleIdleSinceLastTransmission(true); |
[email protected] | 2994826 | 2012-03-01 12:15:08 | [diff] [blame] | 723 | } |
| 724 | |
manzagop | ea99d195 | 2016-09-08 23:40:05 | [diff] [blame] | 725 | bool MetricsService::PrepareInitialStabilityLog( |
| 726 | const std::string& prefs_previous_version) { |
[email protected] | 80a8f31 | 2013-12-16 18:00:30 | [diff] [blame] | 727 | DCHECK_EQ(INITIALIZED, state_); |
[email protected] | 2994826 | 2012-03-01 12:15:08 | [diff] [blame] | 728 | |
dcheng | d99c42a | 2016-04-21 21:54:13 | [diff] [blame] | 729 | std::unique_ptr<MetricsLog> initial_stability_log( |
[email protected] | 09dee82d | 2014-05-22 14:00:53 | [diff] [blame] | 730 | CreateLog(MetricsLog::INITIAL_STABILITY_LOG)); |
[email protected] | 2a321de3 | 2014-05-10 19:59:06 | [diff] [blame] | 731 | |
Steven Holte | c35411dc | 2017-07-28 04:22:14 | [diff] [blame] | 732 | // Do not call OnDidCreateMetricsLog here because the stability |
[email protected] | 2a321de3 | 2014-05-10 19:59:06 | [diff] [blame] | 733 | // log describes stats from the _previous_ session. |
manzagop | ea99d195 | 2016-09-08 23:40:05 | [diff] [blame] | 734 | std::string system_profile_app_version; |
| 735 | if (!initial_stability_log->LoadSavedEnvironmentFromPrefs( |
Steven Holte | d0429a70 | 2017-08-03 08:56:17 | [diff] [blame] | 736 | local_state_, &system_profile_app_version)) { |
Steven Holte | 2c294a3 | 2015-03-12 21:45:03 | [diff] [blame] | 737 | return false; |
manzagop | ea99d195 | 2016-09-08 23:40:05 | [diff] [blame] | 738 | } |
| 739 | if (system_profile_app_version != prefs_previous_version) |
holte | 1bf273c | 2017-02-23 00:22:28 | [diff] [blame] | 740 | StabilityMetricsProvider(local_state_).LogStabilityVersionMismatch(); |
[email protected] | 85791b0b | 2014-05-20 15:18:58 | [diff] [blame] | 741 | |
[email protected] | 80a8f31 | 2013-12-16 18:00:30 | [diff] [blame] | 742 | log_manager_.PauseCurrentLog(); |
dcheng | 5160635 | 2015-12-26 21:16:23 | [diff] [blame] | 743 | log_manager_.BeginLoggingWithLog(std::move(initial_stability_log)); |
[email protected] | 85791b0b | 2014-05-20 15:18:58 | [diff] [blame] | 744 | |
| 745 | // Note: Some stability providers may record stability stats via histograms, |
| 746 | // so this call has to be after BeginLoggingWithLog(). |
Steven Holte | c35411dc | 2017-07-28 04:22:14 | [diff] [blame] | 747 | log_manager_.current_log()->RecordPreviousSessionData(&delegating_provider_); |
[email protected] | c778687a | 2014-02-11 14:46:45 | [diff] [blame] | 748 | RecordCurrentStabilityHistograms(); |
[email protected] | 85791b0b | 2014-05-20 15:18:58 | [diff] [blame] | 749 | |
holte | 6e36a3d | 2017-02-02 22:41:10 | [diff] [blame] | 750 | DVLOG(1) << "Generated an stability log."; |
holte | a3b2411 | 2017-03-14 02:08:24 | [diff] [blame] | 751 | log_manager_.FinishCurrentLog(log_store()); |
[email protected] | 80a8f31 | 2013-12-16 18:00:30 | [diff] [blame] | 752 | log_manager_.ResumePausedLog(); |
| 753 | |
| 754 | // Store unsent logs, including the stability log that was just saved, so |
| 755 | // that they're not lost in case of a crash before upload time. |
holte | a3b2411 | 2017-03-14 02:08:24 | [diff] [blame] | 756 | log_store()->PersistUnsentLogs(); |
[email protected] | 80a8f31 | 2013-12-16 18:00:30 | [diff] [blame] | 757 | |
Steven Holte | 2c294a3 | 2015-03-12 21:45:03 | [diff] [blame] | 758 | return true; |
[email protected] | 80a8f31 | 2013-12-16 18:00:30 | [diff] [blame] | 759 | } |
| 760 | |
[email protected] | b58b8b2 | 2014-04-08 22:40:33 | [diff] [blame] | 761 | void MetricsService::PrepareInitialMetricsLog() { |
Steven Holte | 2c294a3 | 2015-03-12 21:45:03 | [diff] [blame] | 762 | DCHECK_EQ(INIT_TASK_DONE, state_); |
[email protected] | 0edf876 | 2013-11-21 18:33:30 | [diff] [blame] | 763 | |
asvitkine | 88aa933 | 2014-09-29 23:29:17 | [diff] [blame] | 764 | RecordCurrentEnvironment(initial_metrics_log_.get()); |
[email protected] | 076961c | 2014-03-12 22:23:56 | [diff] [blame] | 765 | base::TimeDelta incremental_uptime; |
| 766 | base::TimeDelta uptime; |
[email protected] | 24f81ca | 2014-05-26 15:59:34 | [diff] [blame] | 767 | GetUptimes(local_state_, &incremental_uptime, &uptime); |
[email protected] | 2994826 | 2012-03-01 12:15:08 | [diff] [blame] | 768 | |
| 769 | // Histograms only get written to the current log, so make the new log current |
| 770 | // before writing them. |
| 771 | log_manager_.PauseCurrentLog(); |
dcheng | 5160635 | 2015-12-26 21:16:23 | [diff] [blame] | 772 | log_manager_.BeginLoggingWithLog(std::move(initial_metrics_log_)); |
[email protected] | 85791b0b | 2014-05-20 15:18:58 | [diff] [blame] | 773 | |
| 774 | // Note: Some stability providers may record stability stats via histograms, |
| 775 | // so this call has to be after BeginLoggingWithLog(). |
Steven Holte | 631803df | 2017-07-24 23:40:34 | [diff] [blame] | 776 | log_manager_.current_log()->RecordCurrentSessionData( |
Steven Holte | c35411dc | 2017-07-28 04:22:14 | [diff] [blame] | 777 | &delegating_provider_, base::TimeDelta(), base::TimeDelta()); |
mariakhomenko | 19102898 | 2014-10-20 23:22:56 | [diff] [blame] | 778 | RecordCurrentHistograms(); |
[email protected] | 85791b0b | 2014-05-20 15:18:58 | [diff] [blame] | 779 | |
holte | 6e36a3d | 2017-02-02 22:41:10 | [diff] [blame] | 780 | DVLOG(1) << "Generated an initial log."; |
holte | a3b2411 | 2017-03-14 02:08:24 | [diff] [blame] | 781 | log_manager_.FinishCurrentLog(log_store()); |
[email protected] | 2994826 | 2012-03-01 12:15:08 | [diff] [blame] | 782 | log_manager_.ResumePausedLog(); |
| 783 | |
[email protected] | 94dce12 | 2014-07-16 04:20:12 | [diff] [blame] | 784 | // Store unsent logs, including the initial log that was just saved, so |
| 785 | // that they're not lost in case of a crash before upload time. |
holte | a3b2411 | 2017-03-14 02:08:24 | [diff] [blame] | 786 | log_store()->PersistUnsentLogs(); |
holte | a6a3917 | 2015-03-25 19:57:20 | [diff] [blame] | 787 | |
| 788 | state_ = SENDING_LOGS; |
[email protected] | 2994826 | 2012-03-01 12:15:08 | [diff] [blame] | 789 | } |
| 790 | |
[email protected] | 57ecc4b | 2010-08-11 03:02:51 | [diff] [blame] | 791 | void MetricsService::IncrementLongPrefsValue(const char* path) { |
avi | 2606292 | 2015-12-26 00:14:18 | [diff] [blame] | 792 | int64_t value = local_state_->GetInt64(path); |
[email protected] | 24f81ca | 2014-05-26 15:59:34 | [diff] [blame] | 793 | local_state_->SetInt64(path, value + 1); |
[email protected] | 0bb1a62 | 2009-03-04 03:22:32 | [diff] [blame] | 794 | } |
| 795 | |
[email protected] | c0c55e9 | 2011-09-10 18:47:30 | [diff] [blame] | 796 | bool MetricsService::UmaMetricsProperlyShutdown() { |
| 797 | CHECK(clean_shutdown_status_ == CLEANLY_SHUTDOWN || |
| 798 | clean_shutdown_status_ == NEED_TO_SHUTDOWN); |
| 799 | return clean_shutdown_status_ == CLEANLY_SHUTDOWN; |
| 800 | } |
| 801 | |
[email protected] | 85791b0b | 2014-05-20 15:18:58 | [diff] [blame] | 802 | void MetricsService::RegisterMetricsProvider( |
dcheng | d99c42a | 2016-04-21 21:54:13 | [diff] [blame] | 803 | std::unique_ptr<MetricsProvider> provider) { |
[email protected] | 85791b0b | 2014-05-20 15:18:58 | [diff] [blame] | 804 | DCHECK_EQ(INITIALIZED, state_); |
Steven Holte | c35411dc | 2017-07-28 04:22:14 | [diff] [blame] | 805 | delegating_provider_.RegisterMetricsProvider(std::move(provider)); |
[email protected] | 85791b0b | 2014-05-20 15:18:58 | [diff] [blame] | 806 | } |
| 807 | |
Gabriel Charette | 45f796f | 2017-07-12 07:00:54 | [diff] [blame] | 808 | void MetricsService::CheckForClonedInstall() { |
| 809 | state_manager_->CheckForClonedInstall(); |
[email protected] | 99c892d | 2014-03-24 18:11:21 | [diff] [blame] | 810 | } |
| 811 | |
dcheng | d99c42a | 2016-04-21 21:54:13 | [diff] [blame] | 812 | std::unique_ptr<MetricsLog> MetricsService::CreateLog( |
| 813 | MetricsLog::LogType log_type) { |
ricea | 85ec5795 | 2016-08-31 09:34:10 | [diff] [blame] | 814 | return base::MakeUnique<MetricsLog>(state_manager_->client_id(), session_id_, |
Steven Holte | d0429a70 | 2017-08-03 08:56:17 | [diff] [blame] | 815 | log_type, client_); |
| 816 | } |
| 817 | |
| 818 | std::string MetricsService::RecordCurrentEnvironmentHelper( |
| 819 | MetricsLog* log, |
| 820 | PrefService* local_state, |
Steven Holte | 8e9db0ca | 2017-08-11 01:20:08 | [diff] [blame] | 821 | DelegatingProvider* delegating_provider) { |
Steven Holte | d0429a70 | 2017-08-03 08:56:17 | [diff] [blame] | 822 | const SystemProfileProto& system_profile = |
Steven Holte | 8e9db0ca | 2017-08-11 01:20:08 | [diff] [blame] | 823 | log->RecordEnvironment(delegating_provider); |
Steven Holte | d0429a70 | 2017-08-03 08:56:17 | [diff] [blame] | 824 | EnvironmentRecorder recorder(local_state); |
| 825 | return recorder.SerializeAndRecordEnvironmentToPrefs(system_profile); |
[email protected] | 09dee82d | 2014-05-22 14:00:53 | [diff] [blame] | 826 | } |
| 827 | |
asvitkine | 88aa933 | 2014-09-29 23:29:17 | [diff] [blame] | 828 | void MetricsService::RecordCurrentEnvironment(MetricsLog* log) { |
manzagop | a5d6688d | 2016-10-25 20:16:03 | [diff] [blame] | 829 | DCHECK(client_); |
Steven Holte | 8e9db0ca | 2017-08-11 01:20:08 | [diff] [blame] | 830 | std::string serialized_proto = |
| 831 | RecordCurrentEnvironmentHelper(log, local_state_, &delegating_provider_); |
Steven Holte | d0429a70 | 2017-08-03 08:56:17 | [diff] [blame] | 832 | GlobalPersistentSystemProfile::GetInstance()->SetSystemProfile( |
| 833 | serialized_proto, /*complete=*/true); |
| 834 | client_->OnEnvironmentUpdate(&serialized_proto); |
asvitkine | 88aa933 | 2014-09-29 23:29:17 | [diff] [blame] | 835 | } |
| 836 | |
[email protected] | acc2ce551 | 2014-05-22 18:29:13 | [diff] [blame] | 837 | void MetricsService::RecordCurrentHistograms() { |
| 838 | DCHECK(log_manager_.current_log()); |
bcwhite | 9556e817 | 2016-06-10 19:55:04 | [diff] [blame] | 839 | SCOPED_UMA_HISTOGRAM_TIMER("UMA.MetricsService.RecordCurrentHistograms.Time"); |
bcwhite | 05dc092 | 2016-06-03 04:59:44 | [diff] [blame] | 840 | |
Alexei Svitkine | 24a116bb | 2017-07-24 18:31:31 | [diff] [blame] | 841 | // "true" indicates that StatisticsRecorder should include histograms held in |
| 842 | // persistent storage. |
| 843 | base::StatisticsRecorder::PrepareDeltas( |
| 844 | true, base::Histogram::kNoFlags, |
| 845 | base::Histogram::kUmaTargetedHistogramFlag, &histogram_snapshot_manager_); |
Steven Holte | c35411dc | 2017-07-28 04:22:14 | [diff] [blame] | 846 | delegating_provider_.RecordHistogramSnapshots(&histogram_snapshot_manager_); |
[email protected] | acc2ce551 | 2014-05-22 18:29:13 | [diff] [blame] | 847 | } |
| 848 | |
| 849 | void MetricsService::RecordCurrentStabilityHistograms() { |
| 850 | DCHECK(log_manager_.current_log()); |
Alexei Svitkine | 24a116bb | 2017-07-24 18:31:31 | [diff] [blame] | 851 | // "true" indicates that StatisticsRecorder should include histograms held in |
bcwhite | 5cb99eb | 2016-02-01 21:07:56 | [diff] [blame] | 852 | // persistent storage. |
Alexei Svitkine | 24a116bb | 2017-07-24 18:31:31 | [diff] [blame] | 853 | base::StatisticsRecorder::PrepareDeltas( |
| 854 | true, base::Histogram::kNoFlags, |
| 855 | base::Histogram::kUmaStabilityHistogramFlag, |
| 856 | &histogram_snapshot_manager_); |
Steven Holte | c35411dc | 2017-07-28 04:22:14 | [diff] [blame] | 857 | delegating_provider_.RecordInitialHistogramSnapshots( |
| 858 | &histogram_snapshot_manager_); |
[email protected] | acc2ce551 | 2014-05-22 18:29:13 | [diff] [blame] | 859 | } |
| 860 | |
bcwhite | 8e72aa59 | 2017-06-09 18:59:18 | [diff] [blame] | 861 | bool MetricsService::PrepareProviderMetricsLog() { |
Steven Holte | 971b059 | 2017-10-12 15:28:26 | [diff] [blame] | 862 | DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); |
bcwhite | 8e72aa59 | 2017-06-09 18:59:18 | [diff] [blame] | 863 | |
| 864 | // Create a new log. This will have some defaut values injected in it but |
| 865 | // those will be overwritten when an embedded profile is extracted. |
| 866 | std::unique_ptr<MetricsLog> log = CreateLog(MetricsLog::INDEPENDENT_LOG); |
| 867 | |
Steven Holte | c35411dc | 2017-07-28 04:22:14 | [diff] [blame] | 868 | for (auto& provider : delegating_provider_.GetProviders()) { |
bcwhite | 8e72aa59 | 2017-06-09 18:59:18 | [diff] [blame] | 869 | if (log->LoadIndependentMetrics(provider.get())) { |
| 870 | log_manager_.PauseCurrentLog(); |
| 871 | log_manager_.BeginLoggingWithLog(std::move(log)); |
| 872 | log_manager_.FinishCurrentLog(log_store()); |
| 873 | log_manager_.ResumePausedLog(); |
| 874 | return true; |
| 875 | } |
| 876 | } |
| 877 | return false; |
| 878 | } |
| 879 | |
| 880 | void MetricsService::PrepareProviderMetricsTask() { |
Steven Holte | 971b059 | 2017-10-12 15:28:26 | [diff] [blame] | 881 | DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); |
bcwhite | 8e72aa59 | 2017-06-09 18:59:18 | [diff] [blame] | 882 | bool found = PrepareProviderMetricsLog(); |
| 883 | base::TimeDelta next_check = found ? base::TimeDelta::FromSeconds(5) |
| 884 | : base::TimeDelta::FromMinutes(15); |
Steven Holte | 971b059 | 2017-10-12 15:28:26 | [diff] [blame] | 885 | base::SequencedTaskRunnerHandle::Get()->PostDelayedTask( |
bcwhite | 8e72aa59 | 2017-06-09 18:59:18 | [diff] [blame] | 886 | FROM_HERE, |
| 887 | base::Bind(&MetricsService::PrepareProviderMetricsTask, |
| 888 | self_ptr_factory_.GetWeakPtr()), |
| 889 | next_check); |
| 890 | } |
| 891 | |
holte | 6d34116 | 2016-12-19 21:42:42 | [diff] [blame] | 892 | void MetricsService::LogCleanShutdown(bool end_completed) { |
Steven Holte | 971b059 | 2017-10-12 15:28:26 | [diff] [blame] | 893 | DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); |
[email protected] | c0c55e9 | 2011-09-10 18:47:30 | [diff] [blame] | 894 | // Redundant setting to assure that we always reset this value at shutdown |
| 895 | // (and that we don't use some alternate path, and not call LogCleanShutdown). |
| 896 | clean_shutdown_status_ = CLEANLY_SHUTDOWN; |
manzagop | 14aff5d | 2016-11-23 17:27:00 | [diff] [blame] | 897 | client_->OnLogCleanShutdown(); |
Ilya Sherman | 6c6c833 | 2017-07-11 22:39:22 | [diff] [blame] | 898 | state_manager_->clean_exit_beacon()->WriteBeaconValue(true); |
holte | a27eadf | 2017-01-26 01:58:59 | [diff] [blame] | 899 | SetExecutionPhase(ExecutionPhase::SHUTDOWN_COMPLETE, local_state_); |
holte | 1bf273c | 2017-02-23 00:22:28 | [diff] [blame] | 900 | StabilityMetricsProvider(local_state_).MarkSessionEndCompleted(end_completed); |
initial.commit | 09911bf | 2008-07-26 23:55:29 | [diff] [blame] | 901 | } |
asvitkine | cbd42073 | 2014-08-26 22:15:40 | [diff] [blame] | 902 | |
| 903 | } // namespace metrics |