• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 <memory>
10 #include <utility>
11 
12 #include "base/json/json_string_value_serializer.h"
13 #include "base/logging.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   }
38   NOTREACHED();
39   return "UNKNOWN";
40 }
41 
DeserializeHistogramInfo(PickleIterator * iter)42 HistogramBase* DeserializeHistogramInfo(PickleIterator* iter) {
43   int type;
44   if (!iter->ReadInt(&type))
45     return NULL;
46 
47   switch (type) {
48     case HISTOGRAM:
49       return Histogram::DeserializeInfoImpl(iter);
50     case LINEAR_HISTOGRAM:
51       return LinearHistogram::DeserializeInfoImpl(iter);
52     case BOOLEAN_HISTOGRAM:
53       return BooleanHistogram::DeserializeInfoImpl(iter);
54     case CUSTOM_HISTOGRAM:
55       return CustomHistogram::DeserializeInfoImpl(iter);
56     case SPARSE_HISTOGRAM:
57       return SparseHistogram::DeserializeInfoImpl(iter);
58     default:
59       return NULL;
60   }
61 }
62 
63 const HistogramBase::Sample HistogramBase::kSampleType_MAX = INT_MAX;
64 HistogramBase* HistogramBase::report_histogram_ = nullptr;
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 uint32_t HistogramBase::FindCorruption(
101     const HistogramSamples& /*samples*/) const {
102   // Not supported by default.
103   return NO_INCONSISTENCIES;
104 }
105 
WriteJSON(std::string * output) const106 void HistogramBase::WriteJSON(std::string* output) const {
107   Count count;
108   int64_t sum;
109   std::unique_ptr<ListValue> buckets(new ListValue());
110   GetCountAndBucketData(&count, &sum, buckets.get());
111   std::unique_ptr<DictionaryValue> parameters(new DictionaryValue());
112   GetParameters(parameters.get());
113 
114   JSONStringValueSerializer serializer(output);
115   DictionaryValue root;
116   root.SetString("name", histogram_name());
117   root.SetInteger("count", count);
118   root.SetDouble("sum", static_cast<double>(sum));
119   root.SetInteger("flags", flags());
120   root.Set("params", std::move(parameters));
121   root.Set("buckets", std::move(buckets));
122   root.SetInteger("pid", GetCurrentProcId());
123   serializer.Serialize(root);
124 }
125 
126 // static
EnableActivityReportHistogram(const std::string & process_type)127 void HistogramBase::EnableActivityReportHistogram(
128     const std::string& process_type) {
129   DCHECK(!report_histogram_);
130   size_t existing = StatisticsRecorder::GetHistogramCount();
131   if (existing != 0) {
132     DVLOG(1) << existing
133              << " histograms were created before reporting was enabled.";
134   }
135 
136   std::string name =
137       "UMA.Histograms.Activity" +
138       (process_type.empty() ? process_type : "." + process_type);
139 
140   // Calling FactoryGet() here rather than using a histogram-macro works
141   // around some problems with tests that could end up seeing the results
142   // histogram when not expected due to a bad interaction between
143   // HistogramTester and StatisticsRecorder.
144   report_histogram_ = LinearHistogram::FactoryGet(
145       name, 1, HISTOGRAM_REPORT_MAX, HISTOGRAM_REPORT_MAX + 1,
146       kUmaTargetedHistogramFlag);
147   report_histogram_->Add(HISTOGRAM_REPORT_CREATED);
148 }
149 
FindAndRunCallback(HistogramBase::Sample sample) const150 void HistogramBase::FindAndRunCallback(HistogramBase::Sample sample) const {
151   if ((flags() & kCallbackExists) == 0)
152     return;
153 
154   StatisticsRecorder::OnSampleCallback cb =
155       StatisticsRecorder::FindCallback(histogram_name());
156   if (!cb.is_null())
157     cb.Run(sample);
158 }
159 
WriteAsciiBucketGraph(double current_size,double max_size,std::string * output) const160 void HistogramBase::WriteAsciiBucketGraph(double current_size,
161                                           double max_size,
162                                           std::string* output) const {
163   const int k_line_length = 72;  // Maximal horizontal width of graph.
164   int x_count = static_cast<int>(k_line_length * (current_size / max_size)
165                                  + 0.5);
166   int x_remainder = k_line_length - x_count;
167 
168   while (0 < x_count--)
169     output->append("-");
170   output->append("O");
171   while (0 < x_remainder--)
172     output->append(" ");
173 }
174 
GetSimpleAsciiBucketRange(Sample sample) const175 const std::string HistogramBase::GetSimpleAsciiBucketRange(
176     Sample sample) const {
177   std::string result;
178   if (kHexRangePrintingFlag & flags())
179     StringAppendF(&result, "%#x", sample);
180   else
181     StringAppendF(&result, "%d", sample);
182   return result;
183 }
184 
WriteAsciiBucketValue(Count current,double scaled_sum,std::string * output) const185 void HistogramBase::WriteAsciiBucketValue(Count current,
186                                           double scaled_sum,
187                                           std::string* output) const {
188   StringAppendF(output, " (%d = %3.1f%%)", current, current/scaled_sum);
189 }
190 
191 // static
ReportHistogramActivity(const HistogramBase & histogram,ReportActivity activity)192 void HistogramBase::ReportHistogramActivity(const HistogramBase& histogram,
193                                             ReportActivity activity) {
194   if (!report_histogram_)
195     return;
196 
197   const int32_t flags = histogram.flags_;
198   HistogramReport report_type = HISTOGRAM_REPORT_MAX;
199   switch (activity) {
200     case HISTOGRAM_CREATED:
201       report_histogram_->Add(HISTOGRAM_REPORT_HISTOGRAM_CREATED);
202       switch (histogram.GetHistogramType()) {
203         case HISTOGRAM:
204           report_type = HISTOGRAM_REPORT_TYPE_LOGARITHMIC;
205           break;
206         case LINEAR_HISTOGRAM:
207           report_type = HISTOGRAM_REPORT_TYPE_LINEAR;
208           break;
209         case BOOLEAN_HISTOGRAM:
210           report_type = HISTOGRAM_REPORT_TYPE_BOOLEAN;
211           break;
212         case CUSTOM_HISTOGRAM:
213           report_type = HISTOGRAM_REPORT_TYPE_CUSTOM;
214           break;
215         case SPARSE_HISTOGRAM:
216           report_type = HISTOGRAM_REPORT_TYPE_SPARSE;
217           break;
218       }
219       report_histogram_->Add(report_type);
220       if (flags & kIsPersistent)
221         report_histogram_->Add(HISTOGRAM_REPORT_FLAG_PERSISTENT);
222       if ((flags & kUmaStabilityHistogramFlag) == kUmaStabilityHistogramFlag)
223         report_histogram_->Add(HISTOGRAM_REPORT_FLAG_UMA_STABILITY);
224       else if (flags & kUmaTargetedHistogramFlag)
225         report_histogram_->Add(HISTOGRAM_REPORT_FLAG_UMA_TARGETED);
226       break;
227 
228     case HISTOGRAM_LOOKUP:
229       report_histogram_->Add(HISTOGRAM_REPORT_HISTOGRAM_LOOKUP);
230       break;
231   }
232 }
233 
234 }  // namespace base
235