summaryrefslogtreecommitdiff
path: root/chromium/base/metrics/histogram_snapshot_manager.cc
diff options
context:
space:
mode:
authorZeno Albisser <zeno.albisser@digia.com>2013-08-15 21:46:11 +0200
committerZeno Albisser <zeno.albisser@digia.com>2013-08-15 21:46:11 +0200
commit679147eead574d186ebf3069647b4c23e8ccace6 (patch)
treefc247a0ac8ff119f7c8550879ebb6d3dd8d1ff69 /chromium/base/metrics/histogram_snapshot_manager.cc
downloadqtwebengine-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.cc117
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