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