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