Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 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 "base/metrics/statistics_recorder.h" | 5 #include "base/metrics/statistics_recorder.h" |
| 6 | 6 |
| 7 #include <memory> | 7 #include <memory> |
| 8 | 8 |
| 9 #include "base/at_exit.h" | 9 #include "base/at_exit.h" |
| 10 #include "base/debug/leak_annotations.h" | 10 #include "base/debug/leak_annotations.h" |
| (...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 80 StatisticsRecorder::~StatisticsRecorder() { | 80 StatisticsRecorder::~StatisticsRecorder() { |
| 81 DCHECK(histograms_); | 81 DCHECK(histograms_); |
| 82 DCHECK(ranges_); | 82 DCHECK(ranges_); |
| 83 | 83 |
| 84 // Clean out what this object created and then restore what existed before. | 84 // Clean out what this object created and then restore what existed before. |
| 85 Reset(); | 85 Reset(); |
| 86 base::AutoLock auto_lock(lock_.Get()); | 86 base::AutoLock auto_lock(lock_.Get()); |
| 87 histograms_ = existing_histograms_.release(); | 87 histograms_ = existing_histograms_.release(); |
| 88 callbacks_ = existing_callbacks_.release(); | 88 callbacks_ = existing_callbacks_.release(); |
| 89 ranges_ = existing_ranges_.release(); | 89 ranges_ = existing_ranges_.release(); |
| 90 providers_ = existing_providers_.release(); | |
| 90 } | 91 } |
| 91 | 92 |
| 92 // static | 93 // static |
| 93 void StatisticsRecorder::Initialize() { | 94 void StatisticsRecorder::Initialize() { |
| 94 // Tests sometimes create local StatisticsRecorders in order to provide a | 95 // Tests sometimes create local StatisticsRecorders in order to provide a |
| 95 // contained environment of histograms that can be later discarded. If a | 96 // contained environment of histograms that can be later discarded. If a |
| 96 // true global instance gets created in this environment then it will | 97 // true global instance gets created in this environment then it will |
| 97 // eventually get disconnected when the local instance destructs and | 98 // eventually get disconnected when the local instance destructs and |
| 98 // restores the previous state, resulting in no StatisticsRecorder at all. | 99 // restores the previous state, resulting in no StatisticsRecorder at all. |
| 99 // The global lazy instance, however, will remain valid thus ensuring that | 100 // The global lazy instance, however, will remain valid thus ensuring that |
| 100 // another never gets installed via this method. If a |histograms_| map | 101 // another never gets installed via this method. If a |histograms_| map |
| 101 // exists then assume the StatisticsRecorder is already "initialized". | 102 // exists then assume the StatisticsRecorder is already "initialized". |
| 102 if (histograms_) | 103 if (histograms_) |
| 103 return; | 104 return; |
| 104 | 105 |
| 105 // Ensure that an instance of the StatisticsRecorder object is created. | 106 // Ensure that an instance of the StatisticsRecorder object is created. |
| 106 g_statistics_recorder_.Get(); | 107 g_statistics_recorder_.Get(); |
| 107 } | 108 } |
| 108 | 109 |
| 109 // static | 110 // static |
| 110 bool StatisticsRecorder::IsActive() { | 111 bool StatisticsRecorder::IsActive() { |
| 111 base::AutoLock auto_lock(lock_.Get()); | 112 base::AutoLock auto_lock(lock_.Get()); |
| 112 return histograms_ != nullptr; | 113 return histograms_ != nullptr; |
| 113 } | 114 } |
| 114 | 115 |
| 115 // static | 116 // static |
| 117 void StatisticsRecorder::RegisterHistogramProvider( | |
| 118 const WeakPtr<HistogramProvider>& provider) { | |
| 119 providers_->push_back(provider); | |
| 120 } | |
| 121 | |
| 122 // static | |
| 116 HistogramBase* StatisticsRecorder::RegisterOrDeleteDuplicate( | 123 HistogramBase* StatisticsRecorder::RegisterOrDeleteDuplicate( |
| 117 HistogramBase* histogram) { | 124 HistogramBase* histogram) { |
| 118 HistogramBase* histogram_to_delete = nullptr; | 125 HistogramBase* histogram_to_delete = nullptr; |
| 119 HistogramBase* histogram_to_return = nullptr; | 126 HistogramBase* histogram_to_return = nullptr; |
| 120 { | 127 { |
| 121 base::AutoLock auto_lock(lock_.Get()); | 128 base::AutoLock auto_lock(lock_.Get()); |
| 122 if (!histograms_) { | 129 if (!histograms_) { |
| 123 histogram_to_return = histogram; | 130 histogram_to_return = histogram; |
| 124 | 131 |
| 125 // As per crbug.com/79322 the histograms are intentionally leaked, so we | 132 // As per crbug.com/79322 the histograms are intentionally leaked, so we |
| (...skipping 174 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 300 if (!histograms_) | 307 if (!histograms_) |
| 301 return nullptr; | 308 return nullptr; |
| 302 | 309 |
| 303 HistogramMap::iterator it = histograms_->find(name); | 310 HistogramMap::iterator it = histograms_->find(name); |
| 304 if (histograms_->end() == it) | 311 if (histograms_->end() == it) |
| 305 return nullptr; | 312 return nullptr; |
| 306 return it->second; | 313 return it->second; |
| 307 } | 314 } |
| 308 | 315 |
| 309 // static | 316 // static |
| 317 void StatisticsRecorder::ImportProvidedHistograms() { | |
|
Alexei Svitkine (slow)
2017/01/27 16:22:03
Can you add a thread check here?
bcwhite
2017/01/27 18:05:31
Not sure if I can because base/ doesn't generally
Alexei Svitkine (slow)
2017/01/27 18:06:57
Can you add base::ThreadChecker as a member and us
bcwhite
2017/01/27 18:12:57
These are static methods so there's no object to h
| |
| 318 if (!providers_) | |
| 319 return; | |
| 320 | |
| 321 // Merge histogram data from each provider in turn. | |
| 322 for (const WeakPtr<HistogramProvider>& provider : *providers_) { | |
| 323 if (provider) | |
|
Alexei Svitkine (slow)
2017/01/27 16:22:03
Nit: Maybe add a comment here to mention this is c
bcwhite
2017/01/27 18:05:31
Done.
| |
| 324 provider->MergeHistogramDeltas(); | |
| 325 } | |
| 326 } | |
| 327 | |
| 328 // static | |
| 310 StatisticsRecorder::HistogramIterator StatisticsRecorder::begin( | 329 StatisticsRecorder::HistogramIterator StatisticsRecorder::begin( |
| 311 bool include_persistent) { | 330 bool include_persistent) { |
| 312 DCHECK(histograms_); | 331 DCHECK(histograms_); |
| 313 ImportGlobalPersistentHistograms(); | 332 ImportGlobalPersistentHistograms(); |
| 314 | 333 |
| 315 HistogramMap::iterator iter_begin; | 334 HistogramMap::iterator iter_begin; |
| 316 { | 335 { |
| 317 base::AutoLock auto_lock(lock_.Get()); | 336 base::AutoLock auto_lock(lock_.Get()); |
| 318 iter_begin = histograms_->begin(); | 337 iter_begin = histograms_->begin(); |
| 319 } | 338 } |
| (...skipping 19 matching lines...) Expand all Loading... | |
| 339 g_statistics_recorder_.Get().InitLogOnShutdownWithoutLock(); | 358 g_statistics_recorder_.Get().InitLogOnShutdownWithoutLock(); |
| 340 } | 359 } |
| 341 | 360 |
| 342 // static | 361 // static |
| 343 void StatisticsRecorder::GetSnapshot(const std::string& query, | 362 void StatisticsRecorder::GetSnapshot(const std::string& query, |
| 344 Histograms* snapshot) { | 363 Histograms* snapshot) { |
| 345 base::AutoLock auto_lock(lock_.Get()); | 364 base::AutoLock auto_lock(lock_.Get()); |
| 346 if (!histograms_) | 365 if (!histograms_) |
| 347 return; | 366 return; |
| 348 | 367 |
| 368 ImportGlobalPersistentHistograms(); | |
| 369 | |
| 349 for (const auto& entry : *histograms_) { | 370 for (const auto& entry : *histograms_) { |
| 350 if (entry.second->histogram_name().find(query) != std::string::npos) | 371 if (entry.second->histogram_name().find(query) != std::string::npos) |
| 351 snapshot->push_back(entry.second); | 372 snapshot->push_back(entry.second); |
| 352 } | 373 } |
| 353 } | 374 } |
| 354 | 375 |
| 355 // static | 376 // static |
| 356 bool StatisticsRecorder::SetCallback( | 377 bool StatisticsRecorder::SetCallback( |
| 357 const std::string& name, | 378 const std::string& name, |
| 358 const StatisticsRecorder::OnSampleCallback& cb) { | 379 const StatisticsRecorder::OnSampleCallback& cb) { |
| (...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 451 | 472 |
| 452 // This singleton instance should be started during the single threaded portion | 473 // This singleton instance should be started during the single threaded portion |
| 453 // of main(), and hence it is not thread safe. It initializes globals to | 474 // of main(), and hence it is not thread safe. It initializes globals to |
| 454 // provide support for all future calls. | 475 // provide support for all future calls. |
| 455 StatisticsRecorder::StatisticsRecorder() { | 476 StatisticsRecorder::StatisticsRecorder() { |
| 456 base::AutoLock auto_lock(lock_.Get()); | 477 base::AutoLock auto_lock(lock_.Get()); |
| 457 | 478 |
| 458 existing_histograms_.reset(histograms_); | 479 existing_histograms_.reset(histograms_); |
| 459 existing_callbacks_.reset(callbacks_); | 480 existing_callbacks_.reset(callbacks_); |
| 460 existing_ranges_.reset(ranges_); | 481 existing_ranges_.reset(ranges_); |
| 482 existing_providers_.reset(providers_); | |
| 461 | 483 |
| 462 histograms_ = new HistogramMap; | 484 histograms_ = new HistogramMap; |
| 463 callbacks_ = new CallbackMap; | 485 callbacks_ = new CallbackMap; |
| 464 ranges_ = new RangesMap; | 486 ranges_ = new RangesMap; |
| 487 providers_ = new HistogramProviders; | |
| 465 | 488 |
| 466 InitLogOnShutdownWithoutLock(); | 489 InitLogOnShutdownWithoutLock(); |
| 467 } | 490 } |
| 468 | 491 |
| 469 void StatisticsRecorder::InitLogOnShutdownWithoutLock() { | 492 void StatisticsRecorder::InitLogOnShutdownWithoutLock() { |
| 470 if (!vlog_initialized_ && VLOG_IS_ON(1)) { | 493 if (!vlog_initialized_ && VLOG_IS_ON(1)) { |
| 471 vlog_initialized_ = true; | 494 vlog_initialized_ = true; |
| 472 AtExitManager::RegisterCallback(&DumpHistogramsToVlog, this); | 495 AtExitManager::RegisterCallback(&DumpHistogramsToVlog, this); |
| 473 } | 496 } |
| 474 } | 497 } |
| 475 | 498 |
| 476 // static | 499 // static |
| 477 void StatisticsRecorder::Reset() { | 500 void StatisticsRecorder::Reset() { |
| 478 | 501 |
| 479 std::unique_ptr<HistogramMap> histograms_deleter; | 502 std::unique_ptr<HistogramMap> histograms_deleter; |
| 480 std::unique_ptr<CallbackMap> callbacks_deleter; | 503 std::unique_ptr<CallbackMap> callbacks_deleter; |
| 481 std::unique_ptr<RangesMap> ranges_deleter; | 504 std::unique_ptr<RangesMap> ranges_deleter; |
| 505 std::unique_ptr<HistogramProviders> providers_deleter; | |
| 482 { | 506 { |
| 483 base::AutoLock auto_lock(lock_.Get()); | 507 base::AutoLock auto_lock(lock_.Get()); |
| 484 histograms_deleter.reset(histograms_); | 508 histograms_deleter.reset(histograms_); |
| 485 callbacks_deleter.reset(callbacks_); | 509 callbacks_deleter.reset(callbacks_); |
| 486 ranges_deleter.reset(ranges_); | 510 ranges_deleter.reset(ranges_); |
| 511 providers_deleter.reset(providers_); | |
| 487 histograms_ = nullptr; | 512 histograms_ = nullptr; |
| 488 callbacks_ = nullptr; | 513 callbacks_ = nullptr; |
| 489 ranges_ = nullptr; | 514 ranges_ = nullptr; |
| 515 providers_ = nullptr; | |
| 490 } | 516 } |
| 491 // We are going to leak the histograms and the ranges. | 517 // We are going to leak the histograms and the ranges. |
| 492 } | 518 } |
| 493 | 519 |
| 494 // static | 520 // static |
| 495 void StatisticsRecorder::DumpHistogramsToVlog(void* instance) { | 521 void StatisticsRecorder::DumpHistogramsToVlog(void* instance) { |
| 496 std::string output; | 522 std::string output; |
| 497 StatisticsRecorder::WriteGraph(std::string(), &output); | 523 StatisticsRecorder::WriteGraph(std::string(), &output); |
| 498 VLOG(1) << output; | 524 VLOG(1) << output; |
| 499 } | 525 } |
| 500 | 526 |
| 501 | 527 |
| 502 // static | 528 // static |
| 503 StatisticsRecorder::HistogramMap* StatisticsRecorder::histograms_ = nullptr; | 529 StatisticsRecorder::HistogramMap* StatisticsRecorder::histograms_ = nullptr; |
| 504 // static | 530 // static |
| 505 StatisticsRecorder::CallbackMap* StatisticsRecorder::callbacks_ = nullptr; | 531 StatisticsRecorder::CallbackMap* StatisticsRecorder::callbacks_ = nullptr; |
| 506 // static | 532 // static |
| 507 StatisticsRecorder::RangesMap* StatisticsRecorder::ranges_ = nullptr; | 533 StatisticsRecorder::RangesMap* StatisticsRecorder::ranges_ = nullptr; |
| 508 // static | 534 // static |
| 535 StatisticsRecorder::HistogramProviders* StatisticsRecorder::providers_; | |
| 536 // static | |
| 509 base::LazyInstance<base::Lock>::Leaky StatisticsRecorder::lock_ = | 537 base::LazyInstance<base::Lock>::Leaky StatisticsRecorder::lock_ = |
| 510 LAZY_INSTANCE_INITIALIZER; | 538 LAZY_INSTANCE_INITIALIZER; |
| 511 | 539 |
| 512 } // namespace base | 540 } // namespace base |
| OLD | NEW |