| Index: base/metrics/histogram_snapshot_manager.cc
|
| ===================================================================
|
| --- base/metrics/histogram_snapshot_manager.cc (revision 155400)
|
| +++ base/metrics/histogram_snapshot_manager.cc (working copy)
|
| @@ -4,10 +4,14 @@
|
|
|
| #include "base/metrics/histogram_snapshot_manager.h"
|
|
|
| +#include "base/memory/scoped_ptr.h"
|
| +#include "base/metrics/histogram_flattener.h"
|
| +#include "base/metrics/histogram_samples.h"
|
| #include "base/metrics/statistics_recorder.h"
|
| +#include "base/stl_util.h"
|
|
|
| -using base::Histogram;
|
| -using base::StatisticsRecorder;
|
| +using std::map;
|
| +using std::string;
|
|
|
| namespace base {
|
|
|
| @@ -17,7 +21,9 @@
|
| DCHECK(histogram_flattener_);
|
| }
|
|
|
| -HistogramSnapshotManager::~HistogramSnapshotManager() {}
|
| +HistogramSnapshotManager::~HistogramSnapshotManager() {
|
| + STLDeleteValues(&logged_samples_);
|
| +}
|
|
|
| void HistogramSnapshotManager::PrepareDeltas(Histogram::Flags flag_to_set,
|
| bool record_only_uma) {
|
| @@ -38,11 +44,10 @@
|
| DCHECK(histogram_flattener_);
|
|
|
| // Get up-to-date snapshot of sample stats.
|
| - Histogram::SampleSet snapshot;
|
| - histogram.SnapshotSample(&snapshot);
|
| + scoped_ptr<HistogramSamples> snapshot(histogram.SnapshotSamples());
|
| const std::string& histogram_name = histogram.histogram_name();
|
|
|
| - int corruption = histogram.FindCorruption(snapshot);
|
| + int corruption = histogram.FindCorruption(*snapshot);
|
|
|
| // Crash if we detect that our histograms have been overwritten. This may be
|
| // a fair distance from the memory smasher, but we hope to correlate these
|
| @@ -59,54 +64,54 @@
|
| // COUNT_LOW_ERROR and they never arise together, so we don't need to extract
|
| // bits from corruption.
|
| if (corruption) {
|
| - NOTREACHED();
|
| + DLOG(ERROR) << "Histogram: " << histogram_name
|
| + << " has data corruption: " << corruption;
|
| histogram_flattener_->InconsistencyDetected(
|
| static_cast<Histogram::Inconsistencies>(corruption));
|
| - // Don't record corrupt data to metrics survices.
|
| - if (NULL == inconsistencies_.get())
|
| - inconsistencies_.reset(new ProblemMap);
|
| - int old_corruption = (*inconsistencies_)[histogram_name];
|
| + // Don't record corrupt data to metrics services.
|
| + int old_corruption = inconsistencies_[histogram_name];
|
| if (old_corruption == (corruption | old_corruption))
|
| return; // We've already seen this corruption for this histogram.
|
| - (*inconsistencies_)[histogram_name] |= corruption;
|
| + inconsistencies_[histogram_name] |= corruption;
|
| histogram_flattener_->UniqueInconsistencyDetected(
|
| static_cast<Histogram::Inconsistencies>(corruption));
|
| return;
|
| }
|
|
|
| - // Find the already recorded stats, or create an empty set. Remove from our
|
| - // snapshot anything that we've already recorded.
|
| - LoggedSampleMap::iterator it = logged_samples_.find(histogram_name);
|
| - Histogram::SampleSet* already_logged;
|
| - if (logged_samples_.end() == it) {
|
| - // Add new entry
|
| - already_logged = &logged_samples_[histogram.histogram_name()];
|
| - // Complete initialization.
|
| - already_logged->Resize(histogram.bucket_count());
|
| + HistogramSamples* to_log;
|
| + map<string, HistogramSamples*>::iterator it =
|
| + logged_samples_.find(histogram_name);
|
| + if (it == logged_samples_.end()) {
|
| + to_log = snapshot.release();
|
| +
|
| + // This histogram has not been logged before, add a new entry.
|
| + logged_samples_[histogram_name] = to_log;
|
| } else {
|
| - already_logged = &(it->second);
|
| - int64 discrepancy(already_logged->TotalCount() -
|
| - already_logged->redundant_count());
|
| - if (discrepancy) {
|
| - NOTREACHED(); // Already_logged has become corrupt.
|
| - int problem = static_cast<int>(discrepancy);
|
| - if (problem != discrepancy)
|
| - problem = INT_MAX;
|
| - histogram_flattener_->InconsistencyDetectedInLoggedCount(problem);
|
| - // With no valid baseline, we'll act like we've recorded everything in our
|
| - // snapshot.
|
| - already_logged->Subtract(*already_logged);
|
| - already_logged->Add(snapshot);
|
| - }
|
| - // Deduct any stats we've already logged from our snapshot.
|
| - snapshot.Subtract(*already_logged);
|
| + HistogramSamples* already_logged = it->second;
|
| + InspectLoggedSamplesInconsistency(*snapshot, already_logged);
|
| + snapshot->Subtract(*already_logged);
|
| + already_logged->Add(*snapshot);
|
| + to_log = snapshot.get();
|
| }
|
|
|
| - // Snapshot now contains only a delta to what we've already_logged.
|
| - if (snapshot.redundant_count() > 0) {
|
| - histogram_flattener_->RecordDelta(histogram, snapshot);
|
| - // Add new data into our running total.
|
| - already_logged->Add(snapshot);
|
| + if (to_log->redundant_count() > 0)
|
| + histogram_flattener_->RecordDelta(histogram, *to_log);
|
| +}
|
| +
|
| +void HistogramSnapshotManager::InspectLoggedSamplesInconsistency(
|
| + const HistogramSamples& new_snapshot,
|
| + HistogramSamples* logged_samples) {
|
| + HistogramBase::Count discrepancy =
|
| + logged_samples->TotalCount() - logged_samples->redundant_count();
|
| + if (!discrepancy)
|
| + return;
|
| +
|
| + histogram_flattener_->InconsistencyDetectedInLoggedCount(discrepancy);
|
| + if (discrepancy > Histogram::kCommonRaceBasedCountMismatch) {
|
| + // Fix logged_samples.
|
| + logged_samples->Subtract(*logged_samples);
|
| + logged_samples->Add(new_snapshot);
|
| }
|
| }
|
| +
|
| } // namespace base
|
|
|