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