[email protected] | e182be0 | 2012-01-27 02:35:44 | [diff] [blame] | 1 | // 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] | 83ab4a28 | 2012-07-12 18:19:45 | [diff] [blame] | 5 | #include "base/metrics/histogram_snapshot_manager.h" |
[email protected] | e182be0 | 2012-01-27 02:35:44 | [diff] [blame] | 6 | |
[email protected] | 2f7d9cd | 2012-09-22 03:42:12 | [diff] [blame] | 7 | #include "base/memory/scoped_ptr.h" |
| 8 | #include "base/metrics/histogram_flattener.h" |
| 9 | #include "base/metrics/histogram_samples.h" |
[email protected] | 567d30e | 2012-07-13 21:48:29 | [diff] [blame] | 10 | #include "base/metrics/statistics_recorder.h" |
[email protected] | 2f7d9cd | 2012-09-22 03:42:12 | [diff] [blame] | 11 | #include "base/stl_util.h" |
[email protected] | 567d30e | 2012-07-13 21:48:29 | [diff] [blame] | 12 | |
[email protected] | 2f7d9cd | 2012-09-22 03:42:12 | [diff] [blame] | 13 | using std::map; |
| 14 | using std::string; |
[email protected] | e182be0 | 2012-01-27 02:35:44 | [diff] [blame] | 15 | |
[email protected] | 83ab4a28 | 2012-07-12 18:19:45 | [diff] [blame] | 16 | namespace base { |
[email protected] | e182be0 | 2012-01-27 02:35:44 | [diff] [blame] | 17 | |
[email protected] | 83ab4a28 | 2012-07-12 18:19:45 | [diff] [blame] | 18 | HistogramSnapshotManager::HistogramSnapshotManager( |
| 19 | HistogramFlattener* histogram_flattener) |
| 20 | : histogram_flattener_(histogram_flattener) { |
| 21 | DCHECK(histogram_flattener_); |
| 22 | } |
[email protected] | e182be0 | 2012-01-27 02:35:44 | [diff] [blame] | 23 | |
[email protected] | 2f7d9cd | 2012-09-22 03:42:12 | [diff] [blame] | 24 | HistogramSnapshotManager::~HistogramSnapshotManager() { |
| 25 | STLDeleteValues(&logged_samples_); |
| 26 | } |
[email protected] | 83ab4a28 | 2012-07-12 18:19:45 | [diff] [blame] | 27 | |
[email protected] | c778687a | 2014-02-11 14:46:45 | [diff] [blame] | 28 | void HistogramSnapshotManager::PrepareDeltas( |
| 29 | HistogramBase::Flags flag_to_set, |
| 30 | HistogramBase::Flags required_flags) { |
[email protected] | e182be0 | 2012-01-27 02:35:44 | [diff] [blame] | 31 | StatisticsRecorder::Histograms histograms; |
| 32 | StatisticsRecorder::GetHistograms(&histograms); |
| 33 | for (StatisticsRecorder::Histograms::const_iterator it = histograms.begin(); |
| 34 | histograms.end() != it; |
| 35 | ++it) { |
| 36 | (*it)->SetFlags(flag_to_set); |
[email protected] | c778687a | 2014-02-11 14:46:45 | [diff] [blame] | 37 | if (((*it)->flags() & required_flags) == required_flags) |
| 38 | PrepareDelta(**it); |
[email protected] | e182be0 | 2012-01-27 02:35:44 | [diff] [blame] | 39 | } |
| 40 | } |
| 41 | |
[email protected] | cc7dec21 | 2013-03-01 03:53:25 | [diff] [blame] | 42 | void HistogramSnapshotManager::PrepareDelta(const HistogramBase& histogram) { |
[email protected] | 83ab4a28 | 2012-07-12 18:19:45 | [diff] [blame] | 43 | DCHECK(histogram_flattener_); |
| 44 | |
[email protected] | e182be0 | 2012-01-27 02:35:44 | [diff] [blame] | 45 | // Get up-to-date snapshot of sample stats. |
[email protected] | 2f7d9cd | 2012-09-22 03:42:12 | [diff] [blame] | 46 | scoped_ptr<HistogramSamples> snapshot(histogram.SnapshotSamples()); |
[email protected] | e182be0 | 2012-01-27 02:35:44 | [diff] [blame] | 47 | const std::string& histogram_name = histogram.histogram_name(); |
| 48 | |
[email protected] | 2f7d9cd | 2012-09-22 03:42:12 | [diff] [blame] | 49 | int corruption = histogram.FindCorruption(*snapshot); |
[email protected] | e182be0 | 2012-01-27 02:35:44 | [diff] [blame] | 50 | |
| 51 | // Crash if we detect that our histograms have been overwritten. This may be |
| 52 | // a fair distance from the memory smasher, but we hope to correlate these |
| 53 | // crashes with other events, such as plugins, or usage patterns, etc. |
[email protected] | cc7dec21 | 2013-03-01 03:53:25 | [diff] [blame] | 54 | if (HistogramBase::BUCKET_ORDER_ERROR & corruption) { |
[email protected] | e182be0 | 2012-01-27 02:35:44 | [diff] [blame] | 55 | // The checksum should have caught this, so crash separately if it didn't. |
[email protected] | cc7dec21 | 2013-03-01 03:53:25 | [diff] [blame] | 56 | CHECK_NE(0, HistogramBase::RANGE_CHECKSUM_ERROR & corruption); |
[email protected] | e182be0 | 2012-01-27 02:35:44 | [diff] [blame] | 57 | CHECK(false); // Crash for the bucket order corruption. |
| 58 | } |
| 59 | // Checksum corruption might not have caused order corruption. |
[email protected] | cc7dec21 | 2013-03-01 03:53:25 | [diff] [blame] | 60 | CHECK_EQ(0, HistogramBase::RANGE_CHECKSUM_ERROR & corruption); |
[email protected] | e182be0 | 2012-01-27 02:35:44 | [diff] [blame] | 61 | |
[email protected] | e58234cc | 2012-08-20 23:53:15 | [diff] [blame] | 62 | // Note, at this point corruption can only be COUNT_HIGH_ERROR or |
| 63 | // COUNT_LOW_ERROR and they never arise together, so we don't need to extract |
| 64 | // bits from corruption. |
[email protected] | e182be0 | 2012-01-27 02:35:44 | [diff] [blame] | 65 | if (corruption) { |
[email protected] | 2f7d9cd | 2012-09-22 03:42:12 | [diff] [blame] | 66 | DLOG(ERROR) << "Histogram: " << histogram_name |
| 67 | << " has data corruption: " << corruption; |
[email protected] | e58234cc | 2012-08-20 23:53:15 | [diff] [blame] | 68 | histogram_flattener_->InconsistencyDetected( |
[email protected] | cc7dec21 | 2013-03-01 03:53:25 | [diff] [blame] | 69 | static_cast<HistogramBase::Inconsistency>(corruption)); |
[email protected] | 2f7d9cd | 2012-09-22 03:42:12 | [diff] [blame] | 70 | // Don't record corrupt data to metrics services. |
| 71 | int old_corruption = inconsistencies_[histogram_name]; |
[email protected] | e182be0 | 2012-01-27 02:35:44 | [diff] [blame] | 72 | if (old_corruption == (corruption | old_corruption)) |
| 73 | return; // We've already seen this corruption for this histogram. |
[email protected] | 2f7d9cd | 2012-09-22 03:42:12 | [diff] [blame] | 74 | inconsistencies_[histogram_name] |= corruption; |
[email protected] | e58234cc | 2012-08-20 23:53:15 | [diff] [blame] | 75 | histogram_flattener_->UniqueInconsistencyDetected( |
[email protected] | cc7dec21 | 2013-03-01 03:53:25 | [diff] [blame] | 76 | static_cast<HistogramBase::Inconsistency>(corruption)); |
[email protected] | e182be0 | 2012-01-27 02:35:44 | [diff] [blame] | 77 | return; |
| 78 | } |
| 79 | |
[email protected] | 2f7d9cd | 2012-09-22 03:42:12 | [diff] [blame] | 80 | HistogramSamples* to_log; |
| 81 | map<string, HistogramSamples*>::iterator it = |
| 82 | logged_samples_.find(histogram_name); |
| 83 | if (it == logged_samples_.end()) { |
| 84 | to_log = snapshot.release(); |
| 85 | |
| 86 | // This histogram has not been logged before, add a new entry. |
| 87 | logged_samples_[histogram_name] = to_log; |
[email protected] | e182be0 | 2012-01-27 02:35:44 | [diff] [blame] | 88 | } else { |
[email protected] | 2f7d9cd | 2012-09-22 03:42:12 | [diff] [blame] | 89 | HistogramSamples* already_logged = it->second; |
| 90 | InspectLoggedSamplesInconsistency(*snapshot, already_logged); |
| 91 | snapshot->Subtract(*already_logged); |
| 92 | already_logged->Add(*snapshot); |
| 93 | to_log = snapshot.get(); |
[email protected] | e182be0 | 2012-01-27 02:35:44 | [diff] [blame] | 94 | } |
| 95 | |
[email protected] | 346d874 | 2013-10-16 10:30:06 | [diff] [blame] | 96 | if (to_log->TotalCount() > 0) |
[email protected] | 2f7d9cd | 2012-09-22 03:42:12 | [diff] [blame] | 97 | histogram_flattener_->RecordDelta(histogram, *to_log); |
| 98 | } |
| 99 | |
| 100 | void HistogramSnapshotManager::InspectLoggedSamplesInconsistency( |
| 101 | const HistogramSamples& new_snapshot, |
| 102 | HistogramSamples* logged_samples) { |
| 103 | HistogramBase::Count discrepancy = |
| 104 | logged_samples->TotalCount() - logged_samples->redundant_count(); |
| 105 | if (!discrepancy) |
| 106 | return; |
| 107 | |
| 108 | histogram_flattener_->InconsistencyDetectedInLoggedCount(discrepancy); |
| 109 | if (discrepancy > Histogram::kCommonRaceBasedCountMismatch) { |
| 110 | // Fix logged_samples. |
| 111 | logged_samples->Subtract(*logged_samples); |
| 112 | logged_samples->Add(new_snapshot); |
[email protected] | e182be0 | 2012-01-27 02:35:44 | [diff] [blame] | 113 | } |
| 114 | } |
[email protected] | 2f7d9cd | 2012-09-22 03:42:12 | [diff] [blame] | 115 | |
[email protected] | 83ab4a28 | 2012-07-12 18:19:45 | [diff] [blame] | 116 | } // namespace base |