histogram_base.h 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336
  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. #ifndef BASE_METRICS_HISTOGRAM_BASE_H_
  5. #define BASE_METRICS_HISTOGRAM_BASE_H_
  6. #include <limits.h>
  7. #include <stddef.h>
  8. #include <stdint.h>
  9. #include <atomic>
  10. #include <memory>
  11. #include <string>
  12. #include "base/atomicops.h"
  13. #include "base/base_export.h"
  14. #include "base/strings/string_piece.h"
  15. #include "base/time/time.h"
  16. #include "base/values.h"
  17. namespace base {
  18. class Value;
  19. class HistogramBase;
  20. class HistogramSamples;
  21. class Pickle;
  22. class PickleIterator;
  23. ////////////////////////////////////////////////////////////////////////////////
  24. // This enum is used to facilitate deserialization of histograms from other
  25. // processes into the browser. If you create another class that inherits from
  26. // HistogramBase, add new histogram types and names below.
  27. enum HistogramType {
  28. HISTOGRAM,
  29. LINEAR_HISTOGRAM,
  30. BOOLEAN_HISTOGRAM,
  31. CUSTOM_HISTOGRAM,
  32. SPARSE_HISTOGRAM,
  33. DUMMY_HISTOGRAM,
  34. };
  35. // Controls the verbosity of the information when the histogram is serialized to
  36. // a JSON.
  37. // GENERATED_JAVA_ENUM_PACKAGE: org.chromium.base.metrics
  38. enum JSONVerbosityLevel {
  39. // The histogram is completely serialized.
  40. JSON_VERBOSITY_LEVEL_FULL,
  41. // The bucket information is not serialized.
  42. JSON_VERBOSITY_LEVEL_OMIT_BUCKETS,
  43. };
  44. std::string HistogramTypeToString(HistogramType type);
  45. // This enum is used for reporting how many histograms and of what types and
  46. // variations are being created. It has to be in the main .h file so it is
  47. // visible to files that define the various histogram types.
  48. enum HistogramReport {
  49. // Count the number of reports created. The other counts divided by this
  50. // number will give the average per run of the program.
  51. HISTOGRAM_REPORT_CREATED = 0,
  52. // Count the total number of histograms created. It is the limit against
  53. // which all others are compared.
  54. HISTOGRAM_REPORT_HISTOGRAM_CREATED = 1,
  55. // Count the total number of histograms looked-up. It's better to cache
  56. // the result of a single lookup rather than do it repeatedly.
  57. HISTOGRAM_REPORT_HISTOGRAM_LOOKUP = 2,
  58. // These count the individual histogram types. This must follow the order
  59. // of HistogramType above.
  60. HISTOGRAM_REPORT_TYPE_LOGARITHMIC = 3,
  61. HISTOGRAM_REPORT_TYPE_LINEAR = 4,
  62. HISTOGRAM_REPORT_TYPE_BOOLEAN = 5,
  63. HISTOGRAM_REPORT_TYPE_CUSTOM = 6,
  64. HISTOGRAM_REPORT_TYPE_SPARSE = 7,
  65. // These indicate the individual flags that were set.
  66. HISTOGRAM_REPORT_FLAG_UMA_TARGETED = 8,
  67. HISTOGRAM_REPORT_FLAG_UMA_STABILITY = 9,
  68. HISTOGRAM_REPORT_FLAG_PERSISTENT = 10,
  69. // This must be last.
  70. HISTOGRAM_REPORT_MAX = 11
  71. };
  72. // Create or find existing histogram that matches the pickled info.
  73. // Returns NULL if the pickled data has problems.
  74. BASE_EXPORT HistogramBase* DeserializeHistogramInfo(base::PickleIterator* iter);
  75. ////////////////////////////////////////////////////////////////////////////////
  76. class BASE_EXPORT HistogramBase {
  77. public:
  78. typedef int32_t Sample; // Used for samples.
  79. typedef subtle::Atomic32 AtomicCount; // Used to count samples.
  80. typedef int32_t Count; // Used to manipulate counts in temporaries.
  81. static const Sample kSampleType_MAX; // INT_MAX
  82. enum Flags {
  83. kNoFlags = 0x0,
  84. // Histogram should be UMA uploaded.
  85. kUmaTargetedHistogramFlag = 0x1,
  86. // Indicates that this is a stability histogram. This flag exists to specify
  87. // which histograms should be included in the initial stability log. Please
  88. // refer to |MetricsService::PrepareInitialStabilityLog|.
  89. kUmaStabilityHistogramFlag = kUmaTargetedHistogramFlag | 0x2,
  90. // Indicates that the histogram was pickled to be sent across an IPC
  91. // Channel. If we observe this flag on a histogram being aggregated into
  92. // after IPC, then we are running in a single process mode, and the
  93. // aggregation should not take place (as we would be aggregating back into
  94. // the source histogram!).
  95. kIPCSerializationSourceFlag = 0x10,
  96. // Indicates that a callback exists for when a new sample is recorded on
  97. // this histogram. We store this as a flag with the histogram since
  98. // histograms can be in performance critical code, and this allows us
  99. // to shortcut looking up the callback if it doesn't exist.
  100. kCallbackExists = 0x20,
  101. // Indicates that the histogram is held in "persistent" memory and may
  102. // be accessible between processes. This is only possible if such a
  103. // memory segment has been created/attached, used to create a Persistent-
  104. // MemoryAllocator, and that loaded into the Histogram module before this
  105. // histogram is created.
  106. kIsPersistent = 0x40,
  107. };
  108. // Histogram data inconsistency types.
  109. enum Inconsistency : uint32_t {
  110. NO_INCONSISTENCIES = 0x0,
  111. RANGE_CHECKSUM_ERROR = 0x1,
  112. BUCKET_ORDER_ERROR = 0x2,
  113. COUNT_HIGH_ERROR = 0x4,
  114. COUNT_LOW_ERROR = 0x8,
  115. NEVER_EXCEEDED_VALUE = 0x10,
  116. };
  117. // Construct the base histogram. The name is not copied; it's up to the
  118. // caller to ensure that it lives at least as long as this object.
  119. explicit HistogramBase(const char* name);
  120. HistogramBase(const HistogramBase&) = delete;
  121. HistogramBase& operator=(const HistogramBase&) = delete;
  122. virtual ~HistogramBase();
  123. const char* histogram_name() const { return histogram_name_; }
  124. // Compares |name| to the histogram name and triggers a DCHECK if they do not
  125. // match. This is a helper function used by histogram macros, which results in
  126. // in more compact machine code being generated by the macros.
  127. virtual void CheckName(const StringPiece& name) const;
  128. // Get a unique ID for this histogram's samples.
  129. virtual uint64_t name_hash() const = 0;
  130. // Operations with Flags enum.
  131. int32_t flags() const { return flags_.load(std::memory_order_relaxed); }
  132. void SetFlags(int32_t flags);
  133. void ClearFlags(int32_t flags);
  134. virtual HistogramType GetHistogramType() const = 0;
  135. // Whether the histogram has construction arguments as parameters specified.
  136. // For histograms that don't have the concept of minimum, maximum or
  137. // bucket_count, this function always returns false.
  138. virtual bool HasConstructionArguments(Sample expected_minimum,
  139. Sample expected_maximum,
  140. size_t expected_bucket_count) const = 0;
  141. virtual void Add(Sample value) = 0;
  142. // In Add function the |value| bucket is increased by one, but in some use
  143. // cases we need to increase this value by an arbitrary integer. AddCount
  144. // function increases the |value| bucket by |count|. |count| should be greater
  145. // than or equal to 1.
  146. virtual void AddCount(Sample value, int count) = 0;
  147. // Similar to above but divides |count| by the |scale| amount. Probabilistic
  148. // rounding is used to yield a reasonably accurate total when many samples
  149. // are added. Methods for common cases of scales 1000 and 1024 are included.
  150. // The ScaledLinearHistogram (which can also used be for enumerations) may be
  151. // a better (and faster) solution.
  152. void AddScaled(Sample value, int count, int scale);
  153. void AddKilo(Sample value, int count); // scale=1000
  154. void AddKiB(Sample value, int count); // scale=1024
  155. // Convenient functions that call Add(Sample).
  156. void AddTime(const TimeDelta& time) { AddTimeMillisecondsGranularity(time); }
  157. void AddTimeMillisecondsGranularity(const TimeDelta& time);
  158. // Note: AddTimeMicrosecondsGranularity() drops the report if this client
  159. // doesn't have a high-resolution clock.
  160. void AddTimeMicrosecondsGranularity(const TimeDelta& time);
  161. void AddBoolean(bool value);
  162. virtual void AddSamples(const HistogramSamples& samples) = 0;
  163. virtual bool AddSamplesFromPickle(base::PickleIterator* iter) = 0;
  164. // Serialize the histogram info into |pickle|.
  165. // Note: This only serializes the construction arguments of the histogram, but
  166. // does not serialize the samples.
  167. void SerializeInfo(base::Pickle* pickle) const;
  168. // Try to find out data corruption from histogram and the samples.
  169. // The returned value is a combination of Inconsistency enum.
  170. virtual uint32_t FindCorruption(const HistogramSamples& samples) const;
  171. // Snapshot the current complete set of sample data.
  172. // Note that histogram data is stored per-process. The browser process
  173. // periodically injests data from subprocesses. As such, the browser
  174. // process can see histogram data from any process but other processes
  175. // can only see histogram data recorded in the subprocess.
  176. // Moreover, the data returned here may not be up to date:
  177. // - this function does not use a lock so data might not be synced
  178. // (e.g., across cpu caches)
  179. // - in the browser process, the data from subprocesses may not have
  180. // synced data from subprocesses via MergeHistogramDeltas() recently.
  181. //
  182. // Override with atomic/locked snapshot if needed.
  183. // NOTE: this data can overflow for long-running sessions. It should be
  184. // handled with care and this method is recommended to be used only
  185. // in about:histograms and test code.
  186. virtual std::unique_ptr<HistogramSamples> SnapshotSamples() const = 0;
  187. // Calculate the change (delta) in histogram counts since the previous call
  188. // to this method. Each successive call will return only those counts
  189. // changed since the last call.
  190. //
  191. // See additional caveats by SnapshotSamples().
  192. virtual std::unique_ptr<HistogramSamples> SnapshotDelta() = 0;
  193. // Calculate the change (delta) in histogram counts since the previous call
  194. // to SnapshotDelta() but do so without modifying any internal data as to
  195. // what was previous logged. After such a call, no further calls to this
  196. // method or to SnapshotDelta() should be done as the result would include
  197. // data previously returned. Because no internal data is changed, this call
  198. // can be made on "const" histograms such as those with data held in
  199. // read-only memory.
  200. //
  201. // See additional caveats by SnapshotSamples().
  202. virtual std::unique_ptr<HistogramSamples> SnapshotFinalDelta() const = 0;
  203. // The following method provides graphical histogram displays.
  204. virtual void WriteAscii(std::string* output) const;
  205. // Returns histograms data as a Dict (or an empty dict if not available),
  206. // with the following format:
  207. // {"header": "Name of the histogram with samples, mean, and/or flags",
  208. // "body": "ASCII histogram representation"}
  209. virtual base::Value::Dict ToGraphDict() const = 0;
  210. // TODO(bcwhite): Remove this after https://crbug/836875.
  211. virtual void ValidateHistogramContents() const;
  212. // Produce a JSON representation of the histogram with |verbosity_level| as
  213. // the serialization verbosity. This is implemented with the help of
  214. // GetParameters and GetCountAndBucketData; overwrite them to customize the
  215. // output.
  216. void WriteJSON(std::string* output, JSONVerbosityLevel verbosity_level) const;
  217. protected:
  218. enum ReportActivity { HISTOGRAM_CREATED, HISTOGRAM_LOOKUP };
  219. struct BASE_EXPORT CountAndBucketData {
  220. Count count;
  221. int64_t sum;
  222. Value::List buckets;
  223. CountAndBucketData(Count count, int64_t sum, Value::List buckets);
  224. ~CountAndBucketData();
  225. CountAndBucketData(CountAndBucketData&& other);
  226. CountAndBucketData& operator=(CountAndBucketData&& other);
  227. };
  228. // Subclasses should implement this function to make SerializeInfo work.
  229. virtual void SerializeInfoImpl(base::Pickle* pickle) const = 0;
  230. // Writes information about the construction parameters in |params|.
  231. virtual Value::Dict GetParameters() const = 0;
  232. // Returns 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. CountAndBucketData GetCountAndBucketData() const;
  236. // Produces an actual graph (set of blank vs non blank char's) for a bucket.
  237. void WriteAsciiBucketGraph(double x_count,
  238. int line_length,
  239. std::string* output) const;
  240. // Return a string description of what goes in a given bucket.
  241. const std::string GetSimpleAsciiBucketRange(Sample sample) const;
  242. // Write textual description of the bucket contents (relative to histogram).
  243. // Output is the count in the buckets, as well as the percentage.
  244. void WriteAsciiBucketValue(Count current,
  245. double scaled_sum,
  246. std::string* output) const;
  247. // Retrieves the registered callbacks for this histogram, if any, and runs
  248. // them passing |sample| as the parameter.
  249. void FindAndRunCallbacks(Sample sample) const;
  250. // Gets a permanent string that can be used for histogram objects when the
  251. // original is not a code constant or held in persistent memory.
  252. static const char* GetPermanentName(const std::string& name);
  253. private:
  254. friend class HistogramBaseTest;
  255. // A pointer to permanent storage where the histogram name is held. This can
  256. // be code space or the output of GetPermanentName() or any other storage
  257. // that is known to never change. This is not StringPiece because (a) char*
  258. // is 1/2 the size and (b) StringPiece transparently casts from std::string
  259. // which can easily lead to a pointer to non-permanent space.
  260. // For persistent histograms, this will simply point into the persistent
  261. // memory segment, thus avoiding duplication. For heap histograms, the
  262. // GetPermanentName method will create the necessary copy.
  263. const char* const histogram_name_;
  264. // Additional information about the histogram.
  265. std::atomic<int32_t> flags_{0};
  266. };
  267. } // namespace base
  268. #endif // BASE_METRICS_HISTOGRAM_BASE_H_