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 
22 namespace base {
23 
24 class DictionaryValue;
25 class HistogramBase;
26 class HistogramSamples;
27 class ListValue;
28 class Pickle;
29 class 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 
36 enum HistogramType {
37   HISTOGRAM,
38   LINEAR_HISTOGRAM,
39   BOOLEAN_HISTOGRAM,
40   CUSTOM_HISTOGRAM,
41   SPARSE_HISTOGRAM,
42 };
43 
44 std::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.
49 enum 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.
81 BASE_EXPORT HistogramBase* DeserializeHistogramInfo(base::PickleIterator* iter);
82 
83 ////////////////////////////////////////////////////////////////////////////////
84 
85 class 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 
histogram_name()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.
flags()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