Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2016 The Chromium Authors. All rights reserved. | 1 // Copyright 2016 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "components/metrics/file_metrics_provider.h" | 5 #include "components/metrics/file_metrics_provider.h" |
| 6 | 6 |
| 7 #include "base/command_line.h" | 7 #include "base/command_line.h" |
| 8 #include "base/files/file.h" | 8 #include "base/files/file.h" |
| 9 #include "base/files/file_util.h" | 9 #include "base/files/file_util.h" |
| 10 #include "base/files/memory_mapped_file.h" | 10 #include "base/files/memory_mapped_file.h" |
| (...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 62 PrefService* local_state) | 62 PrefService* local_state) |
| 63 : task_runner_(task_runner), | 63 : task_runner_(task_runner), |
| 64 pref_service_(local_state), | 64 pref_service_(local_state), |
| 65 weak_factory_(this) { | 65 weak_factory_(this) { |
| 66 } | 66 } |
| 67 | 67 |
| 68 FileMetricsProvider::~FileMetricsProvider() {} | 68 FileMetricsProvider::~FileMetricsProvider() {} |
| 69 | 69 |
| 70 void FileMetricsProvider::RegisterFile(const base::FilePath& path, | 70 void FileMetricsProvider::RegisterFile(const base::FilePath& path, |
| 71 FileType type, | 71 FileType type, |
| 72 FileAssociation file_association, | |
| 72 const base::StringPiece prefs_key) { | 73 const base::StringPiece prefs_key) { |
| 73 DCHECK(thread_checker_.CalledOnValidThread()); | 74 DCHECK(thread_checker_.CalledOnValidThread()); |
| 74 | 75 |
| 75 std::unique_ptr<FileInfo> file(new FileInfo(type)); | 76 std::unique_ptr<FileInfo> file(new FileInfo(type)); |
| 76 file->path = path; | 77 file->path = path; |
| 77 file->prefs_key = prefs_key.as_string(); | 78 file->prefs_key = prefs_key.as_string(); |
| 78 | 79 |
| 79 // |prefs_key| may be empty if the caller does not wish to persist the | 80 // |prefs_key| may be empty if the caller does not wish to persist the |
| 80 // state across instances of the program. | 81 // state across instances of the program. |
| 81 if (pref_service_ && !prefs_key.empty()) { | 82 if (pref_service_ && !prefs_key.empty()) { |
| 82 file->last_seen = base::Time::FromInternalValue( | 83 file->last_seen = base::Time::FromInternalValue( |
| 83 pref_service_->GetInt64(metrics::prefs::kMetricsLastSeenPrefix + | 84 pref_service_->GetInt64(metrics::prefs::kMetricsLastSeenPrefix + |
| 84 file->prefs_key)); | 85 file->prefs_key)); |
| 85 } | 86 } |
| 86 | 87 |
| 87 files_to_check_.push_back(std::move(file)); | 88 switch (file_association) { |
| 89 case ASSOCIATE_CURRENT_RUN: | |
| 90 files_to_check_.push_back(std::move(file)); | |
| 91 break; | |
| 92 case ASSOCIATE_PREVIOUS_RUN: | |
| 93 DCHECK_EQ(FILE_HISTOGRAMS_ATOMIC, file->type); | |
| 94 files_for_previous_run_.push_back(std::move(file)); | |
| 95 break; | |
| 96 } | |
| 88 } | 97 } |
| 89 | 98 |
| 90 // static | 99 // static |
| 91 void FileMetricsProvider::RegisterPrefs(PrefRegistrySimple* prefs, | 100 void FileMetricsProvider::RegisterPrefs(PrefRegistrySimple* prefs, |
| 92 const base::StringPiece prefs_key) { | 101 const base::StringPiece prefs_key) { |
| 93 prefs->RegisterInt64Pref(metrics::prefs::kMetricsLastSeenPrefix + | 102 prefs->RegisterInt64Pref(metrics::prefs::kMetricsLastSeenPrefix + |
| 94 prefs_key.as_string(), 0); | 103 prefs_key.as_string(), 0); |
| 95 } | 104 } |
| 96 | 105 |
| 97 // static | 106 // static |
| (...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 180 DCHECK(thread_checker_.CalledOnValidThread()); | 189 DCHECK(thread_checker_.CalledOnValidThread()); |
| 181 base::PersistentHistogramAllocator::Iterator histogram_iter( | 190 base::PersistentHistogramAllocator::Iterator histogram_iter( |
| 182 file->allocator.get()); | 191 file->allocator.get()); |
| 183 | 192 |
| 184 int histogram_count = 0; | 193 int histogram_count = 0; |
| 185 while (true) { | 194 while (true) { |
| 186 std::unique_ptr<base::HistogramBase> histogram = histogram_iter.GetNext(); | 195 std::unique_ptr<base::HistogramBase> histogram = histogram_iter.GetNext(); |
| 187 if (!histogram) | 196 if (!histogram) |
| 188 break; | 197 break; |
| 189 if (file->type == FILE_HISTOGRAMS_ATOMIC) | 198 if (file->type == FILE_HISTOGRAMS_ATOMIC) |
| 190 snapshot_manager->PrepareAbsoluteTakingOwnership(std::move(histogram)); | 199 snapshot_manager->PrepareFinalDeltaTakingOwnership(std::move(histogram)); |
| 191 else | 200 else |
| 192 snapshot_manager->PrepareDeltaTakingOwnership(std::move(histogram)); | 201 snapshot_manager->PrepareDeltaTakingOwnership(std::move(histogram)); |
| 193 ++histogram_count; | 202 ++histogram_count; |
| 194 } | 203 } |
| 195 | 204 |
| 196 DVLOG(1) << "Reported " << histogram_count << " histograms from " | 205 DVLOG(1) << "Reported " << histogram_count << " histograms from " |
| 197 << file->path.value(); | 206 << file->path.value(); |
| 198 } | 207 } |
| 199 | 208 |
| 200 void FileMetricsProvider::CreateAllocatorForFile(FileInfo* file) { | 209 void FileMetricsProvider::CreateAllocatorForFile(FileInfo* file) { |
| (...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 261 | 270 |
| 262 if (!file->allocator && !file->mapped && file->data.empty()) | 271 if (!file->allocator && !file->mapped && file->data.empty()) |
| 263 files_to_check_.splice(files_to_check_.end(), files_to_read_, temp); | 272 files_to_check_.splice(files_to_check_.end(), files_to_read_, temp); |
| 264 } | 273 } |
| 265 | 274 |
| 266 // Schedule a check to see if there are new metrics to load. If so, they | 275 // Schedule a check to see if there are new metrics to load. If so, they |
| 267 // will be reported during the next collection run after this one. The | 276 // will be reported during the next collection run after this one. The |
| 268 // check is run off of the worker-pool so as to not cause delays on the | 277 // check is run off of the worker-pool so as to not cause delays on the |
| 269 // main UI thread (which is currently where metric collection is done). | 278 // main UI thread (which is currently where metric collection is done). |
| 270 ScheduleFilesCheck(); | 279 ScheduleFilesCheck(); |
| 280 | |
| 281 // Clear any data for initial metrics since they're always reported | |
| 282 // before the first call to this method. It couldn't be released after | |
| 283 // being reported in RecordInitialHistogramSnapshots because the data | |
| 284 // will continue to be used by the caller after that method returns. Once | |
| 285 // here, though, all actions to be done on the data have been completed. | |
| 286 #if DCHECK_IS_ON() | |
| 287 for (const std::unique_ptr<FileInfo>& file : files_for_previous_run_) | |
| 288 DCHECK(file->read_complete); | |
| 289 #endif | |
| 290 files_for_previous_run_.clear(); | |
| 291 } | |
| 292 | |
| 293 bool FileMetricsProvider::HasInitialStabilityMetrics() { | |
| 294 DCHECK(thread_checker_.CalledOnValidThread()); | |
| 295 | |
| 296 SCOPED_UMA_HISTOGRAM_TIMER("UMA.FileMetricsProvider.InitialTotalCheckTime"); | |
|
Alexei Svitkine (slow)
2016/05/09 21:24:10
Nit: Add a comment above these scoped timers menti
bcwhite
2016/05/10 15:42:41
Done.
| |
| 297 | |
| 298 // Check all files for previous run to see if they need to be read. | |
| 299 for (auto iter = files_for_previous_run_.begin(); | |
| 300 iter != files_for_previous_run_.end();) { | |
| 301 SCOPED_UMA_HISTOGRAM_TIMER("UMA.FileMetricsProvider.InitialFileCheckTime"); | |
|
Alexei Svitkine (slow)
2016/05/09 21:24:10
How about:
UMA.FileMetricsProvider.InitialCheckTi
bcwhite
2016/05/10 15:42:40
Done.
| |
| 302 | |
| 303 auto temp = iter++; | |
| 304 FileInfo* file = temp->get(); | |
| 305 | |
| 306 // This would normally be done on a background I/O thread but there | |
| 307 // hasn't been a chance to run any at the time this method is called. | |
| 308 // Do the check in-line. | |
| 309 AccessResult result = CheckAndMapNewMetrics(file); | |
| 310 UMA_HISTOGRAM_ENUMERATION("UMA.FileMetricsProvider.InitialAccessResult", | |
| 311 result, ACCESS_RESULT_MAX); | |
| 312 | |
| 313 // If it couldn't be accessed, remove it from the list. There is only ever | |
| 314 // one chance to record it so no point keeping it around for later. Also | |
| 315 // mark it as having been read since uploading it with a future browser | |
| 316 // run would associate it with the previous run which would no longer be | |
| 317 // the run from which it came. | |
| 318 if (result != ACCESS_RESULT_SUCCESS) { | |
| 319 RecordFileAsSeen(file); | |
| 320 files_for_previous_run_.erase(temp); | |
| 321 } | |
| 322 } | |
| 323 | |
| 324 return !files_for_previous_run_.empty(); | |
| 271 } | 325 } |
| 272 | 326 |
| 273 void FileMetricsProvider::RecordHistogramSnapshots( | 327 void FileMetricsProvider::RecordHistogramSnapshots( |
| 274 base::HistogramSnapshotManager* snapshot_manager) { | 328 base::HistogramSnapshotManager* snapshot_manager) { |
| 275 DCHECK(thread_checker_.CalledOnValidThread()); | 329 DCHECK(thread_checker_.CalledOnValidThread()); |
| 276 | 330 |
| 331 SCOPED_UMA_HISTOGRAM_TIMER("UMA.FileMetricsProvider.TotalSnapshotTime"); | |
| 332 | |
| 277 for (std::unique_ptr<FileInfo>& file : files_to_read_) { | 333 for (std::unique_ptr<FileInfo>& file : files_to_read_) { |
| 278 // Skip this file if the data has already been read. | 334 // Skip this file if the data has already been read. |
| 279 if (file->read_complete) | 335 if (file->read_complete) |
| 280 continue; | 336 continue; |
| 281 | 337 |
| 338 SCOPED_UMA_HISTOGRAM_TIMER("UMA.FileMetricsProvider.FileSnapshotTime"); | |
| 339 | |
| 282 // If the file is mapped or loaded then it needs to have an allocator | 340 // If the file is mapped or loaded then it needs to have an allocator |
| 283 // attached to it in order to read histograms out of it. | 341 // attached to it in order to read histograms out of it. |
| 284 if (file->mapped || !file->data.empty()) | 342 if (file->mapped || !file->data.empty()) |
| 285 CreateAllocatorForFile(file.get()); | 343 CreateAllocatorForFile(file.get()); |
| 286 | 344 |
| 287 // A file should not be under "files to read" unless it has an allocator | 345 // A file should not be under "files to read" unless it has an allocator |
| 288 // or is memory-mapped (at which point it will have received an allocator | 346 // or is memory-mapped (at which point it will have received an allocator |
| 289 // above). However, if this method gets called twice before the scheduled- | 347 // above). However, if this method gets called twice before the scheduled- |
| 290 // files-check has a chance to clean up, this may trigger. This also | 348 // files-check has a chance to clean up, this may trigger. This also |
| 291 // catches the case where creating an allocator from the file has failed. | 349 // catches the case where creating an allocator from the file has failed. |
| 292 if (!file->allocator) | 350 if (!file->allocator) |
| 293 continue; | 351 continue; |
| 294 | 352 |
| 295 // Dump all histograms contained within the file to the snapshot-manager. | 353 // Dump all histograms contained within the file to the snapshot-manager. |
| 296 RecordHistogramSnapshotsFromFile(snapshot_manager, file.get()); | 354 RecordHistogramSnapshotsFromFile(snapshot_manager, file.get()); |
| 297 | 355 |
| 298 // Update the last-seen time so it isn't read again unless it changes. | 356 // Update the last-seen time so it isn't read again unless it changes. |
| 299 RecordFileAsSeen(file.get()); | 357 RecordFileAsSeen(file.get()); |
| 300 } | 358 } |
| 301 } | 359 } |
| 302 | 360 |
| 361 void FileMetricsProvider::RecordInitialHistogramSnapshots( | |
| 362 base::HistogramSnapshotManager* snapshot_manager) { | |
| 363 DCHECK(thread_checker_.CalledOnValidThread()); | |
| 364 | |
| 365 SCOPED_UMA_HISTOGRAM_TIMER( | |
| 366 "UMA.FileMetricsProvider.InitialTotalSnapshotTime"); | |
| 367 | |
| 368 for (const std::unique_ptr<FileInfo>& file : files_for_previous_run_) { | |
| 369 SCOPED_UMA_HISTOGRAM_TIMER( | |
| 370 "UMA.FileMetricsProvider.InitialFileSnapshotTime"); | |
| 371 | |
| 372 // The file needs to have an allocator attached to it in order to read | |
| 373 // histograms out of it. | |
| 374 DCHECK(file->mapped || !file->data.empty()); | |
| 375 CreateAllocatorForFile(file.get()); | |
| 376 DCHECK(file->allocator); | |
| 377 | |
| 378 // Dump all histograms contained within the file to the snapshot-manager. | |
| 379 RecordHistogramSnapshotsFromFile(snapshot_manager, file.get()); | |
| 380 | |
| 381 // Update the last-seen time so it isn't read again unless it changes. | |
| 382 RecordFileAsSeen(file.get()); | |
| 383 } | |
| 384 } | |
| 385 | |
| 303 } // namespace metrics | 386 } // namespace metrics |
| OLD | NEW |