[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] | 567d30e | 2012-07-13 21:48:29 | [diff] [blame] | 7 | #include "base/metrics/statistics_recorder.h" |
| 8 | |
[email protected] | e182be0 | 2012-01-27 02:35:44 | [diff] [blame] | 9 | using base::Histogram; |
| 10 | using base::StatisticsRecorder; |
| 11 | |
[email protected] | 83ab4a28 | 2012-07-12 18:19:45 | [diff] [blame] | 12 | namespace base { |
[email protected] | e182be0 | 2012-01-27 02:35:44 | [diff] [blame] | 13 | |
[email protected] | 83ab4a28 | 2012-07-12 18:19:45 | [diff] [blame] | 14 | HistogramSnapshotManager::HistogramSnapshotManager( |
| 15 | HistogramFlattener* histogram_flattener) |
| 16 | : histogram_flattener_(histogram_flattener) { |
| 17 | DCHECK(histogram_flattener_); |
| 18 | } |
[email protected] | e182be0 | 2012-01-27 02:35:44 | [diff] [blame] | 19 | |
[email protected] | 83ab4a28 | 2012-07-12 18:19:45 | [diff] [blame] | 20 | HistogramSnapshotManager::~HistogramSnapshotManager() {} |
| 21 | |
| 22 | void HistogramSnapshotManager::PrepareDeltas(Histogram::Flags flag_to_set, |
| 23 | bool record_only_uma) { |
[email protected] | e182be0 | 2012-01-27 02:35:44 | [diff] [blame] | 24 | 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] | 83ab4a28 | 2012-07-12 18:19:45 | [diff] [blame] | 30 | if (record_only_uma && |
[email protected] | e182be0 | 2012-01-27 02:35:44 | [diff] [blame] | 31 | 0 == ((*it)->flags() & Histogram::kUmaTargetedHistogramFlag)) |
| 32 | continue; |
[email protected] | 83ab4a28 | 2012-07-12 18:19:45 | [diff] [blame] | 33 | PrepareDelta(**it); |
[email protected] | e182be0 | 2012-01-27 02:35:44 | [diff] [blame] | 34 | } |
| 35 | } |
| 36 | |
[email protected] | 83ab4a28 | 2012-07-12 18:19:45 | [diff] [blame] | 37 | void HistogramSnapshotManager::PrepareDelta(const Histogram& histogram) { |
| 38 | DCHECK(histogram_flattener_); |
| 39 | |
[email protected] | e182be0 | 2012-01-27 02:35:44 | [diff] [blame] | 40 | // 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] | e182be0 | 2012-01-27 02:35:44 | [diff] [blame] | 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 | |
[email protected] | e58234cc | 2012-08-20 23:53:15 | [diff] [blame] | 58 | // 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] | e182be0 | 2012-01-27 02:35:44 | [diff] [blame] | 61 | if (corruption) { |
| 62 | NOTREACHED(); |
[email protected] | e58234cc | 2012-08-20 23:53:15 | [diff] [blame] | 63 | histogram_flattener_->InconsistencyDetected( |
| 64 | static_cast<Histogram::Inconsistencies>(corruption)); |
[email protected] | 83ab4a28 | 2012-07-12 18:19:45 | [diff] [blame] | 65 | // Don't record corrupt data to metrics survices. |
[email protected] | e182be0 | 2012-01-27 02:35:44 | [diff] [blame] | 66 | 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] | e58234cc | 2012-08-20 23:53:15 | [diff] [blame] | 72 | histogram_flattener_->UniqueInconsistencyDetected( |
| 73 | static_cast<Histogram::Inconsistencies>(corruption)); |
[email protected] | e182be0 | 2012-01-27 02:35:44 | [diff] [blame] | 74 | return; |
| 75 | } |
| 76 | |
[email protected] | 83ab4a28 | 2012-07-12 18:19:45 | [diff] [blame] | 77 | // Find the already recorded stats, or create an empty set. Remove from our |
| 78 | // snapshot anything that we've already recorded. |
[email protected] | e182be0 | 2012-01-27 02:35:44 | [diff] [blame] | 79 | 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] | 34d06232 | 2012-08-01 21:34:08 | [diff] [blame] | 84 | // Complete initialization. |
| 85 | already_logged->Resize(histogram.bucket_count()); |
[email protected] | e182be0 | 2012-01-27 02:35:44 | [diff] [blame] | 86 | } else { |
| 87 | already_logged = &(it->second); |
| 88 | int64 discrepancy(already_logged->TotalCount() - |
[email protected] | 83ab4a28 | 2012-07-12 18:19:45 | [diff] [blame] | 89 | already_logged->redundant_count()); |
[email protected] | e182be0 | 2012-01-27 02:35:44 | [diff] [blame] | 90 | 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] | e58234cc | 2012-08-20 23:53:15 | [diff] [blame] | 95 | histogram_flattener_->InconsistencyDetectedInLoggedCount(problem); |
[email protected] | 83ab4a28 | 2012-07-12 18:19:45 | [diff] [blame] | 96 | // With no valid baseline, we'll act like we've recorded everything in our |
[email protected] | e182be0 | 2012-01-27 02:35:44 | [diff] [blame] | 97 | // 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] | 83ab4a28 | 2012-07-12 18:19:45 | [diff] [blame] | 107 | histogram_flattener_->RecordDelta(histogram, snapshot); |
[email protected] | e182be0 | 2012-01-27 02:35:44 | [diff] [blame] | 108 | // Add new data into our running total. |
| 109 | already_logged->Add(snapshot); |
| 110 | } |
| 111 | } |
[email protected] | 83ab4a28 | 2012-07-12 18:19:45 | [diff] [blame] | 112 | } // namespace base |