| Index: base/metrics/statistics_recorder.cc
|
| diff --git a/base/metrics/statistics_recorder.cc b/base/metrics/statistics_recorder.cc
|
| index 85408e1fa496dec8dae7574213a3f3b21a1b123d..87ffa3dbcd04e78a724a3bec71b650726bdce79c 100644
|
| --- a/base/metrics/statistics_recorder.cc
|
| +++ b/base/metrics/statistics_recorder.cc
|
| @@ -10,6 +10,7 @@
|
| #include "base/logging.h"
|
| #include "base/memory/scoped_ptr.h"
|
| #include "base/metrics/histogram.h"
|
| +#include "base/stl_util.h"
|
| #include "base/strings/stringprintf.h"
|
| #include "base/synchronization/lock.h"
|
| #include "base/values.h"
|
| @@ -57,10 +58,19 @@ HistogramBase* StatisticsRecorder::RegisterOrDeleteDuplicate(
|
| histogram_to_return = histogram;
|
| } else {
|
| const std::string& name = histogram->histogram_name();
|
| - HistogramMap::iterator it = histograms_->find(name);
|
| + HistogramMap::iterator it = histograms_->find(HistogramNameRef(name));
|
| if (histograms_->end() == it) {
|
| - (*histograms_)[name] = histogram;
|
| + (*histograms_)[HistogramNameRef(name)] = histogram;
|
| ANNOTATE_LEAKING_OBJECT_PTR(histogram); // see crbug.com/79322
|
| + // If there are callbacks for this histogram, we set the kCallbackExists
|
| + // flag.
|
| + auto callback_iterator = callbacks_->find(name);
|
| + if (callback_iterator != callbacks_->end()) {
|
| + if (!callback_iterator->second.is_null())
|
| + histogram->SetFlags(HistogramBase::kCallbackExists);
|
| + else
|
| + histogram->ClearFlags(HistogramBase::kCallbackExists);
|
| + }
|
| histogram_to_return = histogram;
|
| } else if (histogram == it->second) {
|
| // The histogram was registered before.
|
| @@ -190,7 +200,7 @@ void StatisticsRecorder::GetHistograms(Histograms* output) {
|
| return;
|
|
|
| for (const auto& entry : *histograms_) {
|
| - DCHECK_EQ(entry.first, entry.second->histogram_name());
|
| + DCHECK_EQ(entry.first.name_, entry.second->histogram_name());
|
| output->push_back(entry.second);
|
| }
|
| }
|
| @@ -219,12 +229,64 @@ HistogramBase* StatisticsRecorder::FindHistogram(const std::string& name) {
|
| if (histograms_ == NULL)
|
| return NULL;
|
|
|
| - HistogramMap::iterator it = histograms_->find(name);
|
| + HistogramMap::iterator it = histograms_->find(HistogramNameRef(name));
|
| if (histograms_->end() == it)
|
| return NULL;
|
| return it->second;
|
| }
|
|
|
| +// static
|
| +bool StatisticsRecorder::SetCallback(
|
| + const std::string& name,
|
| + const StatisticsRecorder::OnSampleCallback& cb) {
|
| + DCHECK(!cb.is_null());
|
| + if (lock_ == NULL)
|
| + return false;
|
| + base::AutoLock auto_lock(*lock_);
|
| + if (histograms_ == NULL)
|
| + return false;
|
| +
|
| + if (ContainsKey(*callbacks_, name))
|
| + return false;
|
| + callbacks_->insert(std::make_pair(name, cb));
|
| +
|
| + auto histogram_iterator = histograms_->find(HistogramNameRef(name));
|
| + if (histogram_iterator != histograms_->end())
|
| + histogram_iterator->second->SetFlags(HistogramBase::kCallbackExists);
|
| +
|
| + return true;
|
| +}
|
| +
|
| +// static
|
| +void StatisticsRecorder::ClearCallback(const std::string& name) {
|
| + if (lock_ == NULL)
|
| + return;
|
| + base::AutoLock auto_lock(*lock_);
|
| + if (histograms_ == NULL)
|
| + return;
|
| +
|
| + callbacks_->erase(name);
|
| +
|
| + // We also clear the flag from the histogram (if it exists).
|
| + auto histogram_iterator = histograms_->find(HistogramNameRef(name));
|
| + if (histogram_iterator != histograms_->end())
|
| + histogram_iterator->second->ClearFlags(HistogramBase::kCallbackExists);
|
| +}
|
| +
|
| +// static
|
| +StatisticsRecorder::OnSampleCallback StatisticsRecorder::FindCallback(
|
| + const std::string& name) {
|
| + if (lock_ == NULL)
|
| + return OnSampleCallback();
|
| + base::AutoLock auto_lock(*lock_);
|
| + if (histograms_ == NULL)
|
| + return OnSampleCallback();
|
| +
|
| + auto callback_iterator = callbacks_->find(name);
|
| + return callback_iterator != callbacks_->end() ? callback_iterator->second
|
| + : OnSampleCallback();
|
| +}
|
| +
|
| // private static
|
| void StatisticsRecorder::GetSnapshot(const std::string& query,
|
| Histograms* snapshot) {
|
| @@ -235,7 +297,7 @@ void StatisticsRecorder::GetSnapshot(const std::string& query,
|
| return;
|
|
|
| for (const auto& entry : *histograms_) {
|
| - if (entry.first.find(query) != std::string::npos)
|
| + if (entry.first.name_.find(query) != std::string::npos)
|
| snapshot->push_back(entry.second);
|
| }
|
| }
|
| @@ -256,6 +318,7 @@ StatisticsRecorder::StatisticsRecorder() {
|
| }
|
| base::AutoLock auto_lock(*lock_);
|
| histograms_ = new HistogramMap;
|
| + callbacks_ = new CallbackMap;
|
| ranges_ = new RangesMap;
|
|
|
| if (VLOG_IS_ON(1))
|
| @@ -274,14 +337,17 @@ StatisticsRecorder::~StatisticsRecorder() {
|
|
|
| // Clean up.
|
| scoped_ptr<HistogramMap> histograms_deleter;
|
| + scoped_ptr<CallbackMap> callbacks_deleter;
|
| scoped_ptr<RangesMap> ranges_deleter;
|
| // We don't delete lock_ on purpose to avoid having to properly protect
|
| // against it going away after we checked for NULL in the static methods.
|
| {
|
| base::AutoLock auto_lock(*lock_);
|
| histograms_deleter.reset(histograms_);
|
| + callbacks_deleter.reset(callbacks_);
|
| ranges_deleter.reset(ranges_);
|
| histograms_ = NULL;
|
| + callbacks_ = NULL;
|
| ranges_ = NULL;
|
| }
|
| // We are going to leak the histograms and the ranges.
|
| @@ -291,6 +357,8 @@ StatisticsRecorder::~StatisticsRecorder() {
|
| // static
|
| StatisticsRecorder::HistogramMap* StatisticsRecorder::histograms_ = NULL;
|
| // static
|
| +StatisticsRecorder::CallbackMap* StatisticsRecorder::callbacks_ = NULL;
|
| +// static
|
| StatisticsRecorder::RangesMap* StatisticsRecorder::ranges_ = NULL;
|
| // static
|
| base::Lock* StatisticsRecorder::lock_ = NULL;
|
|
|