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