diff options
author | bcwhite <bcwhite@chromium.org> | 2016-03-16 10:25:41 -0700 |
---|---|---|
committer | Commit bot <commit-bot@chromium.org> | 2016-03-16 17:27:24 +0000 |
commit | d723c25e72442b9381023224d3db0ed12ae3210d (patch) | |
tree | 29c9aa415391bad8d66f8cb2048e714ad963cff5 | |
parent | ea79f96b9cd4b36bc0df5e3676fe2de4d63e95e4 (diff) | |
download | chromium_src-d723c25e72442b9381023224d3db0ed12ae3210d.zip chromium_src-d723c25e72442b9381023224d3db0ed12ae3210d.tar.gz chromium_src-d723c25e72442b9381023224d3db0ed12ae3210d.tar.bz2 |
Report histogram creation results.
Add a new histogram that reports information about all the
histograms created in different procesesses, their types,
and what flags were set.
BUG=546019
TBR=grt
grt: single instantiating call in installer_metrics.cc
Review URL: https://codereview.chromium.org/1726873002
Cr-Commit-Position: refs/heads/master@{#381482}
-rw-r--r-- | base/metrics/histogram.cc | 8 | ||||
-rw-r--r-- | base/metrics/histogram_base.cc | 71 | ||||
-rw-r--r-- | base/metrics/histogram_base.h | 54 | ||||
-rw-r--r-- | base/metrics/histogram_base_unittest.cc | 77 | ||||
-rw-r--r-- | base/metrics/persistent_histogram_allocator.cc | 5 | ||||
-rw-r--r-- | base/metrics/sparse_histogram.cc | 3 | ||||
-rw-r--r-- | base/metrics/statistics_recorder.cc | 27 | ||||
-rw-r--r-- | base/metrics/statistics_recorder.h | 8 | ||||
-rw-r--r-- | chrome/installer/setup/installer_metrics.cc | 4 | ||||
-rw-r--r-- | content/app/content_main_runner.cc | 3 | ||||
-rw-r--r-- | tools/metrics/histograms/histograms.xml | 30 |
11 files changed, 272 insertions, 18 deletions
diff --git a/base/metrics/histogram.cc b/base/metrics/histogram.cc index e8d851b..cd6d6be 100644 --- a/base/metrics/histogram.cc +++ b/base/metrics/histogram.cc @@ -216,9 +216,15 @@ HistogramBase* Histogram::Factory::Build() { allocator->FinalizeHistogram(histogram_ref, histogram == tentative_histogram_ptr); } + + // Update report on created histograms. + ReportHistogramActivity(*histogram, HISTOGRAM_CREATED); + } else { + // Update report on lookup histograms. + ReportHistogramActivity(*histogram, HISTOGRAM_LOOKUP); } - DCHECK_EQ(histogram_type_, histogram->GetHistogramType()); + DCHECK_EQ(histogram_type_, histogram->GetHistogramType()) << name_; if (bucket_count_ != 0 && !histogram->HasConstructionArguments(minimum_, maximum_, bucket_count_)) { // The construction arguments do not match the existing histogram. This can diff --git a/base/metrics/histogram_base.cc b/base/metrics/histogram_base.cc index 3a40e68..bf0a14a 100644 --- a/base/metrics/histogram_base.cc +++ b/base/metrics/histogram_base.cc @@ -34,9 +34,8 @@ std::string HistogramTypeToString(HistogramType type) { return "CUSTOM_HISTOGRAM"; case SPARSE_HISTOGRAM: return "SPARSE_HISTOGRAM"; - default: - NOTREACHED(); } + NOTREACHED(); return "UNKNOWN"; } @@ -62,6 +61,7 @@ HistogramBase* DeserializeHistogramInfo(PickleIterator* iter) { } const HistogramBase::Sample HistogramBase::kSampleType_MAX = INT_MAX; +HistogramBase* HistogramBase::report_histogram_ = nullptr; HistogramBase::HistogramBase(const std::string& name) : histogram_name_(name), @@ -122,6 +122,30 @@ void HistogramBase::WriteJSON(std::string* output) const { serializer.Serialize(root); } +// static +void HistogramBase::EnableActivityReportHistogram( + const std::string& process_type) { + DCHECK(!report_histogram_); + size_t existing = StatisticsRecorder::GetHistogramCount(); + if (existing != 0) { + DLOG(WARNING) << existing + << " histograms were created before reporting was enabled."; + } + + std::string name = + "UMA.Histograms.Activity" + + (process_type.empty() ? process_type : "." + process_type); + + // Calling FactoryGet() here rather than using a histogram-macro works + // around some problems with tests that could end up seeing the results + // histogram when not expected due to a bad interaction between + // HistogramTester and StatisticsRecorder. + report_histogram_ = LinearHistogram::FactoryGet( + name, 1, HISTOGRAM_REPORT_MAX, HISTOGRAM_REPORT_MAX + 1, + kUmaTargetedHistogramFlag); + report_histogram_->Add(HISTOGRAM_REPORT_CREATED); +} + void HistogramBase::FindAndRunCallback(HistogramBase::Sample sample) const { if ((flags() & kCallbackExists) == 0) return; @@ -163,4 +187,47 @@ void HistogramBase::WriteAsciiBucketValue(Count current, StringAppendF(output, " (%d = %3.1f%%)", current, current/scaled_sum); } +// static +void HistogramBase::ReportHistogramActivity(const HistogramBase& histogram, + ReportActivity activity) { + if (!report_histogram_) + return; + + const int32_t flags = histogram.flags_; + HistogramReport report_type = HISTOGRAM_REPORT_MAX; + switch (activity) { + case HISTOGRAM_CREATED: + report_histogram_->Add(HISTOGRAM_REPORT_HISTOGRAM_CREATED); + switch (histogram.GetHistogramType()) { + case HISTOGRAM: + report_type = HISTOGRAM_REPORT_TYPE_LOGARITHMIC; + break; + case LINEAR_HISTOGRAM: + report_type = HISTOGRAM_REPORT_TYPE_LINEAR; + break; + case BOOLEAN_HISTOGRAM: + report_type = HISTOGRAM_REPORT_TYPE_BOOLEAN; + break; + case CUSTOM_HISTOGRAM: + report_type = HISTOGRAM_REPORT_TYPE_CUSTOM; + break; + case SPARSE_HISTOGRAM: + report_type = HISTOGRAM_REPORT_TYPE_SPARSE; + break; + } + report_histogram_->Add(report_type); + if (flags & kIsPersistent) + report_histogram_->Add(HISTOGRAM_REPORT_FLAG_PERSISTENT); + if ((flags & kUmaStabilityHistogramFlag) == kUmaStabilityHistogramFlag) + report_histogram_->Add(HISTOGRAM_REPORT_FLAG_UMA_STABILITY); + else if (flags & kUmaTargetedHistogramFlag) + report_histogram_->Add(HISTOGRAM_REPORT_FLAG_UMA_TARGETED); + break; + + case HISTOGRAM_LOOKUP: + report_histogram_->Add(HISTOGRAM_REPORT_HISTOGRAM_LOOKUP); + break; + } +} + } // namespace base diff --git a/base/metrics/histogram_base.h b/base/metrics/histogram_base.h index 6817629..f11befd 100644 --- a/base/metrics/histogram_base.h +++ b/base/metrics/histogram_base.h @@ -30,7 +30,7 @@ class Pickle; class PickleIterator; //////////////////////////////////////////////////////////////////////////////// -// These enums are used to facilitate deserialization of histograms from other +// This enum is used to facilitate deserialization of histograms from other // processes into the browser. If you create another class that inherits from // HistogramBase, add new histogram types and names below. @@ -44,6 +44,39 @@ enum HistogramType { std::string HistogramTypeToString(HistogramType type); +// This enum is used for reporting how many histograms and of what types and +// variations are being created. It has to be in the main .h file so it is +// visible to files that define the various histogram types. +enum HistogramReport { + // Count the number of reports created. The other counts divided by this + // number will give the average per run of the program. + HISTOGRAM_REPORT_CREATED = 0, + + // Count the total number of histograms created. It is the limit against + // which all others are compared. + HISTOGRAM_REPORT_HISTOGRAM_CREATED = 1, + + // Count the total number of histograms looked-up. It's better to cache + // the result of a single lookup rather than do it repeatedly. + HISTOGRAM_REPORT_HISTOGRAM_LOOKUP = 2, + + // These count the individual histogram types. This must follow the order + // of HistogramType above. + HISTOGRAM_REPORT_TYPE_LOGARITHMIC = 3, + HISTOGRAM_REPORT_TYPE_LINEAR = 4, + HISTOGRAM_REPORT_TYPE_BOOLEAN = 5, + HISTOGRAM_REPORT_TYPE_CUSTOM = 6, + HISTOGRAM_REPORT_TYPE_SPARSE = 7, + + // These indicate the individual flags that were set. + HISTOGRAM_REPORT_FLAG_UMA_TARGETED = 8, + HISTOGRAM_REPORT_FLAG_UMA_STABILITY = 9, + HISTOGRAM_REPORT_FLAG_PERSISTENT = 10, + + // This must be last. + HISTOGRAM_REPORT_MAX = 11 +}; + // Create or find existing histogram that matches the pickled info. // Returns NULL if the pickled data has problems. BASE_EXPORT HistogramBase* DeserializeHistogramInfo(base::PickleIterator* iter); @@ -178,7 +211,17 @@ class BASE_EXPORT HistogramBase { // customize the output. void WriteJSON(std::string* output) const; + // This enables a histogram that reports the what types of histograms are + // created and their flags. It must be called while still single-threaded. + // + // IMPORTANT: Callers must update tools/metrics/histograms/histograms.xml + // with the following histogram: + // UMA.Histograms.process_type.Creations + static void EnableActivityReportHistogram(const std::string& process_type); + protected: + enum ReportActivity { HISTOGRAM_CREATED, HISTOGRAM_LOOKUP }; + // Subclasses should implement this function to make SerializeInfo work. virtual bool SerializeInfoImpl(base::Pickle* pickle) const = 0; @@ -210,7 +253,16 @@ class BASE_EXPORT HistogramBase { // passing |sample| as the parameter. void FindAndRunCallback(Sample sample) const; + // Update report with an |activity| that occurred for |histogram|. + static void ReportHistogramActivity(const HistogramBase& histogram, + ReportActivity activicty); + + // Retrieves the global histogram reporting what histograms are created. + static HistogramBase* report_histogram_; + private: + friend class HistogramBaseTest; + const std::string histogram_name_; AtomicCount flags_; diff --git a/base/metrics/histogram_base_unittest.cc b/base/metrics/histogram_base_unittest.cc index 2d6b6df..6b41597 100644 --- a/base/metrics/histogram_base_unittest.cc +++ b/base/metrics/histogram_base_unittest.cc @@ -18,19 +18,29 @@ class HistogramBaseTest : public testing::Test { HistogramBaseTest() { // Each test will have a clean state (no Histogram / BucketRanges // registered). - statistics_recorder_ = NULL; ResetStatisticsRecorder(); } - ~HistogramBaseTest() override { delete statistics_recorder_; } + ~HistogramBaseTest() override { + HistogramBase::report_histogram_ = nullptr; + } void ResetStatisticsRecorder() { - delete statistics_recorder_; - statistics_recorder_ = new StatisticsRecorder(); + // It is necessary to fully destruct any existing StatisticsRecorder + // before creating a new one. + statistics_recorder_.reset(); + statistics_recorder_.reset(new StatisticsRecorder()); + } + + HistogramBase* GetCreationReportHistogram(const std::string& name) { + HistogramBase::EnableActivityReportHistogram(name); + return HistogramBase::report_histogram_; } private: - StatisticsRecorder* statistics_recorder_; + scoped_ptr<StatisticsRecorder> statistics_recorder_; + + DISALLOW_COPY_AND_ASSIGN(HistogramBaseTest); }; TEST_F(HistogramBaseTest, DeserializeHistogram) { @@ -152,4 +162,61 @@ TEST_F(HistogramBaseTest, DeserializeSparseHistogram) { EXPECT_EQ(0, deserialized->flags()); } +TEST_F(HistogramBaseTest, CreationReportHistogram) { + // Enabled creation report. Itself is not included in the report. + HistogramBase* report = GetCreationReportHistogram("CreationReportTest"); + ASSERT_TRUE(report); + + std::vector<HistogramBase::Sample> ranges; + ranges.push_back(1); + ranges.push_back(2); + ranges.push_back(4); + ranges.push_back(8); + ranges.push_back(10); + + // Create all histogram types and verify counts. + Histogram::FactoryGet("CRH-Histogram", 1, 10, 5, 0); + LinearHistogram::FactoryGet("CRH-Linear", 1, 10, 5, 0); + BooleanHistogram::FactoryGet("CRH-Boolean", 0); + CustomHistogram::FactoryGet("CRH-Custom", ranges, 0); + SparseHistogram::FactoryGet("CRH-Sparse", 0); + + scoped_ptr<HistogramSamples> samples = report->SnapshotSamples(); + EXPECT_EQ(1, samples->GetCount(HISTOGRAM_REPORT_CREATED)); + EXPECT_EQ(5, samples->GetCount(HISTOGRAM_REPORT_HISTOGRAM_CREATED)); + EXPECT_EQ(0, samples->GetCount(HISTOGRAM_REPORT_HISTOGRAM_LOOKUP)); + EXPECT_EQ(1, samples->GetCount(HISTOGRAM_REPORT_TYPE_LOGARITHMIC)); + EXPECT_EQ(1, samples->GetCount(HISTOGRAM_REPORT_TYPE_LINEAR)); + EXPECT_EQ(1, samples->GetCount(HISTOGRAM_REPORT_TYPE_BOOLEAN)); + EXPECT_EQ(1, samples->GetCount(HISTOGRAM_REPORT_TYPE_CUSTOM)); + EXPECT_EQ(1, samples->GetCount(HISTOGRAM_REPORT_TYPE_SPARSE)); + + // Create all flag types and verify counts. + Histogram::FactoryGet("CRH-Histogram-UMA-Targeted", 1, 10, 5, + HistogramBase::kUmaTargetedHistogramFlag); + Histogram::FactoryGet("CRH-Histogram-UMA-Stability", 1, 10, 5, + HistogramBase::kUmaStabilityHistogramFlag); + SparseHistogram::FactoryGet("CRH-Sparse-UMA-Targeted", + HistogramBase::kUmaTargetedHistogramFlag); + SparseHistogram::FactoryGet("CRH-Sparse-UMA-Stability", + HistogramBase::kUmaStabilityHistogramFlag); + samples = report->SnapshotSamples(); + EXPECT_EQ(1, samples->GetCount(HISTOGRAM_REPORT_CREATED)); + EXPECT_EQ(9, samples->GetCount(HISTOGRAM_REPORT_HISTOGRAM_CREATED)); + EXPECT_EQ(0, samples->GetCount(HISTOGRAM_REPORT_HISTOGRAM_LOOKUP)); + EXPECT_EQ(2, samples->GetCount(HISTOGRAM_REPORT_FLAG_UMA_TARGETED)); + EXPECT_EQ(2, samples->GetCount(HISTOGRAM_REPORT_FLAG_UMA_STABILITY)); + + // Do lookup of existing histograms and verify counts. + Histogram::FactoryGet("CRH-Histogram", 1, 10, 5, 0); + LinearHistogram::FactoryGet("CRH-Linear", 1, 10, 5, 0); + BooleanHistogram::FactoryGet("CRH-Boolean", 0); + CustomHistogram::FactoryGet("CRH-Custom", ranges, 0); + SparseHistogram::FactoryGet("CRH-Sparse", 0); + samples = report->SnapshotSamples(); + EXPECT_EQ(1, samples->GetCount(HISTOGRAM_REPORT_CREATED)); + EXPECT_EQ(9, samples->GetCount(HISTOGRAM_REPORT_HISTOGRAM_CREATED)); + EXPECT_EQ(5, samples->GetCount(HISTOGRAM_REPORT_HISTOGRAM_LOOKUP)); +} + } // namespace base diff --git a/base/metrics/persistent_histogram_allocator.cc b/base/metrics/persistent_histogram_allocator.cc index 1929060..2e4029e 100644 --- a/base/metrics/persistent_histogram_allocator.cc +++ b/base/metrics/persistent_histogram_allocator.cc @@ -179,6 +179,11 @@ void PersistentHistogramAllocator::SetGlobalAllocator( // also released, future accesses to those histograms will seg-fault. CHECK(!g_allocator); g_allocator = allocator.release(); + + size_t existing = StatisticsRecorder::GetHistogramCount(); + DLOG_IF(WARNING, existing) + << existing + << " histograms were created before persistence was enabled."; } // static diff --git a/base/metrics/sparse_histogram.cc b/base/metrics/sparse_histogram.cc index 5653456..485f179 100644 --- a/base/metrics/sparse_histogram.cc +++ b/base/metrics/sparse_histogram.cc @@ -29,6 +29,9 @@ HistogramBase* SparseHistogram::FactoryGet(const std::string& name, tentative_histogram->SetFlags(flags); histogram = StatisticsRecorder::RegisterOrDeleteDuplicate(tentative_histogram); + ReportHistogramActivity(*histogram, HISTOGRAM_CREATED); + } else { + ReportHistogramActivity(*histogram, HISTOGRAM_LOOKUP); } DCHECK_EQ(SPARSE_HISTOGRAM, histogram->GetHistogramType()); return histogram; diff --git a/base/metrics/statistics_recorder.cc b/base/metrics/statistics_recorder.cc index d0fa2ad..2bb50ad 100644 --- a/base/metrics/statistics_recorder.cc +++ b/base/metrics/statistics_recorder.cc @@ -67,6 +67,15 @@ StatisticsRecorder::HistogramIterator::operator++() { return *this; } +StatisticsRecorder::~StatisticsRecorder() { + DCHECK(lock_); + DCHECK(histograms_); + DCHECK(ranges_); + + // Global clean up. + Reset(); +} + // static void StatisticsRecorder::Initialize() { // Ensure that an instance of the StatisticsRecorder object is created. @@ -369,6 +378,17 @@ StatisticsRecorder::OnSampleCallback StatisticsRecorder::FindCallback( } // static +size_t StatisticsRecorder::GetHistogramCount() { + if (!lock_) + return 0; + + base::AutoLock auto_lock(*lock_); + if (!histograms_) + return 0; + return histograms_->size(); +} + +// static void StatisticsRecorder::ResetForTesting() { // Just call the private version that is used also by the destructor. Reset(); @@ -403,13 +423,6 @@ StatisticsRecorder::StatisticsRecorder() { AtExitManager::RegisterCallback(&DumpHistogramsToVlog, this); } -StatisticsRecorder::~StatisticsRecorder() { - DCHECK(histograms_ && ranges_ && lock_); - - // Global clean up. - Reset(); -} - // static void StatisticsRecorder::Reset() { // If there's no lock then there is nothing to reset. diff --git a/base/metrics/statistics_recorder.h b/base/metrics/statistics_recorder.h index 36b2f30..6eaf079 100644 --- a/base/metrics/statistics_recorder.h +++ b/base/metrics/statistics_recorder.h @@ -63,6 +63,8 @@ class BASE_EXPORT StatisticsRecorder { const bool include_persistent_; }; + ~StatisticsRecorder(); + // Initializes the StatisticsRecorder system. Safe to call multiple times. static void Initialize(); @@ -130,6 +132,9 @@ class BASE_EXPORT StatisticsRecorder { // histogram. This method is thread safe. static OnSampleCallback FindCallback(const std::string& histogram_name); + // Returns the number of known histograms. + static size_t GetHistogramCount(); + // Clears all of the known histograms and resets static variables to a // state that allows a new initialization. static void ResetForTesting(); @@ -162,9 +167,8 @@ class BASE_EXPORT StatisticsRecorder { // The constructor just initializes static members. Usually client code should // use Initialize to do this. But in test code, you can friend this class and - // call destructor/constructor to get a clean StatisticsRecorder. + // call the constructor to get a clean StatisticsRecorder. StatisticsRecorder(); - ~StatisticsRecorder(); static void Reset(); static void DumpHistogramsToVlog(void* instance); diff --git a/chrome/installer/setup/installer_metrics.cc b/chrome/installer/setup/installer_metrics.cc index 5bf860c..ccc7ac4 100644 --- a/chrome/installer/setup/installer_metrics.cc +++ b/chrome/installer/setup/installer_metrics.cc @@ -21,6 +21,10 @@ void BeginPersistentHistogramStorage() { installer::kSetupHistogramAllocatorName); base::PersistentHistogramAllocator::GetGlobalAllocator() ->CreateTrackingHistograms(installer::kSetupHistogramAllocatorName); + + // This can't be enabled until after the allocator is configured because + // there is no other reporting out of setup other than persistent memory. + base::HistogramBase::EnableActivityReportHistogram("setup"); } void EndPersistentHistogramStorage(const base::FilePath& target_path) { diff --git a/content/app/content_main_runner.cc b/content/app/content_main_runner.cc index 5f5f8e5..1bf0c3e 100644 --- a/content/app/content_main_runner.cc +++ b/content/app/content_main_runner.cc @@ -23,6 +23,7 @@ #include "base/macros.h" #include "base/memory/scoped_ptr.h" #include "base/memory/scoped_vector.h" +#include "base/metrics/histogram_base.h" #include "base/metrics/statistics_recorder.h" #include "base/path_service.h" #include "base/process/launch.h" @@ -757,6 +758,8 @@ class ContentMainRunnerImpl : public ContentMainRunner { std::string process_type = command_line.GetSwitchValueASCII(switches::kProcessType); + base::HistogramBase::EnableActivityReportHistogram(process_type); + MainFunctionParams main_params(command_line); main_params.ui_task = ui_task_; #if defined(OS_WIN) diff --git a/tools/metrics/histograms/histograms.xml b/tools/metrics/histograms/histograms.xml index 16f652c..9f45c03 100644 --- a/tools/metrics/histograms/histograms.xml +++ b/tools/metrics/histograms/histograms.xml @@ -53629,6 +53629,15 @@ http://cs/file:chrome/histograms.xml - but prefer this file for new entries. </summary> </histogram> +<histogram name="UMA.Histograms.Activity" enum="HistogramActivityReport"> + <owner>asvitkine@chromium.org</owner> + <owner>bcwhite@chromium.org</owner> + <summary> + Type and flags of every histogram created plus other activities. Counts are + not mutually-exclusive except for the different types. + </summary> +</histogram> + <histogram name="UMA.InitSequence" enum="UmaInitSequence"> <owner>asvitkine@chromium.org</owner> <summary> @@ -70101,6 +70110,20 @@ http://cs/file:chrome/histograms.xml - but prefer this file for new entries. <int value="2" label="Both devices, pointing and keyboard, detected."/> </enum> +<enum name="HistogramActivityReport" type="int"> + <int value="0" label="Reports created"/> + <int value="1" label="Histograms created"/> + <int value="2" label="Histograms found by look-up"/> + <int value="3" label="Logarithmic histograms created"/> + <int value="4" label="Linear histograms created"/> + <int value="5" label="Boolean histograms created"/> + <int value="6" label="Custom histograms created"/> + <int value="7" label="sparse histograms created"/> + <int value="8" label="UMA-targeted histograms created"/> + <int value="9" label="UMA-stability histograms created"/> + <int value="10" label="Persistent histograms created"/> +</enum> + <enum name="HistoryFaviconsRecoveryEnum" type="int"> <summary>Error states noted in thumbnail_database.cc recovery code.</summary> <int value="0" label="RECOVERY_EVENT_RECOVERED">Successful recovery.</int> @@ -88090,6 +88113,13 @@ To add a new entry, add it with any value and run test to compute valid value. <affected-histogram name="OOBE.StepCompletionTime"/> </histogram_suffixes> +<histogram_suffixes name="OtherActivityProcesses" separator="."> + <suffix name="gpu-process"/> + <suffix name="renderer"/> + <suffix name="setup"/> + <affected-histogram name="UMA.Histograms.Activity"/> +</histogram_suffixes> + <histogram_suffixes name="OverlappedReadImpact"> <suffix name="OverlappedReadDisabled" label="Non-blocking reads"/> <suffix name="OverlappedReadEnabled" label="Default, async reads"/> |