diff options
author | Zeno Albisser <zeno.albisser@digia.com> | 2013-08-15 21:46:11 +0200 |
---|---|---|
committer | Zeno Albisser <zeno.albisser@digia.com> | 2013-08-15 21:46:11 +0200 |
commit | 679147eead574d186ebf3069647b4c23e8ccace6 (patch) | |
tree | fc247a0ac8ff119f7c8550879ebb6d3dd8d1ff69 /chromium/base/metrics/histogram_snapshot_manager.cc | |
download | qtwebengine-chromium-679147eead574d186ebf3069647b4c23e8ccace6.tar.gz |
Initial import.
Diffstat (limited to 'chromium/base/metrics/histogram_snapshot_manager.cc')
-rw-r--r-- | chromium/base/metrics/histogram_snapshot_manager.cc | 117 |
1 files changed, 117 insertions, 0 deletions
diff --git a/chromium/base/metrics/histogram_snapshot_manager.cc b/chromium/base/metrics/histogram_snapshot_manager.cc new file mode 100644 index 00000000000..2301819ad30 --- /dev/null +++ b/chromium/base/metrics/histogram_snapshot_manager.cc @@ -0,0 +1,117 @@ +// 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/histogram_snapshot_manager.h" + +#include "base/memory/scoped_ptr.h" +#include "base/metrics/histogram_flattener.h" +#include "base/metrics/histogram_samples.h" +#include "base/metrics/statistics_recorder.h" +#include "base/stl_util.h" + +using std::map; +using std::string; + +namespace base { + +HistogramSnapshotManager::HistogramSnapshotManager( + HistogramFlattener* histogram_flattener) + : histogram_flattener_(histogram_flattener) { + DCHECK(histogram_flattener_); +} + +HistogramSnapshotManager::~HistogramSnapshotManager() { + STLDeleteValues(&logged_samples_); +} + +void HistogramSnapshotManager::PrepareDeltas(HistogramBase::Flags flag_to_set, + bool record_only_uma) { + StatisticsRecorder::Histograms histograms; + StatisticsRecorder::GetHistograms(&histograms); + for (StatisticsRecorder::Histograms::const_iterator it = histograms.begin(); + histograms.end() != it; + ++it) { + (*it)->SetFlags(flag_to_set); + if (record_only_uma && + 0 == ((*it)->flags() & Histogram::kUmaTargetedHistogramFlag)) + continue; + PrepareDelta(**it); + } +} + +void HistogramSnapshotManager::PrepareDelta(const HistogramBase& histogram) { + DCHECK(histogram_flattener_); + + // Get up-to-date snapshot of sample stats. + scoped_ptr<HistogramSamples> snapshot(histogram.SnapshotSamples()); + const std::string& histogram_name = histogram.histogram_name(); + + int corruption = histogram.FindCorruption(*snapshot); + + // Crash if we detect that our histograms have been overwritten. This may be + // a fair distance from the memory smasher, but we hope to correlate these + // crashes with other events, such as plugins, or usage patterns, etc. + if (HistogramBase::BUCKET_ORDER_ERROR & corruption) { + // The checksum should have caught this, so crash separately if it didn't. + CHECK_NE(0, HistogramBase::RANGE_CHECKSUM_ERROR & corruption); + CHECK(false); // Crash for the bucket order corruption. + } + // Checksum corruption might not have caused order corruption. + CHECK_EQ(0, HistogramBase::RANGE_CHECKSUM_ERROR & corruption); + + // Note, at this point corruption can only be COUNT_HIGH_ERROR or + // COUNT_LOW_ERROR and they never arise together, so we don't need to extract + // bits from corruption. + if (corruption) { + DLOG(ERROR) << "Histogram: " << histogram_name + << " has data corruption: " << corruption; + histogram_flattener_->InconsistencyDetected( + static_cast<HistogramBase::Inconsistency>(corruption)); + // Don't record corrupt data to metrics services. + int old_corruption = inconsistencies_[histogram_name]; + if (old_corruption == (corruption | old_corruption)) + return; // We've already seen this corruption for this histogram. + inconsistencies_[histogram_name] |= corruption; + histogram_flattener_->UniqueInconsistencyDetected( + static_cast<HistogramBase::Inconsistency>(corruption)); + return; + } + + HistogramSamples* to_log; + map<string, HistogramSamples*>::iterator it = + logged_samples_.find(histogram_name); + if (it == logged_samples_.end()) { + to_log = snapshot.release(); + + // This histogram has not been logged before, add a new entry. + logged_samples_[histogram_name] = to_log; + } else { + HistogramSamples* already_logged = it->second; + InspectLoggedSamplesInconsistency(*snapshot, already_logged); + snapshot->Subtract(*already_logged); + already_logged->Add(*snapshot); + to_log = snapshot.get(); + } + + if (to_log->redundant_count() > 0) + histogram_flattener_->RecordDelta(histogram, *to_log); +} + +void HistogramSnapshotManager::InspectLoggedSamplesInconsistency( + const HistogramSamples& new_snapshot, + HistogramSamples* logged_samples) { + HistogramBase::Count discrepancy = + logged_samples->TotalCount() - logged_samples->redundant_count(); + if (!discrepancy) + return; + + histogram_flattener_->InconsistencyDetectedInLoggedCount(discrepancy); + if (discrepancy > Histogram::kCommonRaceBasedCountMismatch) { + // Fix logged_samples. + logged_samples->Subtract(*logged_samples); + logged_samples->Add(new_snapshot); + } +} + +} // namespace base |