From 567d30ea4b9b9a9c96e7ed2dd61ee166f615cfd7 Mon Sep 17 00:00:00 2001 From: "kaiwang@chromium.org" Date: Fri, 13 Jul 2012 21:48:29 +0000 Subject: [PATCH] Move StatisticsRecorder out of histogram.cc/h for further refactoring. Review URL: https://chromiumcodereview.appspot.com/10703037 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@146659 0039d316-1c4b-4281-b951-d872f2087c98 --- base/base.gypi | 2 + base/message_loop.cc | 1 + base/metrics/histogram.cc | 276 +------------------- base/metrics/histogram.h | 85 ------ base/metrics/histogram_snapshot_manager.cc | 2 + base/metrics/histogram_unittest.cc | 4 +- base/metrics/statistics_recorder.cc | 285 +++++++++++++++++++++ base/metrics/statistics_recorder.h | 105 ++++++++ .../chrome_browser_application_mac_unittest.mm | 3 +- .../extensions/api/metrics/metrics_apitest.cc | 1 + chrome/browser/metrics/metrics_service.cc | 1 + ...ttp_pipelining_compatibility_client_unittest.cc | 1 + .../default_search_provider_change_browsertest.cc | 1 + .../safe_browsing_service_browsertest.cc | 3 - .../ui/startup/startup_browser_creator_impl.cc | 1 + chrome/browser/ui/webui/about_ui.cc | 1 + chrome/renderer/chrome_render_process_observer.cc | 1 + chrome_frame/metrics_service.cc | 1 + content/browser/browser_main_runner.cc | 1 + content/browser/histogram_internals_request_job.cc | 1 + content/common/child_histogram_message_filter.cc | 1 + content/renderer/renderer_main.cc | 1 + net/base/run_all_unittests.cc | 2 +- net/curvecp/curvecp_transfer_unittest.cc | 4 +- net/disk_cache/stats_histogram.cc | 3 +- .../socket_stream_metrics_unittest.cc | 3 +- net/url_request/url_request_throttler_unittest.cc | 1 + 27 files changed, 421 insertions(+), 370 deletions(-) create mode 100644 base/metrics/statistics_recorder.cc create mode 100644 base/metrics/statistics_recorder.h diff --git a/base/base.gypi b/base/base.gypi index 697195300a24..92d66fa7517f 100644 --- a/base/base.gypi +++ b/base/base.gypi @@ -239,6 +239,8 @@ 'metrics/histogram_flattener.h', 'metrics/histogram_snapshot_manager.cc', 'metrics/histogram_snapshot_manager.h', + 'metrics/statistics_recorder.cc', + 'metrics/statistics_recorder.h', 'metrics/stats_counters.cc', 'metrics/stats_counters.h', 'metrics/stats_table.cc', diff --git a/base/message_loop.cc b/base/message_loop.cc index f3bb4bb1a74b..6b994bc0c330 100644 --- a/base/message_loop.cc +++ b/base/message_loop.cc @@ -16,6 +16,7 @@ #include "base/message_loop_proxy_impl.h" #include "base/message_pump_default.h" #include "base/metrics/histogram.h" +#include "base/metrics/statistics_recorder.h" #include "base/run_loop.h" #include "base/third_party/dynamic_annotations/dynamic_annotations.h" #include "base/thread_task_runner_handle.h" diff --git a/base/metrics/histogram.cc b/base/metrics/histogram.cc index 923ac9c3120e..e176e8f3dc4e 100644 --- a/base/metrics/histogram.cc +++ b/base/metrics/histogram.cc @@ -14,8 +14,8 @@ #include #include -#include "base/debug/leak_annotations.h" #include "base/logging.h" +#include "base/metrics/statistics_recorder.h" #include "base/pickle.h" #include "base/stringprintf.h" #include "base/synchronization/lock.h" @@ -74,13 +74,6 @@ typedef Histogram::Count Count; // static const size_t Histogram::kBucketCount_MAX = 16384u; -// Collect the number of histograms created. -static uint32 number_of_histograms_ = 0; -// Collect the number of vectors saved because of caching ranges. -static uint32 number_of_vectors_saved_ = 0; -// Collect the number of ranges_ elements saved because of caching ranges. -static size_t saved_ranges_size_ = 0; - Histogram* Histogram::FactoryGet(const std::string& name, Sample minimum, Sample maximum, @@ -1037,265 +1030,6 @@ double CustomHistogram::GetBucketSize(Count current, size_t i) const { return 1; } -//------------------------------------------------------------------------------ -// The next section handles global (central) support for all histograms, as well -// as startup/teardown of this service. -//------------------------------------------------------------------------------ - -// This singleton instance should be started during the single threaded portion -// of main(), and hence it is not thread safe. It initializes globals to -// provide support for all future calls. -StatisticsRecorder::StatisticsRecorder() { - DCHECK(!histograms_); - if (lock_ == NULL) { - // This will leak on purpose. It's the only way to make sure we won't race - // against the static uninitialization of the module while one of our - // static methods relying on the lock get called at an inappropriate time - // during the termination phase. Since it's a static data member, we will - // leak one per process, which would be similar to the instance allocated - // during static initialization and released only on process termination. - lock_ = new base::Lock; - } - base::AutoLock auto_lock(*lock_); - histograms_ = new HistogramMap; - ranges_ = new RangesMap; -} - -StatisticsRecorder::~StatisticsRecorder() { - DCHECK(histograms_ && lock_); - - if (dump_on_exit_) { - std::string output; - WriteGraph("", &output); - DLOG(INFO) << output; - } - // Clean up. - HistogramMap* histograms = NULL; - { - base::AutoLock auto_lock(*lock_); - histograms = histograms_; - histograms_ = NULL; - } - RangesMap* ranges = NULL; - { - base::AutoLock auto_lock(*lock_); - ranges = ranges_; - ranges_ = NULL; - } - // We are going to leak the histograms and the ranges. - delete histograms; - delete ranges; - // 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. -} - -// static -bool StatisticsRecorder::IsActive() { - if (lock_ == NULL) - return false; - base::AutoLock auto_lock(*lock_); - return NULL != histograms_; -} - -Histogram* StatisticsRecorder::RegisterOrDeleteDuplicate(Histogram* histogram) { - // As per crbug.com/79322 the histograms are intentionally leaked, so we need - // to annotate them. Because ANNOTATE_LEAKING_OBJECT_PTR may be used only once - // for an object, the duplicates should not be annotated. - // Callers are responsible for not calling RegisterOrDeleteDuplicate(ptr) - // twice if (lock_ == NULL) || (!histograms_). - DCHECK(histogram->HasValidRangeChecksum()); - if (lock_ == NULL) { - ANNOTATE_LEAKING_OBJECT_PTR(histogram); // see crbug.com/79322 - return histogram; - } - base::AutoLock auto_lock(*lock_); - if (!histograms_) { - ANNOTATE_LEAKING_OBJECT_PTR(histogram); // see crbug.com/79322 - return histogram; - } - const std::string name = histogram->histogram_name(); - HistogramMap::iterator it = histograms_->find(name); - // Avoid overwriting a previous registration. - if (histograms_->end() == it) { - (*histograms_)[name] = histogram; - ANNOTATE_LEAKING_OBJECT_PTR(histogram); // see crbug.com/79322 - RegisterOrDeleteDuplicateRanges(histogram); - ++number_of_histograms_; - } else { - delete histogram; // We already have one by this name. - histogram = it->second; - } - return histogram; -} - -// static -void StatisticsRecorder::RegisterOrDeleteDuplicateRanges(Histogram* histogram) { - DCHECK(histogram); - CachedRanges* histogram_ranges = histogram->cached_ranges(); - DCHECK(histogram_ranges); - uint32 checksum = histogram->range_checksum(); - histogram_ranges->SetRangeChecksum(checksum); - - RangesMap::iterator ranges_it = ranges_->find(checksum); - if (ranges_->end() == ranges_it) { - // Register the new CachedRanges. - std::list* checksum_matching_list( - new std::list()); - checksum_matching_list->push_front(histogram_ranges); - (*ranges_)[checksum] = checksum_matching_list; - return; - } - - // Use the registered CachedRanges if the registered CachedRanges has same - // ranges_ as |histogram|'s CachedRanges. - std::list* checksum_matching_list = ranges_it->second; - std::list::iterator checksum_matching_list_it; - for (checksum_matching_list_it = checksum_matching_list->begin(); - checksum_matching_list_it != checksum_matching_list->end(); - ++checksum_matching_list_it) { - CachedRanges* existing_histogram_ranges = *checksum_matching_list_it; - DCHECK(existing_histogram_ranges); - if (existing_histogram_ranges->Equals(histogram_ranges)) { - histogram->set_cached_ranges(existing_histogram_ranges); - ++number_of_vectors_saved_; - saved_ranges_size_ += histogram_ranges->size(); - delete histogram_ranges; - return; - } - } - - // We haven't found a CachedRanges which has the same ranges. Register the - // new CachedRanges. - DCHECK(checksum_matching_list_it == checksum_matching_list->end()); - checksum_matching_list->push_front(histogram_ranges); -} - -// static -void StatisticsRecorder::CollectHistogramStats(const std::string& suffix) { - static int uma_upload_attempt = 0; - ++uma_upload_attempt; - if (uma_upload_attempt == 1) { - UMA_HISTOGRAM_COUNTS_10000( - "Histogram.SharedRange.Count.FirstUpload." + suffix, - number_of_histograms_); - UMA_HISTOGRAM_COUNTS_10000( - "Histogram.SharedRange.RangesSaved.FirstUpload." + suffix, - number_of_vectors_saved_); - UMA_HISTOGRAM_COUNTS( - "Histogram.SharedRange.ElementsSaved.FirstUpload." + suffix, - static_cast(saved_ranges_size_)); - number_of_histograms_ = 0; - number_of_vectors_saved_ = 0; - saved_ranges_size_ = 0; - return; - } - if (uma_upload_attempt == 2) { - UMA_HISTOGRAM_COUNTS_10000( - "Histogram.SharedRange.Count.SecondUpload." + suffix, - number_of_histograms_); - UMA_HISTOGRAM_COUNTS_10000( - "Histogram.SharedRange.RangesSaved.SecondUpload." + suffix, - number_of_vectors_saved_); - UMA_HISTOGRAM_COUNTS( - "Histogram.SharedRange.ElementsSaved.SecondUpload." + suffix, - static_cast(saved_ranges_size_)); - number_of_histograms_ = 0; - number_of_vectors_saved_ = 0; - saved_ranges_size_ = 0; - return; - } - UMA_HISTOGRAM_COUNTS_10000( - "Histogram.SharedRange.Count.RestOfUploads." + suffix, - number_of_histograms_); - UMA_HISTOGRAM_COUNTS_10000( - "Histogram.SharedRange.RangesSaved.RestOfUploads." + suffix, - number_of_vectors_saved_); - UMA_HISTOGRAM_COUNTS( - "Histogram.SharedRange.ElementsSaved.RestOfUploads." + suffix, - static_cast(saved_ranges_size_)); -} - -// static -void StatisticsRecorder::WriteHTMLGraph(const std::string& query, - std::string* output) { - if (!IsActive()) - return; - - Histograms snapshot; - GetSnapshot(query, &snapshot); - for (Histograms::iterator it = snapshot.begin(); - it != snapshot.end(); - ++it) { - (*it)->WriteHTMLGraph(output); - output->append("


"); - } -} - -// static -void StatisticsRecorder::WriteGraph(const std::string& query, - std::string* output) { - if (!IsActive()) - return; - if (query.length()) - StringAppendF(output, "Collections of histograms for %s\n", query.c_str()); - else - output->append("Collections of all histograms\n"); - - Histograms snapshot; - GetSnapshot(query, &snapshot); - for (Histograms::iterator it = snapshot.begin(); - it != snapshot.end(); - ++it) { - (*it)->WriteAscii(true, "\n", output); - output->append("\n"); - } -} - -// static -void StatisticsRecorder::GetHistograms(Histograms* output) { - if (lock_ == NULL) - return; - base::AutoLock auto_lock(*lock_); - if (!histograms_) - return; - for (HistogramMap::iterator it = histograms_->begin(); - histograms_->end() != it; - ++it) { - DCHECK_EQ(it->first, it->second->histogram_name()); - output->push_back(it->second); - } -} - -bool StatisticsRecorder::FindHistogram(const std::string& name, - Histogram** histogram) { - if (lock_ == NULL) - return false; - base::AutoLock auto_lock(*lock_); - if (!histograms_) - return false; - HistogramMap::iterator it = histograms_->find(name); - if (histograms_->end() == it) - return false; - *histogram = it->second; - return true; -} - -// private static -void StatisticsRecorder::GetSnapshot(const std::string& query, - Histograms* snapshot) { - if (lock_ == NULL) - return; - base::AutoLock auto_lock(*lock_); - if (!histograms_) - return; - for (HistogramMap::iterator it = histograms_->begin(); - histograms_->end() != it; - ++it) { - if (it->first.find(query) != std::string::npos) - snapshot->push_back(it->second); - } -} - CachedRanges::CachedRanges(size_t bucket_count, int initial_value) : ranges_(bucket_count, initial_value), range_checksum_(0) { @@ -1322,12 +1056,4 @@ bool CachedRanges::Equals(CachedRanges* other) const { return true; } -// static -StatisticsRecorder::HistogramMap* StatisticsRecorder::histograms_ = NULL; -// static -StatisticsRecorder::RangesMap* StatisticsRecorder::ranges_ = NULL; -// static -base::Lock* StatisticsRecorder::lock_ = NULL; -// static -bool StatisticsRecorder::dump_on_exit_ = false; } // namespace base diff --git a/base/metrics/histogram.h b/base/metrics/histogram.h index 39fe200bf0b6..735de556b6ed 100644 --- a/base/metrics/histogram.h +++ b/base/metrics/histogram.h @@ -40,7 +40,6 @@ #ifndef BASE_METRICS_HISTOGRAM_H_ #define BASE_METRICS_HISTOGRAM_H_ -#include #include #include #include @@ -774,90 +773,6 @@ class BASE_EXPORT CustomHistogram : public Histogram { DISALLOW_COPY_AND_ASSIGN(CustomHistogram); }; -//------------------------------------------------------------------------------ -// StatisticsRecorder handles all histograms in the system. It provides a -// general place for histograms to register, and supports a global API for -// accessing (i.e., dumping, or graphing) the data in all the histograms. - -class BASE_EXPORT StatisticsRecorder { - public: - typedef std::vector Histograms; - - StatisticsRecorder(); - - ~StatisticsRecorder(); - - // Find out if histograms can now be registered into our list. - static bool IsActive(); - - // Register, or add a new histogram to the collection of statistics. If an - // identically named histogram is already registered, then the argument - // |histogram| will deleted. The returned value is always the registered - // histogram (either the argument, or the pre-existing registered histogram). - static Histogram* RegisterOrDeleteDuplicate(Histogram* histogram); - - // Register, or add a new cached_ranges_ of |histogram|. If an identical - // cached_ranges_ is already registered, then the cached_ranges_ of - // |histogram| is deleted and the |histogram|'s cached_ranges_ is reset to the - // registered cached_ranges_. The cached_ranges_ of |histogram| is always the - // registered CachedRanges (either the argument's cached_ranges_, or the - // pre-existing registered cached_ranges_). - static void RegisterOrDeleteDuplicateRanges(Histogram* histogram); - - // Method for collecting stats about histograms created in browser and - // renderer processes. |suffix| is appended to histogram names. |suffix| could - // be either browser or renderer. - static void CollectHistogramStats(const std::string& suffix); - - // Methods for printing histograms. Only histograms which have query as - // a substring are written to output (an empty string will process all - // registered histograms). - static void WriteHTMLGraph(const std::string& query, std::string* output); - static void WriteGraph(const std::string& query, std::string* output); - - // Method for extracting histograms which were marked for use by UMA. - static void GetHistograms(Histograms* output); - - // Find a histogram by name. It matches the exact name. This method is thread - // safe. If a matching histogram is not found, then the |histogram| is - // not changed. - static bool FindHistogram(const std::string& query, Histogram** histogram); - - static bool dump_on_exit() { return dump_on_exit_; } - - static void set_dump_on_exit(bool enable) { dump_on_exit_ = enable; } - - // GetSnapshot copies some of the pointers to registered histograms into the - // caller supplied vector (Histograms). Only histograms with names matching - // query are returned. The query must be a substring of histogram name for its - // pointer to be copied. - static void GetSnapshot(const std::string& query, Histograms* snapshot); - - - private: - // We keep all registered histograms in a map, from name to histogram. - typedef std::map HistogramMap; - - // We keep all |cached_ranges_| in a map, from checksum to a list of - // |cached_ranges_|. Checksum is calculated from the |ranges_| in - // |cached_ranges_|. - typedef std::map*> RangesMap; - - static HistogramMap* histograms_; - - static RangesMap* ranges_; - - // lock protects access to the above map. - static base::Lock* lock_; - - // Dump all known histograms to log. - static bool dump_on_exit_; - - DISALLOW_COPY_AND_ASSIGN(StatisticsRecorder); -}; - -//------------------------------------------------------------------------------ - // CachedRanges stores the Ranges vector. Histograms that have same Ranges // vector will use the same CachedRanges object. class BASE_EXPORT CachedRanges { diff --git a/base/metrics/histogram_snapshot_manager.cc b/base/metrics/histogram_snapshot_manager.cc index b325f73e6842..9d9398d606a3 100644 --- a/base/metrics/histogram_snapshot_manager.cc +++ b/base/metrics/histogram_snapshot_manager.cc @@ -4,6 +4,8 @@ #include "base/metrics/histogram_snapshot_manager.h" +#include "base/metrics/statistics_recorder.h" + using base::Histogram; using base::StatisticsRecorder; diff --git a/base/metrics/histogram_unittest.cc b/base/metrics/histogram_unittest.cc index bd8a427f217b..51834605c62b 100644 --- a/base/metrics/histogram_unittest.cc +++ b/base/metrics/histogram_unittest.cc @@ -1,4 +1,4 @@ -// Copyright (c) 2011 The Chromium Authors. All rights reserved. +// Copyright (c) 2012 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. @@ -7,8 +7,10 @@ #include #include +#include "base/logging.h" #include "base/memory/scoped_ptr.h" #include "base/metrics/histogram.h" +#include "base/metrics/statistics_recorder.h" #include "base/time.h" #include "testing/gtest/include/gtest/gtest.h" diff --git a/base/metrics/statistics_recorder.cc b/base/metrics/statistics_recorder.cc new file mode 100644 index 000000000000..37b6f43ecccb --- /dev/null +++ b/base/metrics/statistics_recorder.cc @@ -0,0 +1,285 @@ +// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "base/metrics/statistics_recorder.h" + +#include "base/debug/leak_annotations.h" +#include "base/logging.h" +#include "base/metrics/histogram.h" +#include "base/stringprintf.h" +#include "base/synchronization/lock.h" + +namespace base { + +// Collect the number of histograms created. +static uint32 number_of_histograms_ = 0; +// Collect the number of vectors saved because of caching ranges. +static uint32 number_of_vectors_saved_ = 0; +// Collect the number of ranges_ elements saved because of caching ranges. +static size_t saved_ranges_size_ = 0; + +// This singleton instance should be started during the single threaded portion +// of main(), and hence it is not thread safe. It initializes globals to +// provide support for all future calls. +StatisticsRecorder::StatisticsRecorder() { + DCHECK(!histograms_); + if (lock_ == NULL) { + // This will leak on purpose. It's the only way to make sure we won't race + // against the static uninitialization of the module while one of our + // static methods relying on the lock get called at an inappropriate time + // during the termination phase. Since it's a static data member, we will + // leak one per process, which would be similar to the instance allocated + // during static initialization and released only on process termination. + lock_ = new base::Lock; + } + base::AutoLock auto_lock(*lock_); + histograms_ = new HistogramMap; + ranges_ = new RangesMap; +} + +StatisticsRecorder::~StatisticsRecorder() { + DCHECK(histograms_ && lock_); + + if (dump_on_exit_) { + std::string output; + WriteGraph("", &output); + DLOG(INFO) << output; + } + // Clean up. + HistogramMap* histograms = NULL; + { + base::AutoLock auto_lock(*lock_); + histograms = histograms_; + histograms_ = NULL; + } + RangesMap* ranges = NULL; + { + base::AutoLock auto_lock(*lock_); + ranges = ranges_; + ranges_ = NULL; + } + // We are going to leak the histograms and the ranges. + delete histograms; + delete ranges; + // 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. +} + +// static +bool StatisticsRecorder::IsActive() { + if (lock_ == NULL) + return false; + base::AutoLock auto_lock(*lock_); + return NULL != histograms_; +} + +Histogram* StatisticsRecorder::RegisterOrDeleteDuplicate(Histogram* histogram) { + // As per crbug.com/79322 the histograms are intentionally leaked, so we need + // to annotate them. Because ANNOTATE_LEAKING_OBJECT_PTR may be used only once + // for an object, the duplicates should not be annotated. + // Callers are responsible for not calling RegisterOrDeleteDuplicate(ptr) + // twice if (lock_ == NULL) || (!histograms_). + DCHECK(histogram->HasValidRangeChecksum()); + if (lock_ == NULL) { + ANNOTATE_LEAKING_OBJECT_PTR(histogram); // see crbug.com/79322 + return histogram; + } + base::AutoLock auto_lock(*lock_); + if (!histograms_) { + ANNOTATE_LEAKING_OBJECT_PTR(histogram); // see crbug.com/79322 + return histogram; + } + const std::string name = histogram->histogram_name(); + HistogramMap::iterator it = histograms_->find(name); + // Avoid overwriting a previous registration. + if (histograms_->end() == it) { + (*histograms_)[name] = histogram; + ANNOTATE_LEAKING_OBJECT_PTR(histogram); // see crbug.com/79322 + RegisterOrDeleteDuplicateRanges(histogram); + ++number_of_histograms_; + } else { + delete histogram; // We already have one by this name. + histogram = it->second; + } + return histogram; +} + +// static +void StatisticsRecorder::RegisterOrDeleteDuplicateRanges(Histogram* histogram) { + DCHECK(histogram); + CachedRanges* histogram_ranges = histogram->cached_ranges(); + DCHECK(histogram_ranges); + uint32 checksum = histogram->range_checksum(); + histogram_ranges->SetRangeChecksum(checksum); + + RangesMap::iterator ranges_it = ranges_->find(checksum); + if (ranges_->end() == ranges_it) { + // Register the new CachedRanges. + std::list* checksum_matching_list( + new std::list()); + checksum_matching_list->push_front(histogram_ranges); + (*ranges_)[checksum] = checksum_matching_list; + return; + } + + // Use the registered CachedRanges if the registered CachedRanges has same + // ranges_ as |histogram|'s CachedRanges. + std::list* checksum_matching_list = ranges_it->second; + std::list::iterator checksum_matching_list_it; + for (checksum_matching_list_it = checksum_matching_list->begin(); + checksum_matching_list_it != checksum_matching_list->end(); + ++checksum_matching_list_it) { + CachedRanges* existing_histogram_ranges = *checksum_matching_list_it; + DCHECK(existing_histogram_ranges); + if (existing_histogram_ranges->Equals(histogram_ranges)) { + histogram->set_cached_ranges(existing_histogram_ranges); + ++number_of_vectors_saved_; + saved_ranges_size_ += histogram_ranges->size(); + delete histogram_ranges; + return; + } + } + + // We haven't found a CachedRanges which has the same ranges. Register the + // new CachedRanges. + DCHECK(checksum_matching_list_it == checksum_matching_list->end()); + checksum_matching_list->push_front(histogram_ranges); +} + +// static +void StatisticsRecorder::CollectHistogramStats(const std::string& suffix) { + static int uma_upload_attempt = 0; + ++uma_upload_attempt; + if (uma_upload_attempt == 1) { + UMA_HISTOGRAM_COUNTS_10000( + "Histogram.SharedRange.Count.FirstUpload." + suffix, + number_of_histograms_); + UMA_HISTOGRAM_COUNTS_10000( + "Histogram.SharedRange.RangesSaved.FirstUpload." + suffix, + number_of_vectors_saved_); + UMA_HISTOGRAM_COUNTS( + "Histogram.SharedRange.ElementsSaved.FirstUpload." + suffix, + static_cast(saved_ranges_size_)); + number_of_histograms_ = 0; + number_of_vectors_saved_ = 0; + saved_ranges_size_ = 0; + return; + } + if (uma_upload_attempt == 2) { + UMA_HISTOGRAM_COUNTS_10000( + "Histogram.SharedRange.Count.SecondUpload." + suffix, + number_of_histograms_); + UMA_HISTOGRAM_COUNTS_10000( + "Histogram.SharedRange.RangesSaved.SecondUpload." + suffix, + number_of_vectors_saved_); + UMA_HISTOGRAM_COUNTS( + "Histogram.SharedRange.ElementsSaved.SecondUpload." + suffix, + static_cast(saved_ranges_size_)); + number_of_histograms_ = 0; + number_of_vectors_saved_ = 0; + saved_ranges_size_ = 0; + return; + } + UMA_HISTOGRAM_COUNTS_10000( + "Histogram.SharedRange.Count.RestOfUploads." + suffix, + number_of_histograms_); + UMA_HISTOGRAM_COUNTS_10000( + "Histogram.SharedRange.RangesSaved.RestOfUploads." + suffix, + number_of_vectors_saved_); + UMA_HISTOGRAM_COUNTS( + "Histogram.SharedRange.ElementsSaved.RestOfUploads." + suffix, + static_cast(saved_ranges_size_)); +} + +// static +void StatisticsRecorder::WriteHTMLGraph(const std::string& query, + std::string* output) { + if (!IsActive()) + return; + + Histograms snapshot; + GetSnapshot(query, &snapshot); + for (Histograms::iterator it = snapshot.begin(); + it != snapshot.end(); + ++it) { + (*it)->WriteHTMLGraph(output); + output->append("


"); + } +} + +// static +void StatisticsRecorder::WriteGraph(const std::string& query, + std::string* output) { + if (!IsActive()) + return; + if (query.length()) + StringAppendF(output, "Collections of histograms for %s\n", query.c_str()); + else + output->append("Collections of all histograms\n"); + + Histograms snapshot; + GetSnapshot(query, &snapshot); + for (Histograms::iterator it = snapshot.begin(); + it != snapshot.end(); + ++it) { + (*it)->WriteAscii(true, "\n", output); + output->append("\n"); + } +} + +// static +void StatisticsRecorder::GetHistograms(Histograms* output) { + if (lock_ == NULL) + return; + base::AutoLock auto_lock(*lock_); + if (!histograms_) + return; + for (HistogramMap::iterator it = histograms_->begin(); + histograms_->end() != it; + ++it) { + DCHECK_EQ(it->first, it->second->histogram_name()); + output->push_back(it->second); + } +} + +bool StatisticsRecorder::FindHistogram(const std::string& name, + Histogram** histogram) { + if (lock_ == NULL) + return false; + base::AutoLock auto_lock(*lock_); + if (!histograms_) + return false; + HistogramMap::iterator it = histograms_->find(name); + if (histograms_->end() == it) + return false; + *histogram = it->second; + return true; +} + +// private static +void StatisticsRecorder::GetSnapshot(const std::string& query, + Histograms* snapshot) { + if (lock_ == NULL) + return; + base::AutoLock auto_lock(*lock_); + if (!histograms_) + return; + for (HistogramMap::iterator it = histograms_->begin(); + histograms_->end() != it; + ++it) { + if (it->first.find(query) != std::string::npos) + snapshot->push_back(it->second); + } +} + +// static +StatisticsRecorder::HistogramMap* StatisticsRecorder::histograms_ = NULL; +// static +StatisticsRecorder::RangesMap* StatisticsRecorder::ranges_ = NULL; +// static +base::Lock* StatisticsRecorder::lock_ = NULL; +// static +bool StatisticsRecorder::dump_on_exit_ = false; + +} // namespace base diff --git a/base/metrics/statistics_recorder.h b/base/metrics/statistics_recorder.h new file mode 100644 index 000000000000..b947c5315f02 --- /dev/null +++ b/base/metrics/statistics_recorder.h @@ -0,0 +1,105 @@ +// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// StatisticsRecorder handles all histograms in the system. It provides a +// general place for histograms to register, and supports a global API for +// accessing (i.e., dumping, or graphing) the data in all the histograms. + +#ifndef BASE_METRICS_STATISTICS_RECORDER_H_ +#define BASE_METRICS_STATISTICS_RECORDER_H_ + +#include +#include +#include +#include + +#include "base/base_export.h" +#include "base/basictypes.h" + +namespace base { + +class CachedRanges; +class Histogram; +class Lock; + +class BASE_EXPORT StatisticsRecorder { + public: + typedef std::vector Histograms; + + StatisticsRecorder(); + + ~StatisticsRecorder(); + + // Find out if histograms can now be registered into our list. + static bool IsActive(); + + // Register, or add a new histogram to the collection of statistics. If an + // identically named histogram is already registered, then the argument + // |histogram| will deleted. The returned value is always the registered + // histogram (either the argument, or the pre-existing registered histogram). + static Histogram* RegisterOrDeleteDuplicate(Histogram* histogram); + + // Register, or add a new cached_ranges_ of |histogram|. If an identical + // cached_ranges_ is already registered, then the cached_ranges_ of + // |histogram| is deleted and the |histogram|'s cached_ranges_ is reset to the + // registered cached_ranges_. The cached_ranges_ of |histogram| is always the + // registered CachedRanges (either the argument's cached_ranges_, or the + // pre-existing registered cached_ranges_). + static void RegisterOrDeleteDuplicateRanges(Histogram* histogram); + + // Method for collecting stats about histograms created in browser and + // renderer processes. |suffix| is appended to histogram names. |suffix| could + // be either browser or renderer. + static void CollectHistogramStats(const std::string& suffix); + + // Methods for printing histograms. Only histograms which have query as + // a substring are written to output (an empty string will process all + // registered histograms). + static void WriteHTMLGraph(const std::string& query, std::string* output); + static void WriteGraph(const std::string& query, std::string* output); + + // Method for extracting histograms which were marked for use by UMA. + static void GetHistograms(Histograms* output); + + // Find a histogram by name. It matches the exact name. This method is thread + // safe. If a matching histogram is not found, then the |histogram| is + // not changed. + static bool FindHistogram(const std::string& query, Histogram** histogram); + + static bool dump_on_exit() { return dump_on_exit_; } + + static void set_dump_on_exit(bool enable) { dump_on_exit_ = enable; } + + // GetSnapshot copies some of the pointers to registered histograms into the + // caller supplied vector (Histograms). Only histograms with names matching + // query are returned. The query must be a substring of histogram name for its + // pointer to be copied. + static void GetSnapshot(const std::string& query, Histograms* snapshot); + + + private: + // We keep all registered histograms in a map, from name to histogram. + typedef std::map HistogramMap; + + // We keep all |cached_ranges_| in a map, from checksum to a list of + // |cached_ranges_|. Checksum is calculated from the |ranges_| in + // |cached_ranges_|. + typedef std::map*> RangesMap; + + static HistogramMap* histograms_; + + static RangesMap* ranges_; + + // lock protects access to the above map. + static base::Lock* lock_; + + // Dump all known histograms to log. + static bool dump_on_exit_; + + DISALLOW_COPY_AND_ASSIGN(StatisticsRecorder); +}; + +} // namespace base + +#endif // BASE_METRICS_STATISTICS_RECORDER_H_ diff --git a/chrome/browser/chrome_browser_application_mac_unittest.mm b/chrome/browser/chrome_browser_application_mac_unittest.mm index 9aa005a252ed..5c12f2768256 100644 --- a/chrome/browser/chrome_browser_application_mac_unittest.mm +++ b/chrome/browser/chrome_browser_application_mac_unittest.mm @@ -1,4 +1,4 @@ -// Copyright (c) 2011 The Chromium Authors. All rights reserved. +// Copyright (c) 2012 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. @@ -6,6 +6,7 @@ #import "base/mac/scoped_nsexception_enabler.h" #include "base/metrics/histogram.h" +#include "base/metrics/statistics_recorder.h" #import "chrome/browser/chrome_browser_application_mac.h" #include "testing/gtest/include/gtest/gtest.h" diff --git a/chrome/browser/extensions/api/metrics/metrics_apitest.cc b/chrome/browser/extensions/api/metrics/metrics_apitest.cc index 51949776aa0e..61edec7d16d3 100644 --- a/chrome/browser/extensions/api/metrics/metrics_apitest.cc +++ b/chrome/browser/extensions/api/metrics/metrics_apitest.cc @@ -5,6 +5,7 @@ #include #include "base/metrics/histogram.h" +#include "base/metrics/statistics_recorder.h" #include "chrome/browser/extensions/extension_apitest.h" #include "content/public/browser/notification_registrar.h" #include "content/public/browser/notification_service.h" diff --git a/chrome/browser/metrics/metrics_service.cc b/chrome/browser/metrics/metrics_service.cc index d2e5a84b198c..a688d419ef6e 100644 --- a/chrome/browser/metrics/metrics_service.cc +++ b/chrome/browser/metrics/metrics_service.cc @@ -152,6 +152,7 @@ #include "base/guid.h" #include "base/md5.h" #include "base/metrics/histogram.h" +#include "base/metrics/statistics_recorder.h" #include "base/rand_util.h" #include "base/string_number_conversions.h" #include "base/threading/platform_thread.h" diff --git a/chrome/browser/net/http_pipelining_compatibility_client_unittest.cc b/chrome/browser/net/http_pipelining_compatibility_client_unittest.cc index b60dabb28187..83598f99ece2 100644 --- a/chrome/browser/net/http_pipelining_compatibility_client_unittest.cc +++ b/chrome/browser/net/http_pipelining_compatibility_client_unittest.cc @@ -11,6 +11,7 @@ #include "base/basictypes.h" #include "base/message_loop.h" #include "base/metrics/histogram.h" +#include "base/metrics/statistics_recorder.h" #include "base/stl_util.h" #include "base/stringprintf.h" #include "content/public/test/test_browser_thread.h" diff --git a/chrome/browser/protector/default_search_provider_change_browsertest.cc b/chrome/browser/protector/default_search_provider_change_browsertest.cc index 9f32e9e58282..32d987e502e6 100644 --- a/chrome/browser/protector/default_search_provider_change_browsertest.cc +++ b/chrome/browser/protector/default_search_provider_change_browsertest.cc @@ -4,6 +4,7 @@ #include "base/memory/scoped_ptr.h" #include "base/metrics/histogram.h" +#include "base/metrics/statistics_recorder.h" #include "base/message_loop.h" #include "base/utf_string_conversions.h" #include "chrome/browser/protector/base_setting_change.h" diff --git a/chrome/browser/safe_browsing/safe_browsing_service_browsertest.cc b/chrome/browser/safe_browsing/safe_browsing_service_browsertest.cc index 066c9e99c945..d2a57f0c89b8 100644 --- a/chrome/browser/safe_browsing/safe_browsing_service_browsertest.cc +++ b/chrome/browser/safe_browsing/safe_browsing_service_browsertest.cc @@ -12,7 +12,6 @@ #include "base/command_line.h" #include "base/file_path.h" #include "base/memory/ref_counted.h" -#include "base/metrics/histogram.h" #include "base/path_service.h" #include "base/scoped_temp_dir.h" #include "base/string_split.h" @@ -42,8 +41,6 @@ #include "sql/statement.h" #include "testing/gmock/include/gmock/gmock.h" -using base::Histogram; -using base::StatisticsRecorder; using content::BrowserThread; using content::InterstitialPage; using content::WebContents; diff --git a/chrome/browser/ui/startup/startup_browser_creator_impl.cc b/chrome/browser/ui/startup/startup_browser_creator_impl.cc index 9db6e384b88e..5551980acd33 100644 --- a/chrome/browser/ui/startup/startup_browser_creator_impl.cc +++ b/chrome/browser/ui/startup/startup_browser_creator_impl.cc @@ -12,6 +12,7 @@ #include "base/lazy_instance.h" #include "base/memory/scoped_ptr.h" #include "base/metrics/histogram.h" +#include "base/metrics/statistics_recorder.h" #include "base/path_service.h" #include "base/string_number_conversions.h" #include "base/string_split.h" diff --git a/chrome/browser/ui/webui/about_ui.cc b/chrome/browser/ui/webui/about_ui.cc index e441804ad160..71980a63f6aa 100644 --- a/chrome/browser/ui/webui/about_ui.cc +++ b/chrome/browser/ui/webui/about_ui.cc @@ -18,6 +18,7 @@ #include "base/json/json_writer.h" #include "base/memory/ref_counted_memory.h" #include "base/memory/singleton.h" +#include "base/metrics/statistics_recorder.h" #include "base/metrics/stats_table.h" #include "base/path_service.h" #include "base/string_number_conversions.h" diff --git a/chrome/renderer/chrome_render_process_observer.cc b/chrome/renderer/chrome_render_process_observer.cc index 44b98d6e3b57..410636021581 100644 --- a/chrome/renderer/chrome_render_process_observer.cc +++ b/chrome/renderer/chrome_render_process_observer.cc @@ -12,6 +12,7 @@ #include "base/memory/weak_ptr.h" #include "base/metrics/field_trial.h" #include "base/metrics/histogram.h" +#include "base/metrics/statistics_recorder.h" #include "base/native_library.h" #include "base/path_service.h" #include "base/process_util.h" diff --git a/chrome_frame/metrics_service.cc b/chrome_frame/metrics_service.cc index 640e02ea7324..2a5e8b1c6698 100644 --- a/chrome_frame/metrics_service.cc +++ b/chrome_frame/metrics_service.cc @@ -50,6 +50,7 @@ #include "third_party/bzip2/bzlib.h" #endif +#include "base/metrics/statistics_recorder.h" #include "base/string16.h" #include "base/string_util.h" #include "base/stringprintf.h" diff --git a/content/browser/browser_main_runner.cc b/content/browser/browser_main_runner.cc index f85968315191..a2ecb744cea3 100644 --- a/content/browser/browser_main_runner.cc +++ b/content/browser/browser_main_runner.cc @@ -10,6 +10,7 @@ #include "base/debug/trace_event.h" #include "base/logging.h" #include "base/metrics/histogram.h" +#include "base/metrics/statistics_recorder.h" #include "content/browser/browser_main_loop.h" #include "content/browser/notification_service_impl.h" #include "content/common/child_process.h" diff --git a/content/browser/histogram_internals_request_job.cc b/content/browser/histogram_internals_request_job.cc index cb3c8fc84e7a..661464270ef8 100644 --- a/content/browser/histogram_internals_request_job.cc +++ b/content/browser/histogram_internals_request_job.cc @@ -5,6 +5,7 @@ #include "content/browser/histogram_internals_request_job.h" #include "base/metrics/histogram.h" +#include "base/metrics/statistics_recorder.h" #include "content/browser/histogram_synchronizer.h" #include "googleurl/src/gurl.h" #include "net/base/escape.h" diff --git a/content/common/child_histogram_message_filter.cc b/content/common/child_histogram_message_filter.cc index 5cc137c93888..79d4fdb50ced 100644 --- a/content/common/child_histogram_message_filter.cc +++ b/content/common/child_histogram_message_filter.cc @@ -8,6 +8,7 @@ #include "base/bind.h" #include "base/message_loop.h" +#include "base/metrics/statistics_recorder.h" #include "content/common/child_process.h" #include "content/common/child_process_messages.h" #include "content/common/child_thread.h" diff --git a/content/renderer/renderer_main.cc b/content/renderer/renderer_main.cc index b98030b5974d..18a64b7af5cb 100644 --- a/content/renderer/renderer_main.cc +++ b/content/renderer/renderer_main.cc @@ -12,6 +12,7 @@ #include "base/metrics/field_trial.h" #include "base/message_loop.h" #include "base/metrics/histogram.h" +#include "base/metrics/statistics_recorder.h" #include "base/metrics/stats_counters.h" #include "base/path_service.h" #include "base/process_util.h" diff --git a/net/base/run_all_unittests.cc b/net/base/run_all_unittests.cc index a139a8fc8468..131653f3b927 100644 --- a/net/base/run_all_unittests.cc +++ b/net/base/run_all_unittests.cc @@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +#include "base/metrics/statistics_recorder.h" #include "build/build_config.h" -#include "base/metrics/histogram.h" #include "crypto/nss_util.h" #include "net/base/net_test_suite.h" #include "net/socket/client_socket_pool_base.h" diff --git a/net/curvecp/curvecp_transfer_unittest.cc b/net/curvecp/curvecp_transfer_unittest.cc index 11c5d3f55d35..8180da4d7d22 100644 --- a/net/curvecp/curvecp_transfer_unittest.cc +++ b/net/curvecp/curvecp_transfer_unittest.cc @@ -1,4 +1,4 @@ -// Copyright (c) 2011 The Chromium Authors. All rights reserved. +// Copyright (c) 2012 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. @@ -6,7 +6,7 @@ #include "base/basictypes.h" #include "base/message_loop.h" -#include "base/metrics/histogram.h" +#include "base/metrics/statistics_recorder.h" #include "net/base/net_test_suite.h" #include "net/base/test_completion_callback.h" #include "net/curvecp/circular_buffer.h" diff --git a/net/disk_cache/stats_histogram.cc b/net/disk_cache/stats_histogram.cc index 943990a3b4a7..22343d504d55 100644 --- a/net/disk_cache/stats_histogram.cc +++ b/net/disk_cache/stats_histogram.cc @@ -1,4 +1,4 @@ -// Copyright (c) 2011 The Chromium Authors. All rights reserved. +// Copyright (c) 2012 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. @@ -6,6 +6,7 @@ #include "base/debug/leak_annotations.h" #include "base/logging.h" +#include "base/metrics/statistics_recorder.h" #include "net/disk_cache/stats.h" namespace disk_cache { diff --git a/net/socket_stream/socket_stream_metrics_unittest.cc b/net/socket_stream/socket_stream_metrics_unittest.cc index 5646302688fe..e0e11d615687 100644 --- a/net/socket_stream/socket_stream_metrics_unittest.cc +++ b/net/socket_stream/socket_stream_metrics_unittest.cc @@ -1,4 +1,4 @@ -// Copyright (c) 2011 The Chromium Authors. All rights reserved. +// Copyright (c) 2012 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. @@ -6,6 +6,7 @@ #include "base/basictypes.h" #include "base/metrics/histogram.h" +#include "base/metrics/statistics_recorder.h" #include "googleurl/src/gurl.h" #include "testing/gtest/include/gtest/gtest.h" #include "testing/platform_test.h" diff --git a/net/url_request/url_request_throttler_unittest.cc b/net/url_request/url_request_throttler_unittest.cc index 7809af61d0f8..a0827798cb0e 100644 --- a/net/url_request/url_request_throttler_unittest.cc +++ b/net/url_request/url_request_throttler_unittest.cc @@ -6,6 +6,7 @@ #include "base/memory/scoped_ptr.h" #include "base/metrics/histogram.h" +#include "base/metrics/statistics_recorder.h" #include "base/pickle.h" #include "base/stringprintf.h" #include "base/string_number_conversions.h" -- 2.11.4.GIT