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 |