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#ifndef BASE_METRICS_HISTOGRAM_BASE_H_
6#define BASE_METRICS_HISTOGRAM_BASE_H_
7
8#include <limits.h>
9#include <stddef.h>
10#include <stdint.h>
11
12#include <memory>
13#include <string>
14#include <vector>
15
16#include "base/atomicops.h"
17#include "base/base_export.h"
18#include "base/macros.h"
19#include "base/strings/string_piece.h"
20#include "base/time/time.h"
21
22namespace base {
23
24class DictionaryValue;
25class HistogramBase;
26class HistogramSamples;
27class ListValue;
28class Pickle;
29class PickleIterator;
30
31////////////////////////////////////////////////////////////////////////////////
32// This enum is used to facilitate deserialization of histograms from other
33// processes into the browser. If you create another class that inherits from
34// HistogramBase, add new histogram types and names below.
35
36enum HistogramType {
37  HISTOGRAM,
38  LINEAR_HISTOGRAM,
39  BOOLEAN_HISTOGRAM,
40  CUSTOM_HISTOGRAM,
41  SPARSE_HISTOGRAM,
42};
43
44std::string HistogramTypeToString(HistogramType type);
45
46// This enum is used for reporting how many histograms and of what types and
47// variations are being created. It has to be in the main .h file so it is
48// visible to files that define the various histogram types.
49enum HistogramReport {
50  // Count the number of reports created. The other counts divided by this
51  // number will give the average per run of the program.
52  HISTOGRAM_REPORT_CREATED = 0,
53
54  // Count the total number of histograms created. It is the limit against
55  // which all others are compared.
56  HISTOGRAM_REPORT_HISTOGRAM_CREATED = 1,
57
58  // Count the total number of histograms looked-up. It's better to cache
59  // the result of a single lookup rather than do it repeatedly.
60  HISTOGRAM_REPORT_HISTOGRAM_LOOKUP = 2,
61
62  // These count the individual histogram types. This must follow the order
63  // of HistogramType above.
64  HISTOGRAM_REPORT_TYPE_LOGARITHMIC = 3,
65  HISTOGRAM_REPORT_TYPE_LINEAR = 4,
66  HISTOGRAM_REPORT_TYPE_BOOLEAN = 5,
67  HISTOGRAM_REPORT_TYPE_CUSTOM = 6,
68  HISTOGRAM_REPORT_TYPE_SPARSE = 7,
69
70  // These indicate the individual flags that were set.
71  HISTOGRAM_REPORT_FLAG_UMA_TARGETED = 8,
72  HISTOGRAM_REPORT_FLAG_UMA_STABILITY = 9,
73  HISTOGRAM_REPORT_FLAG_PERSISTENT = 10,
74
75  // This must be last.
76  HISTOGRAM_REPORT_MAX = 11
77};
78
79// Create or find existing histogram that matches the pickled info.
80// Returns NULL if the pickled data has problems.
81BASE_EXPORT HistogramBase* DeserializeHistogramInfo(base::PickleIterator* iter);
82
83////////////////////////////////////////////////////////////////////////////////
84
85class BASE_EXPORT HistogramBase {
86 public:
87  typedef int32_t Sample;                // Used for samples.
88  typedef subtle::Atomic32 AtomicCount;  // Used to count samples.
89  typedef int32_t Count;  // Used to manipulate counts in temporaries.
90
91  static const Sample kSampleType_MAX;  // INT_MAX
92
93  enum Flags {
94    kNoFlags = 0x0,
95
96    // Histogram should be UMA uploaded.
97    kUmaTargetedHistogramFlag = 0x1,
98
99    // Indicates that this is a stability histogram. This flag exists to specify
100    // which histograms should be included in the initial stability log. Please
101    // refer to |MetricsService::PrepareInitialStabilityLog|.
102    kUmaStabilityHistogramFlag = kUmaTargetedHistogramFlag | 0x2,
103
104    // Indicates that the histogram was pickled to be sent across an IPC
105    // Channel. If we observe this flag on a histogram being aggregated into
106    // after IPC, then we are running in a single process mode, and the
107    // aggregation should not take place (as we would be aggregating back into
108    // the source histogram!).
109    kIPCSerializationSourceFlag = 0x10,
110
111    // Indicates that a callback exists for when a new sample is recorded on
112    // this histogram. We store this as a flag with the histogram since
113    // histograms can be in performance critical code, and this allows us
114    // to shortcut looking up the callback if it doesn't exist.
115    kCallbackExists = 0x20,
116
117    // Indicates that the histogram is held in "persistent" memory and may
118    // be accessible between processes. This is only possible if such a
119    // memory segment has been created/attached, used to create a Persistent-
120    // MemoryAllocator, and that loaded into the Histogram module before this
121    // histogram is created.
122    kIsPersistent = 0x40,
123  };
124
125  // Histogram data inconsistency types.
126  enum Inconsistency : uint32_t {
127    NO_INCONSISTENCIES = 0x0,
128    RANGE_CHECKSUM_ERROR = 0x1,
129    BUCKET_ORDER_ERROR = 0x2,
130    COUNT_HIGH_ERROR = 0x4,
131    COUNT_LOW_ERROR = 0x8,
132
133    NEVER_EXCEEDED_VALUE = 0x10,
134  };
135
136  explicit HistogramBase(const std::string& name);
137  virtual ~HistogramBase();
138
139  const std::string& histogram_name() const { return histogram_name_; }
140
141  // Comapres |name| to the histogram name and triggers a DCHECK if they do not
142  // match. This is a helper function used by histogram macros, which results in
143  // in more compact machine code being generated by the macros.
144  void CheckName(const StringPiece& name) const;
145
146  // Get a unique ID for this histogram's samples.
147  virtual uint64_t name_hash() const = 0;
148
149  // Operations with Flags enum.
150  int32_t flags() const { return subtle::NoBarrier_Load(&flags_); }
151  void SetFlags(int32_t flags);
152  void ClearFlags(int32_t flags);
153
154  virtual HistogramType GetHistogramType() const = 0;
155
156  // Whether the histogram has construction arguments as parameters specified.
157  // For histograms that don't have the concept of minimum, maximum or
158  // bucket_count, this function always returns false.
159  virtual bool HasConstructionArguments(
160      Sample expected_minimum,
161      Sample expected_maximum,
162      uint32_t expected_bucket_count) const = 0;
163
164  virtual void Add(Sample value) = 0;
165
166  // In Add function the |value| bucket is increased by one, but in some use
167  // cases we need to increase this value by an arbitrary integer. AddCount
168  // function increases the |value| bucket by |count|. |count| should be greater
169  // than or equal to 1.
170  virtual void AddCount(Sample value, int count) = 0;
171
172  // 2 convenient functions that call Add(Sample).
173  void AddTime(const TimeDelta& time);
174  void AddBoolean(bool value);
175
176  virtual void AddSamples(const HistogramSamples& samples) = 0;
177  virtual bool AddSamplesFromPickle(base::PickleIterator* iter) = 0;
178
179  // Serialize the histogram info into |pickle|.
180  // Note: This only serializes the construction arguments of the histogram, but
181  // does not serialize the samples.
182  bool SerializeInfo(base::Pickle* pickle) const;
183
184  // Try to find out data corruption from histogram and the samples.
185  // The returned value is a combination of Inconsistency enum.
186  virtual uint32_t FindCorruption(const HistogramSamples& samples) const;
187
188  // Snapshot the current complete set of sample data.
189  // Override with atomic/locked snapshot if needed.
190  virtual std::unique_ptr<HistogramSamples> SnapshotSamples() const = 0;
191
192  // Calculate the change (delta) in histogram counts since the previous call
193  // to this method. Each successive call will return only those counts
194  // changed since the last call.
195  virtual std::unique_ptr<HistogramSamples> SnapshotDelta() = 0;
196
197  // Calculate the change (delta) in histogram counts since the previous call
198  // to SnapshotDelta() but do so without modifying any internal data as to
199  // what was previous logged. After such a call, no further calls to this
200  // method or to SnapshotDelta() should be done as the result would include
201  // data previously returned. Because no internal data is changed, this call
202  // can be made on "const" histograms such as those with data held in
203  // read-only memory.
204  virtual std::unique_ptr<HistogramSamples> SnapshotFinalDelta() const = 0;
205
206  // The following methods provide graphical histogram displays.
207  virtual void WriteHTMLGraph(std::string* output) const = 0;
208  virtual void WriteAscii(std::string* output) const = 0;
209
210  // Produce a JSON representation of the histogram. This is implemented with
211  // the help of GetParameters and GetCountAndBucketData; overwrite them to
212  // customize the output.
213  void WriteJSON(std::string* output) const;
214
215  // This enables a histogram that reports the what types of histograms are
216  // created and their flags. It must be called while still single-threaded.
217  //
218  // IMPORTANT: Callers must update tools/metrics/histograms/histograms.xml
219  // with the following histogram:
220  //    UMA.Histograms.process_type.Creations
221  static void EnableActivityReportHistogram(const std::string& process_type);
222
223 protected:
224  enum ReportActivity { HISTOGRAM_CREATED, HISTOGRAM_LOOKUP };
225
226  // Subclasses should implement this function to make SerializeInfo work.
227  virtual bool SerializeInfoImpl(base::Pickle* pickle) const = 0;
228
229  // Writes information about the construction parameters in |params|.
230  virtual void GetParameters(DictionaryValue* params) const = 0;
231
232  // Writes information about the current (non-empty) buckets and their sample
233  // counts to |buckets|, the total sample count to |count| and the total sum
234  // to |sum|.
235  virtual void GetCountAndBucketData(Count* count,
236                                     int64_t* sum,
237                                     ListValue* buckets) const = 0;
238
239  //// Produce actual graph (set of blank vs non blank char's) for a bucket.
240  void WriteAsciiBucketGraph(double current_size,
241                             double max_size,
242                             std::string* output) const;
243
244  // Return a string description of what goes in a given bucket.
245  const std::string GetSimpleAsciiBucketRange(Sample sample) const;
246
247  // Write textual description of the bucket contents (relative to histogram).
248  // Output is the count in the buckets, as well as the percentage.
249  void WriteAsciiBucketValue(Count current,
250                             double scaled_sum,
251                             std::string* output) const;
252
253  // Retrieves the callback for this histogram, if one exists, and runs it
254  // passing |sample| as the parameter.
255  void FindAndRunCallback(Sample sample) const;
256
257  // Update report with an |activity| that occurred for |histogram|.
258  static void ReportHistogramActivity(const HistogramBase& histogram,
259                                      ReportActivity activicty);
260
261  // Retrieves the global histogram reporting what histograms are created.
262  static HistogramBase* report_histogram_;
263
264 private:
265  friend class HistogramBaseTest;
266
267  const std::string histogram_name_;
268  AtomicCount flags_;
269
270  DISALLOW_COPY_AND_ASSIGN(HistogramBase);
271};
272
273}  // namespace base
274
275#endif  // BASE_METRICS_HISTOGRAM_BASE_H_
276