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_base.h" 6b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 7cce46a0c214b37e8da48c522c83037e8ffa4f9fdAlex Vakulenko#include <limits.h> 8cce46a0c214b37e8da48c522c83037e8ffa4f9fdAlex Vakulenko 9cce46a0c214b37e8da48c522c83037e8ffa4f9fdAlex Vakulenko#include <utility> 10b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 11b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat#include "base/json/json_string_value_serializer.h" 12b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat#include "base/logging.h" 13b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat#include "base/memory/scoped_ptr.h" 14b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat#include "base/metrics/histogram.h" 15b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat#include "base/metrics/histogram_samples.h" 16b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat#include "base/metrics/sparse_histogram.h" 17cce46a0c214b37e8da48c522c83037e8ffa4f9fdAlex Vakulenko#include "base/metrics/statistics_recorder.h" 18b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat#include "base/pickle.h" 19b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat#include "base/process/process_handle.h" 20b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat#include "base/strings/stringprintf.h" 21b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat#include "base/values.h" 22b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 23b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Eratnamespace base { 24b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 25b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Eratstd::string HistogramTypeToString(HistogramType type) { 26b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat switch (type) { 27b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat case HISTOGRAM: 28b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat return "HISTOGRAM"; 29b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat case LINEAR_HISTOGRAM: 30b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat return "LINEAR_HISTOGRAM"; 31b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat case BOOLEAN_HISTOGRAM: 32b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat return "BOOLEAN_HISTOGRAM"; 33b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat case CUSTOM_HISTOGRAM: 34b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat return "CUSTOM_HISTOGRAM"; 35b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat case SPARSE_HISTOGRAM: 36b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat return "SPARSE_HISTOGRAM"; 37b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat default: 38b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat NOTREACHED(); 39b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat } 40b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat return "UNKNOWN"; 41b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat} 42b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 43b8cf94937c52feb53b55c39e3f82094d27de464cDaniel EratHistogramBase* DeserializeHistogramInfo(PickleIterator* iter) { 44b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat int type; 45b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat if (!iter->ReadInt(&type)) 46b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat return NULL; 47b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 48b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat switch (type) { 49b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat case HISTOGRAM: 50b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat return Histogram::DeserializeInfoImpl(iter); 51b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat case LINEAR_HISTOGRAM: 52b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat return LinearHistogram::DeserializeInfoImpl(iter); 53b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat case BOOLEAN_HISTOGRAM: 54b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat return BooleanHistogram::DeserializeInfoImpl(iter); 55b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat case CUSTOM_HISTOGRAM: 56b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat return CustomHistogram::DeserializeInfoImpl(iter); 57b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat case SPARSE_HISTOGRAM: 58b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat return SparseHistogram::DeserializeInfoImpl(iter); 59b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat default: 60b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat return NULL; 61b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat } 62b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat} 63b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 64b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Eratconst HistogramBase::Sample HistogramBase::kSampleType_MAX = INT_MAX; 65b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 66b8cf94937c52feb53b55c39e3f82094d27de464cDaniel EratHistogramBase::HistogramBase(const std::string& name) 67b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat : histogram_name_(name), 68b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat flags_(kNoFlags) {} 69b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 70b8cf94937c52feb53b55c39e3f82094d27de464cDaniel EratHistogramBase::~HistogramBase() {} 71b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 72b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Eratvoid HistogramBase::CheckName(const StringPiece& name) const { 73b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat DCHECK_EQ(histogram_name(), name); 74b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat} 75b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 76cce46a0c214b37e8da48c522c83037e8ffa4f9fdAlex Vakulenkovoid HistogramBase::SetFlags(int32_t flags) { 77cce46a0c214b37e8da48c522c83037e8ffa4f9fdAlex Vakulenko HistogramBase::Count old_flags = subtle::NoBarrier_Load(&flags_); 78cce46a0c214b37e8da48c522c83037e8ffa4f9fdAlex Vakulenko subtle::NoBarrier_Store(&flags_, old_flags | flags); 79b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat} 80b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 81cce46a0c214b37e8da48c522c83037e8ffa4f9fdAlex Vakulenkovoid HistogramBase::ClearFlags(int32_t flags) { 82cce46a0c214b37e8da48c522c83037e8ffa4f9fdAlex Vakulenko HistogramBase::Count old_flags = subtle::NoBarrier_Load(&flags_); 83cce46a0c214b37e8da48c522c83037e8ffa4f9fdAlex Vakulenko subtle::NoBarrier_Store(&flags_, old_flags & ~flags); 84b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat} 85b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 86b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Eratvoid HistogramBase::AddTime(const TimeDelta& time) { 87b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat Add(static_cast<Sample>(time.InMilliseconds())); 88b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat} 89b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 90b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Eratvoid HistogramBase::AddBoolean(bool value) { 91b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat Add(value ? 1 : 0); 92b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat} 93b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 94b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Eratbool HistogramBase::SerializeInfo(Pickle* pickle) const { 95b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat if (!pickle->WriteInt(GetHistogramType())) 96b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat return false; 97b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat return SerializeInfoImpl(pickle); 98b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat} 99b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 10060d96a4a9e0d8c78d46c1f86dec60f9ecdbedbdbChristopher Wileyint HistogramBase::FindCorruption(const HistogramSamples& /* samples */) const { 101b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // Not supported by default. 102b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat return NO_INCONSISTENCIES; 103b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat} 104b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 105b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Eratvoid HistogramBase::WriteJSON(std::string* output) const { 106b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat Count count; 107cce46a0c214b37e8da48c522c83037e8ffa4f9fdAlex Vakulenko int64_t sum; 108b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat scoped_ptr<ListValue> buckets(new ListValue()); 109b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat GetCountAndBucketData(&count, &sum, buckets.get()); 110b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat scoped_ptr<DictionaryValue> parameters(new DictionaryValue()); 111b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat GetParameters(parameters.get()); 112b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 113b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat JSONStringValueSerializer serializer(output); 114b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat DictionaryValue root; 115b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat root.SetString("name", histogram_name()); 116b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat root.SetInteger("count", count); 117b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat root.SetDouble("sum", static_cast<double>(sum)); 118b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat root.SetInteger("flags", flags()); 119cce46a0c214b37e8da48c522c83037e8ffa4f9fdAlex Vakulenko root.Set("params", std::move(parameters)); 120cce46a0c214b37e8da48c522c83037e8ffa4f9fdAlex Vakulenko root.Set("buckets", std::move(buckets)); 121b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat root.SetInteger("pid", GetCurrentProcId()); 122b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat serializer.Serialize(root); 123b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat} 124b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 125cce46a0c214b37e8da48c522c83037e8ffa4f9fdAlex Vakulenkovoid HistogramBase::FindAndRunCallback(HistogramBase::Sample sample) const { 126cce46a0c214b37e8da48c522c83037e8ffa4f9fdAlex Vakulenko if ((flags() & kCallbackExists) == 0) 127cce46a0c214b37e8da48c522c83037e8ffa4f9fdAlex Vakulenko return; 128cce46a0c214b37e8da48c522c83037e8ffa4f9fdAlex Vakulenko 129cce46a0c214b37e8da48c522c83037e8ffa4f9fdAlex Vakulenko StatisticsRecorder::OnSampleCallback cb = 130cce46a0c214b37e8da48c522c83037e8ffa4f9fdAlex Vakulenko StatisticsRecorder::FindCallback(histogram_name()); 131cce46a0c214b37e8da48c522c83037e8ffa4f9fdAlex Vakulenko if (!cb.is_null()) 132cce46a0c214b37e8da48c522c83037e8ffa4f9fdAlex Vakulenko cb.Run(sample); 133cce46a0c214b37e8da48c522c83037e8ffa4f9fdAlex Vakulenko} 134cce46a0c214b37e8da48c522c83037e8ffa4f9fdAlex Vakulenko 135b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Eratvoid HistogramBase::WriteAsciiBucketGraph(double current_size, 136b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat double max_size, 137b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat std::string* output) const { 138b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat const int k_line_length = 72; // Maximal horizontal width of graph. 139b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat int x_count = static_cast<int>(k_line_length * (current_size / max_size) 140b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat + 0.5); 141b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat int x_remainder = k_line_length - x_count; 142b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 143b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat while (0 < x_count--) 144b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat output->append("-"); 145b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat output->append("O"); 146b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat while (0 < x_remainder--) 147b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat output->append(" "); 148b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat} 149b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 150b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Eratconst std::string HistogramBase::GetSimpleAsciiBucketRange( 151b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat Sample sample) const { 152b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat std::string result; 153b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat if (kHexRangePrintingFlag & flags()) 154b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat StringAppendF(&result, "%#x", sample); 155b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat else 156b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat StringAppendF(&result, "%d", sample); 157b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat return result; 158b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat} 159b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 160b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Eratvoid HistogramBase::WriteAsciiBucketValue(Count current, 161b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat double scaled_sum, 162b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat std::string* output) const { 163b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat StringAppendF(output, " (%d = %3.1f%%)", current, current/scaled_sum); 164b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat} 165b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 166b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat} // namespace base 167