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