blob: 43d4d304dea1cbe4e65e8790733c735397fef446 [file] [log] [blame]
bcwhite34c6bbf2016-02-19 22:14:461// Copyright 2016 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#ifndef COMPONENTS_METRICS_FILE_METRICS_PROVIDER_H_
6#define COMPONENTS_METRICS_FILE_METRICS_PROVIDER_H_
7
8#include <list>
dchengd99c42a2016-04-21 21:54:139#include <memory>
bcwhite34c6bbf2016-02-19 22:14:4610#include <string>
11
12#include "base/callback.h"
13#include "base/files/file_path.h"
14#include "base/gtest_prod_util.h"
bcwhite34c6bbf2016-02-19 22:14:4615#include "base/memory/weak_ptr.h"
bcwhite9075a092017-02-01 01:58:5616#include "base/metrics/statistics_recorder.h"
bcwhite34c6bbf2016-02-19 22:14:4617#include "base/threading/thread_checker.h"
18#include "base/time/time.h"
19#include "components/metrics/metrics_provider.h"
20
21class PrefRegistrySimple;
22class PrefService;
23
24namespace base {
bcwhite34c6bbf2016-02-19 22:14:4625class TaskRunner;
26}
27
28namespace metrics {
29
30// FileMetricsProvider gathers and logs histograms written to files on disk.
31// Any number of files can be registered and will be polled once per upload
32// cycle (at startup and periodically thereafter -- about every 30 minutes
33// for desktop) for data to send.
bcwhite9075a092017-02-01 01:58:5634class FileMetricsProvider : public MetricsProvider,
35 public base::StatisticsRecorder::HistogramProvider {
bcwhite34c6bbf2016-02-19 22:14:4636 public:
bcwhite0d2c3822016-05-16 15:17:1237 enum SourceType {
bcwhite34c6bbf2016-02-19 22:14:4638 // "Atomic" files are a collection of histograms that are written
39 // completely in a single atomic operation (typically a write followed
40 // by an atomic rename) and the file is never updated again except to
41 // be replaced by a completely new set of histograms. This is the only
42 // option that can be used if the file is not writeable by *this*
bcwhite48d0e7492016-05-25 01:59:0543 // process. Once the file has been read, an attempt will be made to
44 // delete it thus providing some measure of safety should different
45 // instantiations (such as by different users of a system-level install)
46 // try to read it. In case the delete operation fails, this class
47 // persistently tracks the last-modified time of the file so it will
48 // not be read a second time.
bcwhite0d2c3822016-05-16 15:17:1249 SOURCE_HISTOGRAMS_ATOMIC_FILE,
50
51 // A directory of atomic PMA files. This handles a directory in which
52 // files of metrics are atomically added. Only files ending with ".pma"
53 // will be read. They are read according to their last-modified time and
54 // never read more that once (unless they change). Only one file will
55 // be read per reporting cycle. Filenames that start with a dot (.) or
56 // an underscore (_) are ignored so temporary files (perhaps created by
57 // the ImportantFileWriter) will not get read. Files that have been
58 // read will be attempted to be deleted; should those files not be
59 // deletable by this process, it is the reponsibility of the producer
60 // to keep the directory pruned in some manner.
61 SOURCE_HISTOGRAMS_ATOMIC_DIR,
bcwhite34c6bbf2016-02-19 22:14:4662
63 // "Active" files may be open by one or more other processes and updated
64 // at any time with new samples or new histograms. Such files may also be
65 // inactive for any period of time only to be opened again and have new
66 // data written to them. The file should probably never be deleted because
67 // there would be no guarantee that the data has been reported.
68 // TODO(bcwhite): Enable when read/write mem-mapped files are supported.
bcwhite2a27d742016-06-10 15:47:0569 SOURCE_HISTOGRAMS_ACTIVE_FILE,
bcwhite34c6bbf2016-02-19 22:14:4670 };
71
bcwhite0d2c3822016-05-16 15:17:1272 enum SourceAssociation {
bcwhite65e57d02016-05-13 14:39:4073 // Associates the metrics in the file with the current run of the browser.
74 // The reporting will take place as part of the normal logging of
75 // histograms.
76 ASSOCIATE_CURRENT_RUN,
77
78 // Associates the metrics in the file with the previous run of the browesr.
79 // The reporting will take place as part of the "stability" histograms.
80 // This is important when metrics are dumped as part of a crash of the
81 // previous run. This can only be used with FILE_HISTOGRAMS_ATOMIC.
82 ASSOCIATE_PREVIOUS_RUN,
83 };
84
bcwhite34c6bbf2016-02-19 22:14:4685 FileMetricsProvider(const scoped_refptr<base::TaskRunner>& task_runner,
86 PrefService* local_state);
87 ~FileMetricsProvider() override;
88
bcwhite0d2c3822016-05-16 15:17:1289 // Indicates a file or directory to be monitored and how the file or files
90 // within that directory are used. Because some metadata may need to persist
91 // across process restarts, preferences entries are used based on the
92 // |prefs_key| name. Call RegisterPrefs() with the same name to create the
bcwhite4ff719b2017-03-14 14:05:4293 // necessary keys in advance. Set |prefs_key| empty (nullptr will work) if
94 // no persistence is required. ACTIVE files shouldn't have a pref key as
95 // they update internal state about what has been previously sent.
bcwhite0d2c3822016-05-16 15:17:1296 void RegisterSource(const base::FilePath& path,
97 SourceType type,
98 SourceAssociation source_association,
99 const base::StringPiece prefs_key);
bcwhite34c6bbf2016-02-19 22:14:46100
101 // Registers all necessary preferences for maintaining persistent state
102 // about a monitored file across process restarts. The |prefs_key| is
103 // typically the filename.
104 static void RegisterPrefs(PrefRegistrySimple* prefs,
105 const base::StringPiece prefs_key);
106
107 private:
108 friend class FileMetricsProviderTest;
bcwhite34c6bbf2016-02-19 22:14:46109
110 // The different results that can occur accessing a file.
111 enum AccessResult {
112 // File was successfully mapped.
113 ACCESS_RESULT_SUCCESS,
114
115 // File does not exist.
116 ACCESS_RESULT_DOESNT_EXIST,
117
118 // File exists but not modified since last read.
119 ACCESS_RESULT_NOT_MODIFIED,
120
121 // File is not valid: is a directory or zero-size.
122 ACCESS_RESULT_INVALID_FILE,
123
124 // System could not map file into memory.
125 ACCESS_RESULT_SYSTEM_MAP_FAILURE,
126
127 // File had invalid contents.
128 ACCESS_RESULT_INVALID_CONTENTS,
129
bcwhite2a27d742016-06-10 15:47:05130 // File could not be opened.
131 ACCESS_RESULT_NO_OPEN,
bcwhite0d2c3822016-05-16 15:17:12132
bcwhite42561dc2017-03-16 18:35:24133 // File contents were internally deleted.
134 ACCESS_RESULT_MEMORY_DELETED,
135
bcwhite34c6bbf2016-02-19 22:14:46136 ACCESS_RESULT_MAX
137 };
138
bcwhite0d2c3822016-05-16 15:17:12139 // Information about sources being monitored; defined and used exclusively
bcwhite34c6bbf2016-02-19 22:14:46140 // inside the .cc file.
bcwhite0d2c3822016-05-16 15:17:12141 struct SourceInfo;
142 using SourceInfoList = std::list<std::unique_ptr<SourceInfo>>;
bcwhite34c6bbf2016-02-19 22:14:46143
bcwhite0d2c3822016-05-16 15:17:12144 // Looks for the next file to read within a directory. Returns true if a
145 // file was found. This is part of CheckAndMapNewMetricSourcesOnTaskRunner
146 // and so runs on an thread capable of I/O. The |source| structure will
147 // be internally updated to indicate the next file to be read.
148 static bool LocateNextFileInDirectory(SourceInfo* source);
bcwhite34c6bbf2016-02-19 22:14:46149
bcwhite2a27d742016-06-10 15:47:05150 // Checks a list of sources (on a task-runner allowed to do I/O) and merge
151 // any data found within them.
152 static void CheckAndMergeMetricSourcesOnTaskRunner(SourceInfoList* sources);
153
154 // Checks a single source and maps it into memory.
155 static AccessResult CheckAndMapMetricSource(SourceInfo* source);
156
157 // Merges all of the histograms from a |source| to the StatisticsRecorder.
158 static void MergeHistogramDeltasFromSource(SourceInfo* source);
159
160 // Records all histograms from a given source via a snapshot-manager.
161 static void RecordHistogramSnapshotsFromSource(
162 base::HistogramSnapshotManager* snapshot_manager,
163 SourceInfo* source);
bcwhite48d0e7492016-05-25 01:59:05164
bcwhite0d2c3822016-05-16 15:17:12165 // Creates a task to check all monitored sources for updates.
166 void ScheduleSourcesCheck();
167
bcwhite0d2c3822016-05-16 15:17:12168 // Takes a list of sources checked by an external task and determines what
bcwhite34c6bbf2016-02-19 22:14:46169 // to do with each.
bcwhite0d2c3822016-05-16 15:17:12170 void RecordSourcesChecked(SourceInfoList* checked);
bcwhite34c6bbf2016-02-19 22:14:46171
bcwhite2a27d742016-06-10 15:47:05172 // Schedules the deletion of a file in the background using the task-runner.
173 void DeleteFileAsync(const base::FilePath& path);
174
bcwhite0d2c3822016-05-16 15:17:12175 // Updates the persistent state information to show a source as being read.
bcwhite48d0e7492016-05-25 01:59:05176 void RecordSourceAsRead(SourceInfo* source);
bcwhite34c6bbf2016-02-19 22:14:46177
178 // metrics::MetricsDataProvider:
179 void OnDidCreateMetricsLog() override;
bcwhite65e57d02016-05-13 14:39:40180 bool HasInitialStabilityMetrics() override;
bcwhite65e57d02016-05-13 14:39:40181 void RecordInitialHistogramSnapshots(
182 base::HistogramSnapshotManager* snapshot_manager) override;
bcwhite34c6bbf2016-02-19 22:14:46183
bcwhite9075a092017-02-01 01:58:56184 // base::StatisticsRecorder::HistogramProvider:
185 void MergeHistogramDeltas() override;
186
bcwhite34c6bbf2016-02-19 22:14:46187 // A task-runner capable of performing I/O.
188 scoped_refptr<base::TaskRunner> task_runner_;
189
bcwhite0d2c3822016-05-16 15:17:12190 // A list of sources not currently active that need to be checked for changes.
191 SourceInfoList sources_to_check_;
bcwhite34c6bbf2016-02-19 22:14:46192
bcwhite2a27d742016-06-10 15:47:05193 // A list of currently active sources to be merged when required.
194 SourceInfoList sources_mapped_;
bcwhite34c6bbf2016-02-19 22:14:46195
bcwhite0d2c3822016-05-16 15:17:12196 // A list of sources for a previous run. These are held separately because
bcwhite65e57d02016-05-13 14:39:40197 // they are not subject to the periodic background checking that handles
198 // metrics for the current run.
bcwhite0d2c3822016-05-16 15:17:12199 SourceInfoList sources_for_previous_run_;
bcwhite65e57d02016-05-13 14:39:40200
bcwhite0d2c3822016-05-16 15:17:12201 // The preferences-service used to store persistent state about sources.
bcwhite34c6bbf2016-02-19 22:14:46202 PrefService* pref_service_;
203
204 base::ThreadChecker thread_checker_;
205 base::WeakPtrFactory<FileMetricsProvider> weak_factory_;
206
207 DISALLOW_COPY_AND_ASSIGN(FileMetricsProvider);
208};
209
210} // namespace metrics
211
212#endif // COMPONENTS_METRICS_FILE_METRICS_PROVIDER_H_