1*6777b538SAndroid Build Coastguard Worker // Copyright 2012 The Chromium Authors 2*6777b538SAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be 3*6777b538SAndroid Build Coastguard Worker // found in the LICENSE file. 4*6777b538SAndroid Build Coastguard Worker 5*6777b538SAndroid Build Coastguard Worker #ifndef BASE_METRICS_HISTOGRAM_SAMPLES_H_ 6*6777b538SAndroid Build Coastguard Worker #define BASE_METRICS_HISTOGRAM_SAMPLES_H_ 7*6777b538SAndroid Build Coastguard Worker 8*6777b538SAndroid Build Coastguard Worker #include <stddef.h> 9*6777b538SAndroid Build Coastguard Worker #include <stdint.h> 10*6777b538SAndroid Build Coastguard Worker 11*6777b538SAndroid Build Coastguard Worker #include <limits> 12*6777b538SAndroid Build Coastguard Worker #include <memory> 13*6777b538SAndroid Build Coastguard Worker #include <string> 14*6777b538SAndroid Build Coastguard Worker #include <string_view> 15*6777b538SAndroid Build Coastguard Worker 16*6777b538SAndroid Build Coastguard Worker #include "base/atomicops.h" 17*6777b538SAndroid Build Coastguard Worker #include "base/base_export.h" 18*6777b538SAndroid Build Coastguard Worker #include "base/gtest_prod_util.h" 19*6777b538SAndroid Build Coastguard Worker #include "base/memory/raw_ptr.h" 20*6777b538SAndroid Build Coastguard Worker #include "base/metrics/histogram_base.h" 21*6777b538SAndroid Build Coastguard Worker 22*6777b538SAndroid Build Coastguard Worker namespace base { 23*6777b538SAndroid Build Coastguard Worker 24*6777b538SAndroid Build Coastguard Worker class Pickle; 25*6777b538SAndroid Build Coastguard Worker class PickleIterator; 26*6777b538SAndroid Build Coastguard Worker class SampleCountIterator; 27*6777b538SAndroid Build Coastguard Worker 28*6777b538SAndroid Build Coastguard Worker // HistogramSamples is a container storing all samples of a histogram. All 29*6777b538SAndroid Build Coastguard Worker // elements must be of a fixed width to ensure 32/64-bit interoperability. 30*6777b538SAndroid Build Coastguard Worker // If this structure changes, bump the version number for kTypeIdHistogram 31*6777b538SAndroid Build Coastguard Worker // in persistent_histogram_allocator.cc. 32*6777b538SAndroid Build Coastguard Worker // 33*6777b538SAndroid Build Coastguard Worker // Note that though these samples are individually consistent (through the use 34*6777b538SAndroid Build Coastguard Worker // of atomic operations on the counts), there is only "eventual consistency" 35*6777b538SAndroid Build Coastguard Worker // overall when multiple threads are accessing this data. That means that the 36*6777b538SAndroid Build Coastguard Worker // sum, redundant-count, etc. could be momentarily out-of-sync with the stored 37*6777b538SAndroid Build Coastguard Worker // counts but will settle to a consistent "steady state" once all threads have 38*6777b538SAndroid Build Coastguard Worker // exited this code. 39*6777b538SAndroid Build Coastguard Worker class BASE_EXPORT HistogramSamples { 40*6777b538SAndroid Build Coastguard Worker public: 41*6777b538SAndroid Build Coastguard Worker // A single bucket and count. To fit within a single atomic on 32-bit build 42*6777b538SAndroid Build Coastguard Worker // architectures, both |bucket| and |count| are limited in size to 16 bits. 43*6777b538SAndroid Build Coastguard Worker // This limits the functionality somewhat but if an entry can't fit then 44*6777b538SAndroid Build Coastguard Worker // the full array of samples can be allocated and used. 45*6777b538SAndroid Build Coastguard Worker struct SingleSample { 46*6777b538SAndroid Build Coastguard Worker uint16_t bucket; 47*6777b538SAndroid Build Coastguard Worker uint16_t count; 48*6777b538SAndroid Build Coastguard Worker }; 49*6777b538SAndroid Build Coastguard Worker 50*6777b538SAndroid Build Coastguard Worker // A structure for managing an atomic single sample. Because this is generally 51*6777b538SAndroid Build Coastguard Worker // used in association with other atomic values, the defined methods use 52*6777b538SAndroid Build Coastguard Worker // acquire/release operations to guarantee ordering with outside values. 53*6777b538SAndroid Build Coastguard Worker union BASE_EXPORT AtomicSingleSample { AtomicSingleSample()54*6777b538SAndroid Build Coastguard Worker AtomicSingleSample() : as_atomic(0) {} AtomicSingleSample(subtle::Atomic32 rhs)55*6777b538SAndroid Build Coastguard Worker explicit AtomicSingleSample(subtle::Atomic32 rhs) : as_atomic(rhs) {} 56*6777b538SAndroid Build Coastguard Worker 57*6777b538SAndroid Build Coastguard Worker // Returns the single sample in an atomic manner. This in an "acquire" 58*6777b538SAndroid Build Coastguard Worker // load. The returned sample isn't shared and thus its fields can be safely 59*6777b538SAndroid Build Coastguard Worker // accessed. If this object is disabled, this will return an empty sample 60*6777b538SAndroid Build Coastguard Worker // (bucket count set to 0). 61*6777b538SAndroid Build Coastguard Worker SingleSample Load() const; 62*6777b538SAndroid Build Coastguard Worker 63*6777b538SAndroid Build Coastguard Worker // Extracts and returns the single sample and changes it to |new_value| in 64*6777b538SAndroid Build Coastguard Worker // an atomic manner. If this object is disabled, this will return an empty 65*6777b538SAndroid Build Coastguard Worker // sample (bucket count set to 0). 66*6777b538SAndroid Build Coastguard Worker SingleSample Extract(AtomicSingleSample new_value = AtomicSingleSample(0)); 67*6777b538SAndroid Build Coastguard Worker 68*6777b538SAndroid Build Coastguard Worker // Like Extract() above, but also disables this object so that it will 69*6777b538SAndroid Build Coastguard Worker // never accumulate another value. If this object is already disabled, this 70*6777b538SAndroid Build Coastguard Worker // will return an empty sample (bucket count set to 0). 71*6777b538SAndroid Build Coastguard Worker SingleSample ExtractAndDisable(); 72*6777b538SAndroid Build Coastguard Worker 73*6777b538SAndroid Build Coastguard Worker // Adds a given count to the held bucket. If not possible, it returns false 74*6777b538SAndroid Build Coastguard Worker // and leaves the parts unchanged. Once extracted/disabled, this always 75*6777b538SAndroid Build Coastguard Worker // returns false. This in an "acquire/release" operation. 76*6777b538SAndroid Build Coastguard Worker bool Accumulate(size_t bucket, HistogramBase::Count count); 77*6777b538SAndroid Build Coastguard Worker 78*6777b538SAndroid Build Coastguard Worker // Returns if the sample has been "disabled" (via Extract) and thus not 79*6777b538SAndroid Build Coastguard Worker // allowed to accept further accumulation. 80*6777b538SAndroid Build Coastguard Worker bool IsDisabled() const; 81*6777b538SAndroid Build Coastguard Worker 82*6777b538SAndroid Build Coastguard Worker private: 83*6777b538SAndroid Build Coastguard Worker // union field: The actual sample bucket and count. 84*6777b538SAndroid Build Coastguard Worker SingleSample as_parts; 85*6777b538SAndroid Build Coastguard Worker 86*6777b538SAndroid Build Coastguard Worker // union field: The sample as an atomic value. Atomic64 would provide 87*6777b538SAndroid Build Coastguard Worker // more flexibility but isn't available on all builds. This can hold a 88*6777b538SAndroid Build Coastguard Worker // special, internal "disabled" value indicating that it must not accept 89*6777b538SAndroid Build Coastguard Worker // further accumulation. 90*6777b538SAndroid Build Coastguard Worker subtle::Atomic32 as_atomic; 91*6777b538SAndroid Build Coastguard Worker }; 92*6777b538SAndroid Build Coastguard Worker 93*6777b538SAndroid Build Coastguard Worker // A structure of information about the data, common to all sample containers. 94*6777b538SAndroid Build Coastguard Worker // Because of how this is used in persistent memory, it must be a POD object 95*6777b538SAndroid Build Coastguard Worker // that makes sense when initialized to all zeros. 96*6777b538SAndroid Build Coastguard Worker struct Metadata { 97*6777b538SAndroid Build Coastguard Worker // Expected size for 32/64-bit check. 98*6777b538SAndroid Build Coastguard Worker static constexpr size_t kExpectedInstanceSize = 24; 99*6777b538SAndroid Build Coastguard Worker 100*6777b538SAndroid Build Coastguard Worker // Initialized when the sample-set is first created with a value provided 101*6777b538SAndroid Build Coastguard Worker // by the caller. It is generally used to identify the sample-set across 102*6777b538SAndroid Build Coastguard Worker // threads and processes, though not necessarily uniquely as it is possible 103*6777b538SAndroid Build Coastguard Worker // to have multiple sample-sets representing subsets of the data. 104*6777b538SAndroid Build Coastguard Worker uint64_t id; 105*6777b538SAndroid Build Coastguard Worker 106*6777b538SAndroid Build Coastguard Worker // The sum of all the entries, effectivly the sum(sample * count) for 107*6777b538SAndroid Build Coastguard Worker // all samples. Despite being atomic, no guarantees are made on the 108*6777b538SAndroid Build Coastguard Worker // accuracy of this value; there may be races during histogram 109*6777b538SAndroid Build Coastguard Worker // accumulation and snapshotting that we choose to accept. It should 110*6777b538SAndroid Build Coastguard Worker // be treated as approximate. 111*6777b538SAndroid Build Coastguard Worker #ifdef ARCH_CPU_64_BITS 112*6777b538SAndroid Build Coastguard Worker subtle::Atomic64 sum; 113*6777b538SAndroid Build Coastguard Worker #else 114*6777b538SAndroid Build Coastguard Worker // 32-bit systems don't have atomic 64-bit operations. Use a basic type 115*6777b538SAndroid Build Coastguard Worker // and don't worry about "shearing". 116*6777b538SAndroid Build Coastguard Worker int64_t sum; 117*6777b538SAndroid Build Coastguard Worker #endif 118*6777b538SAndroid Build Coastguard Worker 119*6777b538SAndroid Build Coastguard Worker // A "redundant" count helps identify memory corruption. It redundantly 120*6777b538SAndroid Build Coastguard Worker // stores the total number of samples accumulated in the histogram. We 121*6777b538SAndroid Build Coastguard Worker // can compare this count to the sum of the counts (TotalCount() function), 122*6777b538SAndroid Build Coastguard Worker // and detect problems. Note, depending on the implementation of different 123*6777b538SAndroid Build Coastguard Worker // histogram types, there might be races during histogram accumulation 124*6777b538SAndroid Build Coastguard Worker // and snapshotting that we choose to accept. In this case, the tallies 125*6777b538SAndroid Build Coastguard Worker // might mismatch even when no memory corruption has happened. 126*6777b538SAndroid Build Coastguard Worker HistogramBase::AtomicCount redundant_count{0}; 127*6777b538SAndroid Build Coastguard Worker 128*6777b538SAndroid Build Coastguard Worker // A single histogram value and associated count. This allows histograms 129*6777b538SAndroid Build Coastguard Worker // that typically report only a single value to not require full storage 130*6777b538SAndroid Build Coastguard Worker // to be allocated. 131*6777b538SAndroid Build Coastguard Worker AtomicSingleSample single_sample; // 32 bits 132*6777b538SAndroid Build Coastguard Worker }; 133*6777b538SAndroid Build Coastguard Worker 134*6777b538SAndroid Build Coastguard Worker // Because structures held in persistent memory must be POD, there can be no 135*6777b538SAndroid Build Coastguard Worker // default constructor to clear the fields. This derived class exists just 136*6777b538SAndroid Build Coastguard Worker // to clear them when being allocated on the heap. 137*6777b538SAndroid Build Coastguard Worker struct BASE_EXPORT LocalMetadata : Metadata { 138*6777b538SAndroid Build Coastguard Worker LocalMetadata(); 139*6777b538SAndroid Build Coastguard Worker }; 140*6777b538SAndroid Build Coastguard Worker 141*6777b538SAndroid Build Coastguard Worker HistogramSamples(const HistogramSamples&) = delete; 142*6777b538SAndroid Build Coastguard Worker HistogramSamples& operator=(const HistogramSamples&) = delete; 143*6777b538SAndroid Build Coastguard Worker virtual ~HistogramSamples(); 144*6777b538SAndroid Build Coastguard Worker 145*6777b538SAndroid Build Coastguard Worker virtual void Accumulate(HistogramBase::Sample value, 146*6777b538SAndroid Build Coastguard Worker HistogramBase::Count count) = 0; 147*6777b538SAndroid Build Coastguard Worker virtual HistogramBase::Count GetCount(HistogramBase::Sample value) const = 0; 148*6777b538SAndroid Build Coastguard Worker virtual HistogramBase::Count TotalCount() const = 0; 149*6777b538SAndroid Build Coastguard Worker 150*6777b538SAndroid Build Coastguard Worker void Add(const HistogramSamples& other); 151*6777b538SAndroid Build Coastguard Worker 152*6777b538SAndroid Build Coastguard Worker // Add from serialized samples. 153*6777b538SAndroid Build Coastguard Worker bool AddFromPickle(PickleIterator* iter); 154*6777b538SAndroid Build Coastguard Worker 155*6777b538SAndroid Build Coastguard Worker void Subtract(const HistogramSamples& other); 156*6777b538SAndroid Build Coastguard Worker 157*6777b538SAndroid Build Coastguard Worker // Adds the samples from |other| while also resetting |other|'s sample counts 158*6777b538SAndroid Build Coastguard Worker // to 0. 159*6777b538SAndroid Build Coastguard Worker void Extract(HistogramSamples& other); 160*6777b538SAndroid Build Coastguard Worker 161*6777b538SAndroid Build Coastguard Worker // Returns an iterator to read the sample counts. 162*6777b538SAndroid Build Coastguard Worker virtual std::unique_ptr<SampleCountIterator> Iterator() const = 0; 163*6777b538SAndroid Build Coastguard Worker 164*6777b538SAndroid Build Coastguard Worker // Returns a special kind of iterator that resets the underlying sample count 165*6777b538SAndroid Build Coastguard Worker // to 0 when Get() is called. The returned iterator must be consumed 166*6777b538SAndroid Build Coastguard Worker // completely before being destroyed, otherwise samples may be lost (this is 167*6777b538SAndroid Build Coastguard Worker // enforced by a DCHECK in the destructor). 168*6777b538SAndroid Build Coastguard Worker virtual std::unique_ptr<SampleCountIterator> ExtractingIterator() = 0; 169*6777b538SAndroid Build Coastguard Worker 170*6777b538SAndroid Build Coastguard Worker // Returns true if |this| is empty (has no samples, has a |sum| of zero, and 171*6777b538SAndroid Build Coastguard Worker // has a |redundant_count| of zero), which is indicative that the caller does 172*6777b538SAndroid Build Coastguard Worker // not need to process |this|. 173*6777b538SAndroid Build Coastguard Worker // - Note 1: This should only be called when |this| is only manipulated on one 174*6777b538SAndroid Build Coastguard Worker // thread at a time (e.g., the underlying data does not change on another 175*6777b538SAndroid Build Coastguard Worker // thread). If this is not the case, then the returned value cannot be trusted 176*6777b538SAndroid Build Coastguard Worker // at all. 177*6777b538SAndroid Build Coastguard Worker // - Note 2: For performance reasons, this is not guaranteed to return the 178*6777b538SAndroid Build Coastguard Worker // correct value. If false is returned, |this| may or may not be empty. 179*6777b538SAndroid Build Coastguard Worker // However, if true is returned, then |this| is guaranteed to be empty (no 180*6777b538SAndroid Build Coastguard Worker // false positives). Of course, this assumes that "Note 1" is respected. 181*6777b538SAndroid Build Coastguard Worker // - Note 3: The base implementation of this method checks for |sum| and 182*6777b538SAndroid Build Coastguard Worker // |redundant_count|, but the child implementations should also check for 183*6777b538SAndroid Build Coastguard Worker // samples. 184*6777b538SAndroid Build Coastguard Worker virtual bool IsDefinitelyEmpty() const; 185*6777b538SAndroid Build Coastguard Worker 186*6777b538SAndroid Build Coastguard Worker void Serialize(Pickle* pickle) const; 187*6777b538SAndroid Build Coastguard Worker 188*6777b538SAndroid Build Coastguard Worker // Returns ASCII representation of histograms data for histogram samples. 189*6777b538SAndroid Build Coastguard Worker // The dictionary returned will be of the form 190*6777b538SAndroid Build Coastguard Worker // {"name":<string>, "header":<string>, "body": <string>} 191*6777b538SAndroid Build Coastguard Worker base::Value::Dict ToGraphDict(std::string_view histogram_name, 192*6777b538SAndroid Build Coastguard Worker int32_t flags) const; 193*6777b538SAndroid Build Coastguard Worker 194*6777b538SAndroid Build Coastguard Worker // Accessor functions. id()195*6777b538SAndroid Build Coastguard Worker uint64_t id() const { return meta_->id; } sum()196*6777b538SAndroid Build Coastguard Worker int64_t sum() const { 197*6777b538SAndroid Build Coastguard Worker #ifdef ARCH_CPU_64_BITS 198*6777b538SAndroid Build Coastguard Worker return subtle::NoBarrier_Load(&meta_->sum); 199*6777b538SAndroid Build Coastguard Worker #else 200*6777b538SAndroid Build Coastguard Worker return meta_->sum; 201*6777b538SAndroid Build Coastguard Worker #endif 202*6777b538SAndroid Build Coastguard Worker } redundant_count()203*6777b538SAndroid Build Coastguard Worker HistogramBase::Count redundant_count() const { 204*6777b538SAndroid Build Coastguard Worker return subtle::NoBarrier_Load(&meta_->redundant_count); 205*6777b538SAndroid Build Coastguard Worker } 206*6777b538SAndroid Build Coastguard Worker 207*6777b538SAndroid Build Coastguard Worker protected: 208*6777b538SAndroid Build Coastguard Worker enum NegativeSampleReason { 209*6777b538SAndroid Build Coastguard Worker SAMPLES_HAVE_LOGGED_BUT_NOT_SAMPLE, 210*6777b538SAndroid Build Coastguard Worker SAMPLES_SAMPLE_LESS_THAN_LOGGED, 211*6777b538SAndroid Build Coastguard Worker SAMPLES_ADDED_NEGATIVE_COUNT, 212*6777b538SAndroid Build Coastguard Worker SAMPLES_ADD_WENT_NEGATIVE, 213*6777b538SAndroid Build Coastguard Worker SAMPLES_ADD_OVERFLOW, 214*6777b538SAndroid Build Coastguard Worker SAMPLES_ACCUMULATE_NEGATIVE_COUNT, 215*6777b538SAndroid Build Coastguard Worker SAMPLES_ACCUMULATE_WENT_NEGATIVE, 216*6777b538SAndroid Build Coastguard Worker DEPRECATED_SAMPLES_ACCUMULATE_OVERFLOW, 217*6777b538SAndroid Build Coastguard Worker SAMPLES_ACCUMULATE_OVERFLOW, 218*6777b538SAndroid Build Coastguard Worker MAX_NEGATIVE_SAMPLE_REASONS 219*6777b538SAndroid Build Coastguard Worker }; 220*6777b538SAndroid Build Coastguard Worker 221*6777b538SAndroid Build Coastguard Worker HistogramSamples(uint64_t id, Metadata* meta); 222*6777b538SAndroid Build Coastguard Worker HistogramSamples(uint64_t id, std::unique_ptr<Metadata> meta); 223*6777b538SAndroid Build Coastguard Worker 224*6777b538SAndroid Build Coastguard Worker // Based on |op| type, add or subtract sample counts data from the iterator. 225*6777b538SAndroid Build Coastguard Worker enum Operator { ADD, SUBTRACT }; 226*6777b538SAndroid Build Coastguard Worker virtual bool AddSubtractImpl(SampleCountIterator* iter, Operator op) = 0; 227*6777b538SAndroid Build Coastguard Worker 228*6777b538SAndroid Build Coastguard Worker // Accumulates to the embedded single-sample field if possible. Returns true 229*6777b538SAndroid Build Coastguard Worker // on success, false otherwise. Sum and redundant-count are also updated in 230*6777b538SAndroid Build Coastguard Worker // the success case. 231*6777b538SAndroid Build Coastguard Worker bool AccumulateSingleSample(HistogramBase::Sample value, 232*6777b538SAndroid Build Coastguard Worker HistogramBase::Count count, 233*6777b538SAndroid Build Coastguard Worker size_t bucket); 234*6777b538SAndroid Build Coastguard Worker 235*6777b538SAndroid Build Coastguard Worker // Atomically adjust the sum and redundant-count. 236*6777b538SAndroid Build Coastguard Worker void IncreaseSumAndCount(int64_t sum, HistogramBase::Count count); 237*6777b538SAndroid Build Coastguard Worker 238*6777b538SAndroid Build Coastguard Worker // Record a negative-sample observation and the reason why. 239*6777b538SAndroid Build Coastguard Worker void RecordNegativeSample(NegativeSampleReason reason, 240*6777b538SAndroid Build Coastguard Worker HistogramBase::Count increment); 241*6777b538SAndroid Build Coastguard Worker single_sample()242*6777b538SAndroid Build Coastguard Worker AtomicSingleSample& single_sample() { return meta_->single_sample; } single_sample()243*6777b538SAndroid Build Coastguard Worker const AtomicSingleSample& single_sample() const { 244*6777b538SAndroid Build Coastguard Worker return meta_->single_sample; 245*6777b538SAndroid Build Coastguard Worker } 246*6777b538SAndroid Build Coastguard Worker 247*6777b538SAndroid Build Coastguard Worker // Produces an actual graph (set of blank vs non blank char's) for a bucket. 248*6777b538SAndroid Build Coastguard Worker static void WriteAsciiBucketGraph(double x_count, 249*6777b538SAndroid Build Coastguard Worker int line_length, 250*6777b538SAndroid Build Coastguard Worker std::string* output); 251*6777b538SAndroid Build Coastguard Worker 252*6777b538SAndroid Build Coastguard Worker // Writes textual description of the bucket contents (relative to histogram). 253*6777b538SAndroid Build Coastguard Worker // Output is the count in the buckets, as well as the percentage. 254*6777b538SAndroid Build Coastguard Worker void WriteAsciiBucketValue(HistogramBase::Count current, 255*6777b538SAndroid Build Coastguard Worker double scaled_sum, 256*6777b538SAndroid Build Coastguard Worker std::string* output) const; 257*6777b538SAndroid Build Coastguard Worker 258*6777b538SAndroid Build Coastguard Worker // Gets a body for this histogram samples. 259*6777b538SAndroid Build Coastguard Worker virtual std::string GetAsciiBody() const; 260*6777b538SAndroid Build Coastguard Worker 261*6777b538SAndroid Build Coastguard Worker // Gets a header message describing this histogram samples. 262*6777b538SAndroid Build Coastguard Worker virtual std::string GetAsciiHeader(std::string_view histogram_name, 263*6777b538SAndroid Build Coastguard Worker int32_t flags) const; 264*6777b538SAndroid Build Coastguard Worker 265*6777b538SAndroid Build Coastguard Worker // Returns a string description of what goes in a given bucket. 266*6777b538SAndroid Build Coastguard Worker const std::string GetSimpleAsciiBucketRange( 267*6777b538SAndroid Build Coastguard Worker HistogramBase::Sample sample) const; 268*6777b538SAndroid Build Coastguard Worker meta()269*6777b538SAndroid Build Coastguard Worker Metadata* meta() { return meta_; } 270*6777b538SAndroid Build Coastguard Worker 271*6777b538SAndroid Build Coastguard Worker private: 272*6777b538SAndroid Build Coastguard Worker FRIEND_TEST_ALL_PREFIXES(HistogramSamplesTest, WriteAsciiBucketGraph); 273*6777b538SAndroid Build Coastguard Worker 274*6777b538SAndroid Build Coastguard Worker // Depending on derived class `meta_` can come from: 275*6777b538SAndroid Build Coastguard Worker // - Local storage: Then `meta_owned_` is set and meta_ points to it. 276*6777b538SAndroid Build Coastguard Worker // - External storage: Then `meta_owned_` is null, and `meta_` point toward an 277*6777b538SAndroid Build Coastguard Worker // external object. The callers guarantees the value will outlive this 278*6777b538SAndroid Build Coastguard Worker // instance. 279*6777b538SAndroid Build Coastguard Worker std::unique_ptr<Metadata> meta_owned_; 280*6777b538SAndroid Build Coastguard Worker raw_ptr<Metadata> meta_; 281*6777b538SAndroid Build Coastguard Worker }; 282*6777b538SAndroid Build Coastguard Worker 283*6777b538SAndroid Build Coastguard Worker class BASE_EXPORT SampleCountIterator { 284*6777b538SAndroid Build Coastguard Worker public: 285*6777b538SAndroid Build Coastguard Worker virtual ~SampleCountIterator(); 286*6777b538SAndroid Build Coastguard Worker 287*6777b538SAndroid Build Coastguard Worker virtual bool Done() const = 0; 288*6777b538SAndroid Build Coastguard Worker virtual void Next() = 0; 289*6777b538SAndroid Build Coastguard Worker 290*6777b538SAndroid Build Coastguard Worker // Get the sample and count at current position. 291*6777b538SAndroid Build Coastguard Worker // Note: |max| is int64_t because histograms support logged values in the 292*6777b538SAndroid Build Coastguard Worker // full int32_t range and bucket max is exclusive, so it needs to support 293*6777b538SAndroid Build Coastguard Worker // values up to MAXINT32+1. 294*6777b538SAndroid Build Coastguard Worker // Requires: !Done(); 295*6777b538SAndroid Build Coastguard Worker virtual void Get(HistogramBase::Sample* min, 296*6777b538SAndroid Build Coastguard Worker int64_t* max, 297*6777b538SAndroid Build Coastguard Worker HistogramBase::Count* count) = 0; 298*6777b538SAndroid Build Coastguard Worker static_assert(std::numeric_limits<HistogramBase::Sample>::max() < 299*6777b538SAndroid Build Coastguard Worker std::numeric_limits<int64_t>::max(), 300*6777b538SAndroid Build Coastguard Worker "Get() |max| must be able to hold Histogram::Sample max + 1"); 301*6777b538SAndroid Build Coastguard Worker 302*6777b538SAndroid Build Coastguard Worker // Get the index of current histogram bucket. 303*6777b538SAndroid Build Coastguard Worker // For histograms that don't use predefined buckets, it returns false. 304*6777b538SAndroid Build Coastguard Worker // Requires: !Done(); 305*6777b538SAndroid Build Coastguard Worker virtual bool GetBucketIndex(size_t* index) const; 306*6777b538SAndroid Build Coastguard Worker }; 307*6777b538SAndroid Build Coastguard Worker 308*6777b538SAndroid Build Coastguard Worker class BASE_EXPORT SingleSampleIterator : public SampleCountIterator { 309*6777b538SAndroid Build Coastguard Worker public: 310*6777b538SAndroid Build Coastguard Worker SingleSampleIterator(HistogramBase::Sample min, 311*6777b538SAndroid Build Coastguard Worker int64_t max, 312*6777b538SAndroid Build Coastguard Worker HistogramBase::Count count, 313*6777b538SAndroid Build Coastguard Worker size_t bucket_index, 314*6777b538SAndroid Build Coastguard Worker bool value_was_extracted); 315*6777b538SAndroid Build Coastguard Worker ~SingleSampleIterator() override; 316*6777b538SAndroid Build Coastguard Worker 317*6777b538SAndroid Build Coastguard Worker // SampleCountIterator: 318*6777b538SAndroid Build Coastguard Worker bool Done() const override; 319*6777b538SAndroid Build Coastguard Worker void Next() override; 320*6777b538SAndroid Build Coastguard Worker void Get(HistogramBase::Sample* min, 321*6777b538SAndroid Build Coastguard Worker int64_t* max, 322*6777b538SAndroid Build Coastguard Worker HistogramBase::Count* count) override; 323*6777b538SAndroid Build Coastguard Worker 324*6777b538SAndroid Build Coastguard Worker // SampleVector uses predefined buckets so iterator can return bucket index. 325*6777b538SAndroid Build Coastguard Worker bool GetBucketIndex(size_t* index) const override; 326*6777b538SAndroid Build Coastguard Worker 327*6777b538SAndroid Build Coastguard Worker private: 328*6777b538SAndroid Build Coastguard Worker // Information about the single value to return. 329*6777b538SAndroid Build Coastguard Worker const HistogramBase::Sample min_; 330*6777b538SAndroid Build Coastguard Worker const int64_t max_; 331*6777b538SAndroid Build Coastguard Worker const size_t bucket_index_; 332*6777b538SAndroid Build Coastguard Worker HistogramBase::Count count_; 333*6777b538SAndroid Build Coastguard Worker 334*6777b538SAndroid Build Coastguard Worker // Whether the value that this iterator holds was extracted from the 335*6777b538SAndroid Build Coastguard Worker // underlying data (i.e., reset to 0). 336*6777b538SAndroid Build Coastguard Worker const bool value_was_extracted_; 337*6777b538SAndroid Build Coastguard Worker }; 338*6777b538SAndroid Build Coastguard Worker 339*6777b538SAndroid Build Coastguard Worker } // namespace base 340*6777b538SAndroid Build Coastguard Worker 341*6777b538SAndroid Build Coastguard Worker #endif // BASE_METRICS_HISTOGRAM_SAMPLES_H_ 342