| 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_enumerator.h" | 9 #include "base/files/file_enumerator.h" |
| 10 #include "base/files/file_util.h" | 10 #include "base/files/file_util.h" |
| 11 #include "base/files/memory_mapped_file.h" | 11 #include "base/files/memory_mapped_file.h" |
| 12 #include "base/logging.h" | 12 #include "base/logging.h" |
| 13 #include "base/memory/ptr_util.h" | 13 #include "base/memory/ptr_util.h" |
| 14 #include "base/metrics/histogram_base.h" | 14 #include "base/metrics/histogram_base.h" |
| 15 #include "base/metrics/histogram_macros.h" | 15 #include "base/metrics/histogram_macros.h" |
| 16 #include "base/metrics/persistent_histogram_allocator.h" | 16 #include "base/metrics/persistent_histogram_allocator.h" |
| 17 #include "base/metrics/persistent_memory_allocator.h" | 17 #include "base/metrics/persistent_memory_allocator.h" |
| 18 #include "base/strings/string_piece.h" | 18 #include "base/strings/string_piece.h" |
| 19 #include "base/task_runner.h" | 19 #include "base/task_runner.h" |
| 20 #include "base/time/time.h" | 20 #include "base/time/time.h" |
| 21 #include "components/metrics/metrics_pref_names.h" | 21 #include "components/metrics/metrics_pref_names.h" |
| 22 #include "components/metrics/metrics_service.h" | 22 #include "components/metrics/metrics_service.h" |
| 23 #include "components/metrics/persistent_system_profile.h" |
| 23 #include "components/prefs/pref_registry_simple.h" | 24 #include "components/prefs/pref_registry_simple.h" |
| 24 #include "components/prefs/pref_service.h" | 25 #include "components/prefs/pref_service.h" |
| 25 | 26 |
| 26 namespace metrics { | 27 namespace metrics { |
| 27 | 28 |
| 28 namespace { | 29 namespace { |
| 29 | 30 |
| 30 // These structures provide values used to define how files are opened and | 31 // These structures provide values used to define how files are opened and |
| 31 // accessed. It obviates the need for multiple code-paths within several of | 32 // accessed. It obviates the need for multiple code-paths within several of |
| 32 // the methods. | 33 // the methods. |
| (...skipping 30 matching lines...) Expand all Loading... |
| 63 }, | 64 }, |
| 64 // SOURCE_HISTOGRAMS_ACTIVE_FILE | 65 // SOURCE_HISTOGRAMS_ACTIVE_FILE |
| 65 { | 66 { |
| 66 // Allow writing (updated "logged" values) to the file. | 67 // Allow writing (updated "logged" values) to the file. |
| 67 STD_OPEN | base::File::FLAG_WRITE, | 68 STD_OPEN | base::File::FLAG_WRITE, |
| 68 base::MemoryMappedFile::READ_WRITE, | 69 base::MemoryMappedFile::READ_WRITE, |
| 69 false | 70 false |
| 70 } | 71 } |
| 71 }; | 72 }; |
| 72 | 73 |
| 74 enum EmbeddedProfileResult : int { |
| 75 EMBEDDED_PROFILE_ATTEMPT, |
| 76 EMBEDDED_PROFILE_FOUND, |
| 77 EMBEDDED_PROFILE_FALLBACK, |
| 78 EMBEDDED_PROFILE_DROPPED, |
| 79 EMBEDDED_PROFILE_ACTION_MAX |
| 80 }; |
| 81 |
| 82 void RecordEmbeddedProfileResult(EmbeddedProfileResult result) { |
| 83 UMA_HISTOGRAM_ENUMERATION("UMA.FileMetricsProvider.EmbeddedProfileResult", |
| 84 result, EMBEDDED_PROFILE_ACTION_MAX); |
| 85 } |
| 86 |
| 73 void DeleteFileWhenPossible(const base::FilePath& path) { | 87 void DeleteFileWhenPossible(const base::FilePath& path) { |
| 74 // Open (with delete) and then immediately close the file by going out of | 88 // Open (with delete) and then immediately close the file by going out of |
| 75 // scope. This is the only cross-platform safe way to delete a file that may | 89 // scope. This is the only cross-platform safe way to delete a file that may |
| 76 // be open elsewhere, a distinct possibility given the asynchronous nature | 90 // be open elsewhere, a distinct possibility given the asynchronous nature |
| 77 // of the delete task. | 91 // of the delete task. |
| 78 base::File file(path, base::File::FLAG_OPEN | base::File::FLAG_READ | | 92 base::File file(path, base::File::FLAG_OPEN | base::File::FLAG_READ | |
| 79 base::File::FLAG_DELETE_ON_CLOSE); | 93 base::File::FLAG_DELETE_ON_CLOSE); |
| 80 } | 94 } |
| 81 | 95 |
| 82 } // namespace | 96 } // namespace |
| 83 | 97 |
| 84 // This structure stores all the information about the sources being monitored | 98 // This structure stores all the information about the sources being monitored |
| 85 // and their current reporting state. | 99 // and their current reporting state. |
| 86 struct FileMetricsProvider::SourceInfo { | 100 struct FileMetricsProvider::SourceInfo { |
| 87 SourceInfo(SourceType source_type) : type(source_type) {} | 101 SourceInfo(SourceType source_type, SourceAssociation source_association) |
| 102 : type(source_type), association(source_association) {} |
| 88 ~SourceInfo() {} | 103 ~SourceInfo() {} |
| 89 | 104 |
| 90 // How to access this source (file/dir, atomic/active). | 105 // How to access this source (file/dir, atomic/active). |
| 91 const SourceType type; | 106 const SourceType type; |
| 92 | 107 |
| 108 // With what run this source is associated. |
| 109 const SourceAssociation association; |
| 110 |
| 93 // Where on disk the directory is located. This will only be populated when | 111 // Where on disk the directory is located. This will only be populated when |
| 94 // a directory is being monitored. | 112 // a directory is being monitored. |
| 95 base::FilePath directory; | 113 base::FilePath directory; |
| 96 | 114 |
| 97 // Where on disk the file is located. If a directory is being monitored, | 115 // Where on disk the file is located. If a directory is being monitored, |
| 98 // this will be updated for whatever file is being read. | 116 // this will be updated for whatever file is being read. |
| 99 base::FilePath path; | 117 base::FilePath path; |
| 100 | 118 |
| 101 // Name used inside prefs to persistent metadata. | 119 // Name used inside prefs to persistent metadata. |
| 102 std::string prefs_key; | 120 std::string prefs_key; |
| (...skipping 26 matching lines...) Expand all Loading... |
| 129 | 147 |
| 130 void FileMetricsProvider::RegisterSource(const base::FilePath& path, | 148 void FileMetricsProvider::RegisterSource(const base::FilePath& path, |
| 131 SourceType type, | 149 SourceType type, |
| 132 SourceAssociation source_association, | 150 SourceAssociation source_association, |
| 133 const base::StringPiece prefs_key) { | 151 const base::StringPiece prefs_key) { |
| 134 DCHECK(thread_checker_.CalledOnValidThread()); | 152 DCHECK(thread_checker_.CalledOnValidThread()); |
| 135 | 153 |
| 136 // Ensure that kSourceOptions has been filled for this type. | 154 // Ensure that kSourceOptions has been filled for this type. |
| 137 DCHECK_GT(arraysize(kSourceOptions), static_cast<size_t>(type)); | 155 DCHECK_GT(arraysize(kSourceOptions), static_cast<size_t>(type)); |
| 138 | 156 |
| 139 std::unique_ptr<SourceInfo> source(new SourceInfo(type)); | 157 std::unique_ptr<SourceInfo> source(new SourceInfo(type, source_association)); |
| 140 source->prefs_key = prefs_key.as_string(); | 158 source->prefs_key = prefs_key.as_string(); |
| 141 | 159 |
| 142 switch (source->type) { | 160 switch (source->type) { |
| 143 case SOURCE_HISTOGRAMS_ACTIVE_FILE: | 161 case SOURCE_HISTOGRAMS_ACTIVE_FILE: |
| 144 DCHECK(prefs_key.empty()); | 162 DCHECK(prefs_key.empty()); |
| 145 // fall through | 163 // fall through |
| 146 case SOURCE_HISTOGRAMS_ATOMIC_FILE: | 164 case SOURCE_HISTOGRAMS_ATOMIC_FILE: |
| 147 source->path = path; | 165 source->path = path; |
| 148 break; | 166 break; |
| 149 case SOURCE_HISTOGRAMS_ATOMIC_DIR: | 167 case SOURCE_HISTOGRAMS_ATOMIC_DIR: |
| 150 source->directory = path; | 168 source->directory = path; |
| 151 break; | 169 break; |
| 152 } | 170 } |
| 153 | 171 |
| 154 // |prefs_key| may be empty if the caller does not wish to persist the | 172 // |prefs_key| may be empty if the caller does not wish to persist the |
| 155 // state across instances of the program. | 173 // state across instances of the program. |
| 156 if (pref_service_ && !prefs_key.empty()) { | 174 if (pref_service_ && !prefs_key.empty()) { |
| 157 source->last_seen = base::Time::FromInternalValue( | 175 source->last_seen = base::Time::FromInternalValue( |
| 158 pref_service_->GetInt64(metrics::prefs::kMetricsLastSeenPrefix + | 176 pref_service_->GetInt64(metrics::prefs::kMetricsLastSeenPrefix + |
| 159 source->prefs_key)); | 177 source->prefs_key)); |
| 160 } | 178 } |
| 161 | 179 |
| 162 switch (source_association) { | 180 switch (source_association) { |
| 163 case ASSOCIATE_CURRENT_RUN: | 181 case ASSOCIATE_CURRENT_RUN: |
| 182 case ASSOCIATE_INTERNAL_PROFILE: |
| 164 sources_to_check_.push_back(std::move(source)); | 183 sources_to_check_.push_back(std::move(source)); |
| 165 break; | 184 break; |
| 166 case ASSOCIATE_PREVIOUS_RUN: | 185 case ASSOCIATE_PREVIOUS_RUN: |
| 186 case ASSOCIATE_INTERNAL_PROFILE_OR_PREVIOUS_RUN: |
| 167 DCHECK_EQ(SOURCE_HISTOGRAMS_ATOMIC_FILE, source->type); | 187 DCHECK_EQ(SOURCE_HISTOGRAMS_ATOMIC_FILE, source->type); |
| 168 sources_for_previous_run_.push_back(std::move(source)); | 188 sources_for_previous_run_.push_back(std::move(source)); |
| 169 break; | 189 break; |
| 170 } | 190 } |
| 171 } | 191 } |
| 172 | 192 |
| 173 // static | 193 // static |
| 174 void FileMetricsProvider::RegisterPrefs(PrefRegistrySimple* prefs, | 194 void FileMetricsProvider::RegisterPrefs(PrefRegistrySimple* prefs, |
| 175 const base::StringPiece prefs_key) { | 195 const base::StringPiece prefs_key) { |
| 176 prefs->RegisterInt64Pref(metrics::prefs::kMetricsLastSeenPrefix + | 196 prefs->RegisterInt64Pref(metrics::prefs::kMetricsLastSeenPrefix + |
| (...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 243 if (oldest_file_path.empty()) | 263 if (oldest_file_path.empty()) |
| 244 return false; | 264 return false; |
| 245 | 265 |
| 246 // Set the active file to be the oldest modified file that has not yet | 266 // Set the active file to be the oldest modified file that has not yet |
| 247 // been read. | 267 // been read. |
| 248 source->path = std::move(oldest_file_path); | 268 source->path = std::move(oldest_file_path); |
| 249 return true; | 269 return true; |
| 250 } | 270 } |
| 251 | 271 |
| 252 // static | 272 // static |
| 273 void FileMetricsProvider::FinishedWithSource(SourceInfo* source, |
| 274 AccessResult result) { |
| 275 // Different source types require different post-processing. |
| 276 switch (source->type) { |
| 277 case SOURCE_HISTOGRAMS_ATOMIC_FILE: |
| 278 case SOURCE_HISTOGRAMS_ATOMIC_DIR: |
| 279 // Done with this file so delete the allocator and its owned file. |
| 280 source->allocator.reset(); |
| 281 // Remove the file if has been recorded. This prevents them from |
| 282 // accumulating or also being recorded by different instances of |
| 283 // the browser. |
| 284 if (result == ACCESS_RESULT_SUCCESS || |
| 285 result == ACCESS_RESULT_NOT_MODIFIED) { |
| 286 DeleteFileWhenPossible(source->path); |
| 287 } |
| 288 break; |
| 289 case SOURCE_HISTOGRAMS_ACTIVE_FILE: |
| 290 // Keep the allocator open so it doesn't have to be re-mapped each |
| 291 // time. This also allows the contents to be merged on-demand. |
| 292 break; |
| 293 } |
| 294 } |
| 295 |
| 296 // static |
| 253 void FileMetricsProvider::CheckAndMergeMetricSourcesOnTaskRunner( | 297 void FileMetricsProvider::CheckAndMergeMetricSourcesOnTaskRunner( |
| 254 SourceInfoList* sources) { | 298 SourceInfoList* sources) { |
| 255 // This method has all state information passed in |sources| and is intended | 299 // This method has all state information passed in |sources| and is intended |
| 256 // to run on a worker thread rather than the UI thread. | 300 // to run on a worker thread rather than the UI thread. |
| 257 for (std::unique_ptr<SourceInfo>& source : *sources) { | 301 for (std::unique_ptr<SourceInfo>& source : *sources) { |
| 258 AccessResult result = CheckAndMapMetricSource(source.get()); | 302 AccessResult result = CheckAndMapMetricSource(source.get()); |
| 259 | 303 |
| 260 // Some results are not reported in order to keep the dashboard clean. | 304 // Some results are not reported in order to keep the dashboard clean. |
| 261 if (result != ACCESS_RESULT_DOESNT_EXIST && | 305 if (result != ACCESS_RESULT_DOESNT_EXIST && |
| 262 result != ACCESS_RESULT_NOT_MODIFIED) { | 306 result != ACCESS_RESULT_NOT_MODIFIED) { |
| 263 UMA_HISTOGRAM_ENUMERATION( | 307 UMA_HISTOGRAM_ENUMERATION( |
| 264 "UMA.FileMetricsProvider.AccessResult", result, ACCESS_RESULT_MAX); | 308 "UMA.FileMetricsProvider.AccessResult", result, ACCESS_RESULT_MAX); |
| 265 } | 309 } |
| 266 | 310 |
| 311 // Metrics associated with internal profiles have to be fetched directly |
| 312 // so just keep the mapping for use by the main thread. |
| 313 if (source->association == ASSOCIATE_INTERNAL_PROFILE) |
| 314 continue; |
| 315 |
| 267 // Mapping was successful. Merge it. | 316 // Mapping was successful. Merge it. |
| 268 if (result == ACCESS_RESULT_SUCCESS) { | 317 if (result == ACCESS_RESULT_SUCCESS) { |
| 269 MergeHistogramDeltasFromSource(source.get()); | 318 MergeHistogramDeltasFromSource(source.get()); |
| 270 DCHECK(source->read_complete); | 319 DCHECK(source->read_complete); |
| 271 } | 320 } |
| 272 | 321 |
| 273 // Different source types require different post-processing. | 322 // All done with this source. |
| 274 switch (source->type) { | 323 FinishedWithSource(source.get(), result); |
| 275 case SOURCE_HISTOGRAMS_ATOMIC_FILE: | |
| 276 case SOURCE_HISTOGRAMS_ATOMIC_DIR: | |
| 277 // Done with this file so delete the allocator and its owned file. | |
| 278 source->allocator.reset(); | |
| 279 // Remove the file if has been recorded. This prevents them from | |
| 280 // accumulating or also being recorded by different instances of | |
| 281 // the browser. | |
| 282 if (result == ACCESS_RESULT_SUCCESS || | |
| 283 result == ACCESS_RESULT_NOT_MODIFIED) { | |
| 284 base::DeleteFile(source->path, /*recursive=*/false); | |
| 285 } | |
| 286 break; | |
| 287 case SOURCE_HISTOGRAMS_ACTIVE_FILE: | |
| 288 // Keep the allocator open so it doesn't have to be re-mapped each | |
| 289 // time. This also allows the contents to be merged on-demand. | |
| 290 break; | |
| 291 } | |
| 292 } | 324 } |
| 293 } | 325 } |
| 294 | 326 |
| 295 // This method has all state information passed in |source| and is intended | 327 // This method has all state information passed in |source| and is intended |
| 296 // to run on a worker thread rather than the UI thread. | 328 // to run on a worker thread rather than the UI thread. |
| 297 // static | 329 // static |
| 298 FileMetricsProvider::AccessResult FileMetricsProvider::CheckAndMapMetricSource( | 330 FileMetricsProvider::AccessResult FileMetricsProvider::CheckAndMapMetricSource( |
| 299 SourceInfo* source) { | 331 SourceInfo* source) { |
| 332 // If source was read, clean up after it. |
| 333 if (source->read_complete) |
| 334 FinishedWithSource(source, ACCESS_RESULT_SUCCESS); |
| 335 source->read_complete = false; |
| 300 DCHECK(!source->allocator); | 336 DCHECK(!source->allocator); |
| 301 source->read_complete = false; | |
| 302 | 337 |
| 303 // If the source is a directory, look for files within it. | 338 // If the source is a directory, look for files within it. |
| 304 if (!source->directory.empty() && !LocateNextFileInDirectory(source)) | 339 if (!source->directory.empty() && !LocateNextFileInDirectory(source)) |
| 305 return ACCESS_RESULT_DOESNT_EXIST; | 340 return ACCESS_RESULT_DOESNT_EXIST; |
| 306 | 341 |
| 307 // Do basic validation on the file metadata. | 342 // Do basic validation on the file metadata. |
| 308 base::File::Info info; | 343 base::File::Info info; |
| 309 if (!base::GetFileInfo(source->path, &info)) | 344 if (!base::GetFileInfo(source->path, &info)) |
| 310 return ACCESS_RESULT_DOESNT_EXIST; | 345 return ACCESS_RESULT_DOESNT_EXIST; |
| 311 | 346 |
| (...skipping 118 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 430 // try again immediately to see if more is available (in a directory of | 465 // try again immediately to see if more is available (in a directory of |
| 431 // files). Otherwise, remember the source for checking again at a later time. | 466 // files). Otherwise, remember the source for checking again at a later time. |
| 432 bool did_read = false; | 467 bool did_read = false; |
| 433 for (auto iter = checked->begin(); iter != checked->end();) { | 468 for (auto iter = checked->begin(); iter != checked->end();) { |
| 434 auto temp = iter++; | 469 auto temp = iter++; |
| 435 SourceInfo* source = temp->get(); | 470 SourceInfo* source = temp->get(); |
| 436 if (source->read_complete) { | 471 if (source->read_complete) { |
| 437 RecordSourceAsRead(source); | 472 RecordSourceAsRead(source); |
| 438 did_read = true; | 473 did_read = true; |
| 439 } | 474 } |
| 440 if (source->allocator) | 475 if (source->allocator) { |
| 441 sources_mapped_.splice(sources_mapped_.end(), *checked, temp); | 476 if (source->association == ASSOCIATE_INTERNAL_PROFILE) { |
| 442 else | 477 sources_with_profile_.splice(sources_with_profile_.end(), *checked, |
| 478 temp); |
| 479 } else { |
| 480 sources_mapped_.splice(sources_mapped_.end(), *checked, temp); |
| 481 } |
| 482 } else { |
| 443 sources_to_check_.splice(sources_to_check_.end(), *checked, temp); | 483 sources_to_check_.splice(sources_to_check_.end(), *checked, temp); |
| 484 } |
| 444 } | 485 } |
| 445 | 486 |
| 446 // If a read was done, schedule another one immediately. In the case of a | 487 // If a read was done, schedule another one immediately. In the case of a |
| 447 // directory of files, this ensures that all entries get processed. It's | 488 // directory of files, this ensures that all entries get processed. It's |
| 448 // done here instead of as a loop in CheckAndMergeMetricSourcesOnTaskRunner | 489 // done here instead of as a loop in CheckAndMergeMetricSourcesOnTaskRunner |
| 449 // so that (a) it gives the disk a rest and (b) testing of individual reads | 490 // so that (a) it gives the disk a rest and (b) testing of individual reads |
| 450 // is possible. | 491 // is possible. |
| 451 if (did_read) | 492 if (did_read) |
| 452 ScheduleSourcesCheck(); | 493 ScheduleSourcesCheck(); |
| 453 } | 494 } |
| (...skipping 26 matching lines...) Expand all Loading... |
| 480 // Clear any data for initial metrics since they're always reported | 521 // Clear any data for initial metrics since they're always reported |
| 481 // before the first call to this method. It couldn't be released after | 522 // before the first call to this method. It couldn't be released after |
| 482 // being reported in RecordInitialHistogramSnapshots because the data | 523 // being reported in RecordInitialHistogramSnapshots because the data |
| 483 // will continue to be used by the caller after that method returns. Once | 524 // will continue to be used by the caller after that method returns. Once |
| 484 // here, though, all actions to be done on the data have been completed. | 525 // here, though, all actions to be done on the data have been completed. |
| 485 for (const std::unique_ptr<SourceInfo>& source : sources_for_previous_run_) | 526 for (const std::unique_ptr<SourceInfo>& source : sources_for_previous_run_) |
| 486 DeleteFileAsync(source->path); | 527 DeleteFileAsync(source->path); |
| 487 sources_for_previous_run_.clear(); | 528 sources_for_previous_run_.clear(); |
| 488 } | 529 } |
| 489 | 530 |
| 531 bool FileMetricsProvider::ProvideIndependentMetrics( |
| 532 SystemProfileProto* system_profile_proto, |
| 533 base::HistogramSnapshotManager* snapshot_manager) { |
| 534 DCHECK(thread_checker_.CalledOnValidThread()); |
| 535 |
| 536 while (!sources_with_profile_.empty()) { |
| 537 SourceInfo* source = sources_with_profile_.begin()->get(); |
| 538 DCHECK(source->allocator); |
| 539 |
| 540 bool success = false; |
| 541 RecordEmbeddedProfileResult(EMBEDDED_PROFILE_ATTEMPT); |
| 542 if (PersistentSystemProfile::GetSystemProfile( |
| 543 *source->allocator->memory_allocator(), system_profile_proto)) { |
| 544 RecordHistogramSnapshotsFromSource(snapshot_manager, source); |
| 545 success = true; |
| 546 RecordEmbeddedProfileResult(EMBEDDED_PROFILE_FOUND); |
| 547 } else { |
| 548 RecordEmbeddedProfileResult(EMBEDDED_PROFILE_DROPPED); |
| 549 } |
| 550 |
| 551 // Regardless of whether this source was successfully recorded, it is never |
| 552 // read again. |
| 553 source->read_complete = true; |
| 554 RecordSourceAsRead(source); |
| 555 sources_to_check_.splice(sources_to_check_.end(), sources_with_profile_, |
| 556 sources_with_profile_.begin()); |
| 557 if (success) |
| 558 return true; |
| 559 } |
| 560 |
| 561 return false; |
| 562 } |
| 563 |
| 490 bool FileMetricsProvider::HasInitialStabilityMetrics() { | 564 bool FileMetricsProvider::HasInitialStabilityMetrics() { |
| 491 DCHECK(thread_checker_.CalledOnValidThread()); | 565 DCHECK(thread_checker_.CalledOnValidThread()); |
| 492 | 566 |
| 493 // Measure the total time spent checking all sources as well as the time | 567 // Measure the total time spent checking all sources as well as the time |
| 494 // per individual file. This method is called during startup and thus blocks | 568 // per individual file. This method is called during startup and thus blocks |
| 495 // the initial showing of the browser window so it's important to know the | 569 // the initial showing of the browser window so it's important to know the |
| 496 // total delay. | 570 // total delay. |
| 497 SCOPED_UMA_HISTOGRAM_TIMER("UMA.FileMetricsProvider.InitialCheckTime.Total"); | 571 SCOPED_UMA_HISTOGRAM_TIMER("UMA.FileMetricsProvider.InitialCheckTime.Total"); |
| 498 | 572 |
| 499 // Check all sources for previous run to see if they need to be read. | 573 // Check all sources for previous run to see if they need to be read. |
| (...skipping 14 matching lines...) Expand all Loading... |
| 514 // If it couldn't be accessed, remove it from the list. There is only ever | 588 // If it couldn't be accessed, remove it from the list. There is only ever |
| 515 // one chance to record it so no point keeping it around for later. Also | 589 // one chance to record it so no point keeping it around for later. Also |
| 516 // mark it as having been read since uploading it with a future browser | 590 // mark it as having been read since uploading it with a future browser |
| 517 // run would associate it with the then-previous run which would no longer | 591 // run would associate it with the then-previous run which would no longer |
| 518 // be the run from which it came. | 592 // be the run from which it came. |
| 519 if (result != ACCESS_RESULT_SUCCESS) { | 593 if (result != ACCESS_RESULT_SUCCESS) { |
| 520 DCHECK(!source->allocator); | 594 DCHECK(!source->allocator); |
| 521 RecordSourceAsRead(source); | 595 RecordSourceAsRead(source); |
| 522 DeleteFileAsync(source->path); | 596 DeleteFileAsync(source->path); |
| 523 sources_for_previous_run_.erase(temp); | 597 sources_for_previous_run_.erase(temp); |
| 598 continue; |
| 599 } |
| 600 |
| 601 DCHECK(source->allocator); |
| 602 |
| 603 // If the source should be associated with an existing internal profile, |
| 604 // move it to |sources_with_profile_| for later upload. |
| 605 if (source->association == ASSOCIATE_INTERNAL_PROFILE_OR_PREVIOUS_RUN) { |
| 606 if (PersistentSystemProfile::HasSystemProfile( |
| 607 *source->allocator->memory_allocator())) { |
| 608 RecordEmbeddedProfileResult(EMBEDDED_PROFILE_ATTEMPT); |
| 609 RecordEmbeddedProfileResult(EMBEDDED_PROFILE_FALLBACK); |
| 610 sources_with_profile_.splice(sources_with_profile_.end(), |
| 611 sources_for_previous_run_, temp); |
| 612 } |
| 524 } | 613 } |
| 525 } | 614 } |
| 526 | 615 |
| 527 return !sources_for_previous_run_.empty(); | 616 return !sources_for_previous_run_.empty(); |
| 528 } | 617 } |
| 529 | 618 |
| 530 void FileMetricsProvider::RecordInitialHistogramSnapshots( | 619 void FileMetricsProvider::RecordInitialHistogramSnapshots( |
| 531 base::HistogramSnapshotManager* snapshot_manager) { | 620 base::HistogramSnapshotManager* snapshot_manager) { |
| 532 DCHECK(thread_checker_.CalledOnValidThread()); | 621 DCHECK(thread_checker_.CalledOnValidThread()); |
| 533 | 622 |
| (...skipping 29 matching lines...) Expand all Loading... |
| 563 // important to know how much total "jank" may be introduced. | 652 // important to know how much total "jank" may be introduced. |
| 564 SCOPED_UMA_HISTOGRAM_TIMER("UMA.FileMetricsProvider.SnapshotTime.Total"); | 653 SCOPED_UMA_HISTOGRAM_TIMER("UMA.FileMetricsProvider.SnapshotTime.Total"); |
| 565 | 654 |
| 566 for (std::unique_ptr<SourceInfo>& source : sources_mapped_) { | 655 for (std::unique_ptr<SourceInfo>& source : sources_mapped_) { |
| 567 SCOPED_UMA_HISTOGRAM_TIMER("UMA.FileMetricsProvider.SnapshotTime.File"); | 656 SCOPED_UMA_HISTOGRAM_TIMER("UMA.FileMetricsProvider.SnapshotTime.File"); |
| 568 MergeHistogramDeltasFromSource(source.get()); | 657 MergeHistogramDeltasFromSource(source.get()); |
| 569 } | 658 } |
| 570 } | 659 } |
| 571 | 660 |
| 572 } // namespace metrics | 661 } // namespace metrics |
| OLD | NEW |