blob: b75932caae1e67019f16ecf586056e67761e0067 [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
[email protected]e182be02012-01-27 02:35:4447 // 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
[email protected]e58234cc2012-08-20 23:53:1558 // Note, at this point corruption can only be COUNT_HIGH_ERROR or
59 // COUNT_LOW_ERROR and they never arise together, so we don't need to extract
60 // bits from corruption.
[email protected]e182be02012-01-27 02:35:4461 if (corruption) {
62 NOTREACHED();
[email protected]e58234cc2012-08-20 23:53:1563 histogram_flattener_->InconsistencyDetected(
64 static_cast<Histogram::Inconsistencies>(corruption));
[email protected]83ab4a282012-07-12 18:19:4565 // Don't record corrupt data to metrics survices.
[email protected]e182be02012-01-27 02:35:4466 if (NULL == inconsistencies_.get())
67 inconsistencies_.reset(new ProblemMap);
68 int old_corruption = (*inconsistencies_)[histogram_name];
69 if (old_corruption == (corruption | old_corruption))
70 return; // We've already seen this corruption for this histogram.
71 (*inconsistencies_)[histogram_name] |= corruption;
[email protected]e58234cc2012-08-20 23:53:1572 histogram_flattener_->UniqueInconsistencyDetected(
73 static_cast<Histogram::Inconsistencies>(corruption));
[email protected]e182be02012-01-27 02:35:4474 return;
75 }
76
[email protected]83ab4a282012-07-12 18:19:4577 // Find the already recorded stats, or create an empty set. Remove from our
78 // snapshot anything that we've already recorded.
[email protected]e182be02012-01-27 02:35:4479 LoggedSampleMap::iterator it = logged_samples_.find(histogram_name);
80 Histogram::SampleSet* already_logged;
81 if (logged_samples_.end() == it) {
82 // Add new entry
83 already_logged = &logged_samples_[histogram.histogram_name()];
[email protected]34d062322012-08-01 21:34:0884 // Complete initialization.
85 already_logged->Resize(histogram.bucket_count());
[email protected]e182be02012-01-27 02:35:4486 } else {
87 already_logged = &(it->second);
88 int64 discrepancy(already_logged->TotalCount() -
[email protected]83ab4a282012-07-12 18:19:4589 already_logged->redundant_count());
[email protected]e182be02012-01-27 02:35:4490 if (discrepancy) {
91 NOTREACHED(); // Already_logged has become corrupt.
92 int problem = static_cast<int>(discrepancy);
93 if (problem != discrepancy)
94 problem = INT_MAX;
[email protected]e58234cc2012-08-20 23:53:1595 histogram_flattener_->InconsistencyDetectedInLoggedCount(problem);
[email protected]83ab4a282012-07-12 18:19:4596 // With no valid baseline, we'll act like we've recorded everything in our
[email protected]e182be02012-01-27 02:35:4497 // snapshot.
98 already_logged->Subtract(*already_logged);
99 already_logged->Add(snapshot);
100 }
101 // Deduct any stats we've already logged from our snapshot.
102 snapshot.Subtract(*already_logged);
103 }
104
105 // Snapshot now contains only a delta to what we've already_logged.
106 if (snapshot.redundant_count() > 0) {
[email protected]83ab4a282012-07-12 18:19:45107 histogram_flattener_->RecordDelta(histogram, snapshot);
[email protected]e182be02012-01-27 02:35:44108 // Add new data into our running total.
109 already_logged->Add(snapshot);
110 }
111}
[email protected]83ab4a282012-07-12 18:19:45112} // namespace base