blob: 2812c165b569d1f5d8aeefac674fbff1139bc700 [file] [log] [blame]
[email protected]e182be02012-01-27 02:35:441// Copyright (c) 2012 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
[email protected]83ab4a282012-07-12 18:19:455#include "base/metrics/histogram_snapshot_manager.h"
[email protected]e182be02012-01-27 02:35:446
[email protected]567d30e2012-07-13 21:48:297#include "base/metrics/statistics_recorder.h"
8
[email protected]e182be02012-01-27 02:35:449using base::Histogram;
10using base::StatisticsRecorder;
11
[email protected]83ab4a282012-07-12 18:19:4512namespace base {
[email protected]e182be02012-01-27 02:35:4413
[email protected]83ab4a282012-07-12 18:19:4514HistogramSnapshotManager::HistogramSnapshotManager(
15 HistogramFlattener* histogram_flattener)
16 : histogram_flattener_(histogram_flattener) {
17 DCHECK(histogram_flattener_);
18}
[email protected]e182be02012-01-27 02:35:4419
[email protected]83ab4a282012-07-12 18:19:4520HistogramSnapshotManager::~HistogramSnapshotManager() {}
21
22void HistogramSnapshotManager::PrepareDeltas(Histogram::Flags flag_to_set,
23 bool record_only_uma) {
[email protected]e182be02012-01-27 02:35:4424 StatisticsRecorder::Histograms histograms;
25 StatisticsRecorder::GetHistograms(&histograms);
26 for (StatisticsRecorder::Histograms::const_iterator it = histograms.begin();
27 histograms.end() != it;
28 ++it) {
29 (*it)->SetFlags(flag_to_set);
[email protected]83ab4a282012-07-12 18:19:4530 if (record_only_uma &&
[email protected]e182be02012-01-27 02:35:4431 0 == ((*it)->flags() & Histogram::kUmaTargetedHistogramFlag))
32 continue;
[email protected]83ab4a282012-07-12 18:19:4533 PrepareDelta(**it);
[email protected]e182be02012-01-27 02:35:4434 }
35}
36
[email protected]83ab4a282012-07-12 18:19:4537void HistogramSnapshotManager::PrepareDelta(const Histogram& histogram) {
38 DCHECK(histogram_flattener_);
39
[email protected]e182be02012-01-27 02:35:4440 // Get up-to-date snapshot of sample stats.
41 Histogram::SampleSet snapshot;
42 histogram.SnapshotSample(&snapshot);
43 const std::string& histogram_name = histogram.histogram_name();
44
45 int corruption = histogram.FindCorruption(snapshot);
46
47 // Crash if we detect that our histograms have been overwritten. This may be
48 // a fair distance from the memory smasher, but we hope to correlate these
49 // crashes with other events, such as plugins, or usage patterns, etc.
50 if (Histogram::BUCKET_ORDER_ERROR & corruption) {
51 // The checksum should have caught this, so crash separately if it didn't.
52 CHECK_NE(0, Histogram::RANGE_CHECKSUM_ERROR & corruption);
53 CHECK(false); // Crash for the bucket order corruption.
54 }
55 // Checksum corruption might not have caused order corruption.
56 CHECK_EQ(0, Histogram::RANGE_CHECKSUM_ERROR & corruption);
57
58 if (corruption) {
59 NOTREACHED();
[email protected]83ab4a282012-07-12 18:19:4560 histogram_flattener_->InconsistencyDetected(corruption);
61 // Don't record corrupt data to metrics survices.
[email protected]e182be02012-01-27 02:35:4462 if (NULL == inconsistencies_.get())
63 inconsistencies_.reset(new ProblemMap);
64 int old_corruption = (*inconsistencies_)[histogram_name];
65 if (old_corruption == (corruption | old_corruption))
66 return; // We've already seen this corruption for this histogram.
67 (*inconsistencies_)[histogram_name] |= corruption;
[email protected]83ab4a282012-07-12 18:19:4568 histogram_flattener_->UniqueInconsistencyDetected(corruption);
[email protected]e182be02012-01-27 02:35:4469 return;
70 }
71
[email protected]83ab4a282012-07-12 18:19:4572 // Find the already recorded stats, or create an empty set. Remove from our
73 // snapshot anything that we've already recorded.
[email protected]e182be02012-01-27 02:35:4474 LoggedSampleMap::iterator it = logged_samples_.find(histogram_name);
75 Histogram::SampleSet* already_logged;
76 if (logged_samples_.end() == it) {
77 // Add new entry
78 already_logged = &logged_samples_[histogram.histogram_name()];
[email protected]34d062322012-08-01 21:34:0879 // Complete initialization.
80 already_logged->Resize(histogram.bucket_count());
[email protected]e182be02012-01-27 02:35:4481 } else {
82 already_logged = &(it->second);
83 int64 discrepancy(already_logged->TotalCount() -
[email protected]83ab4a282012-07-12 18:19:4584 already_logged->redundant_count());
[email protected]e182be02012-01-27 02:35:4485 if (discrepancy) {
86 NOTREACHED(); // Already_logged has become corrupt.
87 int problem = static_cast<int>(discrepancy);
88 if (problem != discrepancy)
89 problem = INT_MAX;
[email protected]83ab4a282012-07-12 18:19:4590 histogram_flattener_->SnapshotProblemResolved(problem);
91 // With no valid baseline, we'll act like we've recorded everything in our
[email protected]e182be02012-01-27 02:35:4492 // snapshot.
93 already_logged->Subtract(*already_logged);
94 already_logged->Add(snapshot);
95 }
96 // Deduct any stats we've already logged from our snapshot.
97 snapshot.Subtract(*already_logged);
98 }
99
100 // Snapshot now contains only a delta to what we've already_logged.
101 if (snapshot.redundant_count() > 0) {
[email protected]83ab4a282012-07-12 18:19:45102 histogram_flattener_->RecordDelta(histogram, snapshot);
[email protected]e182be02012-01-27 02:35:44103 // Add new data into our running total.
104 already_logged->Add(snapshot);
105 }
106}
[email protected]83ab4a282012-07-12 18:19:45107} // namespace base