1b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// Copyright (c) 2012 The Chromium Authors. All rights reserved. 2b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// Use of this source code is governed by a BSD-style license that can be 3b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// found in the LICENSE file. 4b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 5b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat#include "base/metrics/histogram_snapshot_manager.h" 6b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 794ffa55491333f3dcc701befd0d2652922916d99Luis Hector Chavez#include <memory> 894ffa55491333f3dcc701befd0d2652922916d99Luis Hector Chavez 994ffa55491333f3dcc701befd0d2652922916d99Luis Hector Chavez#include "base/debug/alias.h" 10b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat#include "base/metrics/histogram_flattener.h" 11b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat#include "base/metrics/histogram_samples.h" 12b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat#include "base/metrics/statistics_recorder.h" 13b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat#include "base/stl_util.h" 14b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 15b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Eratnamespace base { 16b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 17b8cf94937c52feb53b55c39e3f82094d27de464cDaniel EratHistogramSnapshotManager::HistogramSnapshotManager( 18b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat HistogramFlattener* histogram_flattener) 190c4f26a46430b8c503c65f5cae1d2b6876d53e30Luis Hector Chavez : histogram_flattener_(histogram_flattener) { 20b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat DCHECK(histogram_flattener_); 21b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat} 22b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 23b8cf94937c52feb53b55c39e3f82094d27de464cDaniel EratHistogramSnapshotManager::~HistogramSnapshotManager() { 24b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat} 25b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 2645779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenkovoid HistogramSnapshotManager::PrepareDelta(HistogramBase* histogram) { 2745779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko PrepareSamples(histogram, histogram->SnapshotDelta()); 2845779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko} 2945779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko 300c4f26a46430b8c503c65f5cae1d2b6876d53e30Luis Hector Chavezvoid HistogramSnapshotManager::PrepareFinalDelta( 310c4f26a46430b8c503c65f5cae1d2b6876d53e30Luis Hector Chavez const HistogramBase* histogram) { 320c4f26a46430b8c503c65f5cae1d2b6876d53e30Luis Hector Chavez PrepareSamples(histogram, histogram->SnapshotFinalDelta()); 3345779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko} 3445779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko 3545779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenkovoid HistogramSnapshotManager::PrepareSamples( 3645779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko const HistogramBase* histogram, 3794ffa55491333f3dcc701befd0d2652922916d99Luis Hector Chavez std::unique_ptr<HistogramSamples> samples) { 38b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat DCHECK(histogram_flattener_); 39b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 400c4f26a46430b8c503c65f5cae1d2b6876d53e30Luis Hector Chavez // Get information known about this histogram. If it did not previously 410c4f26a46430b8c503c65f5cae1d2b6876d53e30Luis Hector Chavez // exist, one will be created and initialized. 4245779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko SampleInfo* sample_info = &known_histograms_[histogram->name_hash()]; 43b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 44b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // Crash if we detect that our histograms have been overwritten. This may be 45b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // a fair distance from the memory smasher, but we hope to correlate these 46b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // crashes with other events, such as plugins, or usage patterns, etc. 4745779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko uint32_t corruption = histogram->FindCorruption(*samples); 48b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat if (HistogramBase::BUCKET_ORDER_ERROR & corruption) { 490c4f26a46430b8c503c65f5cae1d2b6876d53e30Luis Hector Chavez // Extract fields useful during debug. 500c4f26a46430b8c503c65f5cae1d2b6876d53e30Luis Hector Chavez const BucketRanges* ranges = 510c4f26a46430b8c503c65f5cae1d2b6876d53e30Luis Hector Chavez static_cast<const Histogram*>(histogram)->bucket_ranges(); 520c4f26a46430b8c503c65f5cae1d2b6876d53e30Luis Hector Chavez std::vector<HistogramBase::Sample> ranges_copy; 530c4f26a46430b8c503c65f5cae1d2b6876d53e30Luis Hector Chavez for (size_t i = 0; i < ranges->size(); ++i) 540c4f26a46430b8c503c65f5cae1d2b6876d53e30Luis Hector Chavez ranges_copy.push_back(ranges->range(i)); 550c4f26a46430b8c503c65f5cae1d2b6876d53e30Luis Hector Chavez HistogramBase::Sample* ranges_ptr = &ranges_copy[0]; 560c4f26a46430b8c503c65f5cae1d2b6876d53e30Luis Hector Chavez const char* histogram_name = histogram->histogram_name().c_str(); 570c4f26a46430b8c503c65f5cae1d2b6876d53e30Luis Hector Chavez int32_t flags = histogram->flags(); 58b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // The checksum should have caught this, so crash separately if it didn't. 5945779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko CHECK_NE(0U, HistogramBase::RANGE_CHECKSUM_ERROR & corruption); 60b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat CHECK(false); // Crash for the bucket order corruption. 6194ffa55491333f3dcc701befd0d2652922916d99Luis Hector Chavez // Ensure that compiler keeps around pointers to |histogram| and its 6294ffa55491333f3dcc701befd0d2652922916d99Luis Hector Chavez // internal |bucket_ranges_| for any minidumps. 630c4f26a46430b8c503c65f5cae1d2b6876d53e30Luis Hector Chavez base::debug::Alias(&ranges_ptr); 640c4f26a46430b8c503c65f5cae1d2b6876d53e30Luis Hector Chavez base::debug::Alias(&histogram_name); 650c4f26a46430b8c503c65f5cae1d2b6876d53e30Luis Hector Chavez base::debug::Alias(&flags); 66b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat } 67b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // Checksum corruption might not have caused order corruption. 6845779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko CHECK_EQ(0U, HistogramBase::RANGE_CHECKSUM_ERROR & corruption); 69b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 70b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // Note, at this point corruption can only be COUNT_HIGH_ERROR or 71b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // COUNT_LOW_ERROR and they never arise together, so we don't need to extract 72b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // bits from corruption. 73b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat if (corruption) { 7445779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko DLOG(ERROR) << "Histogram: \"" << histogram->histogram_name() 7545779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko << "\" has data corruption: " << corruption; 76b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat histogram_flattener_->InconsistencyDetected( 77b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat static_cast<HistogramBase::Inconsistency>(corruption)); 78b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // Don't record corrupt data to metrics services. 7945779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko const uint32_t old_corruption = sample_info->inconsistencies; 80b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat if (old_corruption == (corruption | old_corruption)) 81b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat return; // We've already seen this corruption for this histogram. 820c4f26a46430b8c503c65f5cae1d2b6876d53e30Luis Hector Chavez sample_info->inconsistencies |= corruption; 830c4f26a46430b8c503c65f5cae1d2b6876d53e30Luis Hector Chavez histogram_flattener_->UniqueInconsistencyDetected( 840c4f26a46430b8c503c65f5cae1d2b6876d53e30Luis Hector Chavez static_cast<HistogramBase::Inconsistency>(corruption)); 85b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat return; 86b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat } 87b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 880c4f26a46430b8c503c65f5cae1d2b6876d53e30Luis Hector Chavez if (samples->TotalCount() > 0) 890c4f26a46430b8c503c65f5cae1d2b6876d53e30Luis Hector Chavez histogram_flattener_->RecordDelta(*histogram, *samples); 90b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat} 91b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 92b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Eratvoid HistogramSnapshotManager::InspectLoggedSamplesInconsistency( 93b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat const HistogramSamples& new_snapshot, 94b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat HistogramSamples* logged_samples) { 95b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat HistogramBase::Count discrepancy = 96b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat logged_samples->TotalCount() - logged_samples->redundant_count(); 97b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat if (!discrepancy) 98b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat return; 99b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 100b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat histogram_flattener_->InconsistencyDetectedInLoggedCount(discrepancy); 101b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat if (discrepancy > Histogram::kCommonRaceBasedCountMismatch) { 102b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // Fix logged_samples. 103b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat logged_samples->Subtract(*logged_samples); 104b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat logged_samples->Add(new_snapshot); 105b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat } 106b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat} 107b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 108b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat} // namespace base 109