15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved. 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file. 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/metrics/histogram_base.h" 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <climits> 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/json/json_string_value_serializer.h" 10868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/logging.h" 115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/memory/scoped_ptr.h" 122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/metrics/histogram.h" 132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/metrics/histogram_samples.h" 142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/metrics/sparse_histogram.h" 152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/pickle.h" 1658e6fbe4ee35d65e14b626c557d37565bf8ad179Ben Murdoch#include "base/process/process_handle.h" 17868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/stringprintf.h" 185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/values.h" 195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace base { 215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)std::string HistogramTypeToString(HistogramType type) { 235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) switch (type) { 245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case HISTOGRAM: 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return "HISTOGRAM"; 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case LINEAR_HISTOGRAM: 275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return "LINEAR_HISTOGRAM"; 285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case BOOLEAN_HISTOGRAM: 295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return "BOOLEAN_HISTOGRAM"; 305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case CUSTOM_HISTOGRAM: 315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return "CUSTOM_HISTOGRAM"; 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case SPARSE_HISTOGRAM: 335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return "SPARSE_HISTOGRAM"; 345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) default: 355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NOTREACHED(); 365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return "UNKNOWN"; 385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)HistogramBase* DeserializeHistogramInfo(PickleIterator* iter) { 412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int type; 422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!iter->ReadInt(&type)) 432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return NULL; 442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) switch (type) { 462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) case HISTOGRAM: 472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return Histogram::DeserializeInfoImpl(iter); 482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) case LINEAR_HISTOGRAM: 492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return LinearHistogram::DeserializeInfoImpl(iter); 502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) case BOOLEAN_HISTOGRAM: 512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return BooleanHistogram::DeserializeInfoImpl(iter); 522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) case CUSTOM_HISTOGRAM: 532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return CustomHistogram::DeserializeInfoImpl(iter); 542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) case SPARSE_HISTOGRAM: 552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return SparseHistogram::DeserializeInfoImpl(iter); 562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) default: 572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return NULL; 582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const HistogramBase::Sample HistogramBase::kSampleType_MAX = INT_MAX; 625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)HistogramBase::HistogramBase(const std::string& name) 645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) : histogram_name_(name), 655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) flags_(kNoFlags) {} 665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)HistogramBase::~HistogramBase() {} 685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void HistogramBase::CheckName(const StringPiece& name) const { 705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DCHECK_EQ(histogram_name(), name); 715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HistogramBase::SetFlags(int32 flags) { 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) flags_ |= flags; 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HistogramBase::ClearFlags(int32 flags) { 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) flags_ &= ~flags; 795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void HistogramBase::AddTime(const TimeDelta& time) { 822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) Add(static_cast<Sample>(time.InMilliseconds())); 832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void HistogramBase::AddBoolean(bool value) { 862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) Add(value ? 1 : 0); 872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool HistogramBase::SerializeInfo(Pickle* pickle) const { 902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!pickle->WriteInt(GetHistogramType())) 912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return false; 922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return SerializeInfoImpl(pickle); 932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)int HistogramBase::FindCorruption(const HistogramSamples& samples) const { 962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Not supported by default. 972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return NO_INCONSISTENCIES; 982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HistogramBase::WriteJSON(std::string* output) const { 1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Count count; 102b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) int64 sum; 1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_ptr<ListValue> buckets(new ListValue()); 104b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) GetCountAndBucketData(&count, &sum, buckets.get()); 1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_ptr<DictionaryValue> parameters(new DictionaryValue()); 1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GetParameters(parameters.get()); 1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) JSONStringValueSerializer serializer(output); 1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DictionaryValue root; 1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) root.SetString("name", histogram_name()); 1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) root.SetInteger("count", count); 112b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) root.SetDouble("sum", sum); 1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) root.SetInteger("flags", flags()); 1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) root.Set("params", parameters.release()); 1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) root.Set("buckets", buckets.release()); 116c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) root.SetInteger("pid", GetCurrentProcId()); 1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) serializer.Serialize(root); 1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 120c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void HistogramBase::WriteAsciiBucketGraph(double current_size, 121c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) double max_size, 122c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) std::string* output) const { 123c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) const int k_line_length = 72; // Maximal horizontal width of graph. 124c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) int x_count = static_cast<int>(k_line_length * (current_size / max_size) 125c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) + 0.5); 126c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) int x_remainder = k_line_length - x_count; 127c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 128c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) while (0 < x_count--) 129c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) output->append("-"); 130c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) output->append("O"); 131c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) while (0 < x_remainder--) 132c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) output->append(" "); 133c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 134c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 135c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)const std::string HistogramBase::GetSimpleAsciiBucketRange( 136c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) Sample sample) const { 137c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) std::string result; 138c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (kHexRangePrintingFlag & flags()) 139c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) StringAppendF(&result, "%#x", sample); 140c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) else 141c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) StringAppendF(&result, "%d", sample); 142c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return result; 143c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 144c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 145c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void HistogramBase::WriteAsciiBucketValue(Count current, 146c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) double scaled_sum, 147c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) std::string* output) const { 148c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) StringAppendF(output, " (%d = %3.1f%%)", current, current/scaled_sum); 149c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 150c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace base 152