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