1 // Copyright 2012 The Chromium Authors 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 // Histogram is an object that aggregates statistics, and can summarize them in 6 // various forms, including ASCII graphical, HTML, and numerically (as a 7 // vector of numbers corresponding to each of the aggregating buckets). 8 9 // It supports calls to accumulate either time intervals (which are processed 10 // as integral number of milliseconds), or arbitrary integral units. 11 12 // For Histogram (exponential histogram), LinearHistogram and CustomHistogram, 13 // the minimum for a declared range is 1 (instead of 0), while the maximum is 14 // (HistogramBase::kSampleType_MAX - 1). However, there will always be underflow 15 // and overflow buckets added automatically, so a 0 bucket will always exist 16 // even when a minimum value of 1 is specified. 17 18 // Each use of a histogram with the same name will reference the same underlying 19 // data, so it is safe to record to the same histogram from multiple locations 20 // in the code. It is a runtime error if all uses of the same histogram do not 21 // agree exactly in type, bucket size and range. 22 23 // For Histogram and LinearHistogram, the maximum for a declared range should 24 // always be larger (not equal) than minimal range. Zero and 25 // HistogramBase::kSampleType_MAX are implicitly added as first and last ranges, 26 // so the smallest legal bucket_count is 3. However CustomHistogram can have 27 // bucket count as 2 (when you give a custom ranges vector containing only 1 28 // range). 29 // For these 3 kinds of histograms, the max bucket count is always 30 // (Histogram::kBucketCount_MAX - 1). 31 32 // The buckets layout of class Histogram is exponential. For example, buckets 33 // might contain (sequentially) the count of values in the following intervals: 34 // [0,1), [1,2), [2,4), [4,8), [8,16), [16,32), [32,64), [64,infinity) 35 // That bucket allocation would actually result from construction of a histogram 36 // for values between 1 and 64, with 8 buckets, such as: 37 // Histogram count("some name", 1, 64, 8); 38 // Note that the underflow bucket [0,1) and the overflow bucket [64,infinity) 39 // are also counted by the constructor in the user supplied "bucket_count" 40 // argument. 41 // The above example has an exponential ratio of 2 (doubling the bucket width 42 // in each consecutive bucket). The Histogram class automatically calculates 43 // the smallest ratio that it can use to construct the number of buckets 44 // selected in the constructor. An another example, if you had 50 buckets, 45 // and millisecond time values from 1 to 10000, then the ratio between 46 // consecutive bucket widths will be approximately somewhere around the 50th 47 // root of 10000. This approach provides very fine grain (narrow) buckets 48 // at the low end of the histogram scale, but allows the histogram to cover a 49 // gigantic range with the addition of very few buckets. 50 51 // Usually we use macros to define and use a histogram, which are defined in 52 // base/metrics/histogram_macros.h. Note: Callers should include that header 53 // directly if they only access the histogram APIs through macros. 54 // 55 // Macros use a pattern involving a function static variable, that is a pointer 56 // to a histogram. This static is explicitly initialized on any thread 57 // that detects a uninitialized (NULL) pointer. The potentially racy 58 // initialization is not a problem as it is always set to point to the same 59 // value (i.e., the FactoryGet always returns the same value). FactoryGet 60 // is also completely thread safe, which results in a completely thread safe, 61 // and relatively fast, set of counters. To avoid races at shutdown, the static 62 // pointer is NOT deleted, and we leak the histograms at process termination. 63 64 #ifndef BASE_METRICS_HISTOGRAM_H_ 65 #define BASE_METRICS_HISTOGRAM_H_ 66 67 #include <stddef.h> 68 #include <stdint.h> 69 70 #include <map> 71 #include <memory> 72 #include <string> 73 #include <string_view> 74 #include <vector> 75 76 #include "base/base_export.h" 77 #include "base/compiler_specific.h" 78 #include "base/containers/span.h" 79 #include "base/dcheck_is_on.h" 80 #include "base/gtest_prod_util.h" 81 #include "base/memory/raw_ptr.h" 82 #include "base/metrics/bucket_ranges.h" 83 #include "base/metrics/histogram_base.h" 84 #include "base/metrics/histogram_samples.h" 85 #include "base/time/time.h" 86 #include "base/values.h" 87 88 namespace base { 89 90 class BooleanHistogram; 91 class CustomHistogram; 92 class DelayedPersistentAllocation; 93 class Histogram; 94 class HistogramTest; 95 class LinearHistogram; 96 class Pickle; 97 class PickleIterator; 98 class SampleVector; 99 class SampleVectorBase; 100 101 class BASE_EXPORT Histogram : public HistogramBase { 102 public: 103 // Initialize maximum number of buckets in histograms as 1000, plus over and 104 // under. This must be a value that fits in a uint32_t (since that's how we 105 // serialize bucket counts) as well as a Sample (since samples can be up to 106 // this value). 107 static constexpr size_t kBucketCount_MAX = 1002; 108 109 typedef std::vector<Count> Counts; 110 111 Histogram(const Histogram&) = delete; 112 Histogram& operator=(const Histogram&) = delete; 113 114 ~Histogram() override; 115 116 //---------------------------------------------------------------------------- 117 // For a valid histogram, input should follow these restrictions: 118 // minimum > 0 (if a minimum below 1 is specified, it will implicitly be 119 // normalized up to 1) 120 // maximum > minimum 121 // buckets > 2 [minimum buckets needed: underflow, overflow and the range] 122 // Additionally, 123 // buckets <= (maximum - minimum + 2) - this is to ensure that we don't have 124 // more buckets than the range of numbers; having more buckets than 1 per 125 // value in the range would be nonsensical. 126 static HistogramBase* FactoryGet(std::string_view name, 127 Sample minimum, 128 Sample maximum, 129 size_t bucket_count, 130 int32_t flags); 131 static HistogramBase* FactoryTimeGet(std::string_view name, 132 base::TimeDelta minimum, 133 base::TimeDelta maximum, 134 size_t bucket_count, 135 int32_t flags); 136 static HistogramBase* FactoryMicrosecondsTimeGet(std::string_view name, 137 base::TimeDelta minimum, 138 base::TimeDelta maximum, 139 size_t bucket_count, 140 int32_t flags); 141 142 // Overloads of the above functions that take a const std::string& or const 143 // char* |name| param, to avoid code bloat from the std::string constructor 144 // being inlined into call sites. 145 static HistogramBase* FactoryGet(const std::string& name, 146 Sample minimum, 147 Sample maximum, 148 size_t bucket_count, 149 int32_t flags); 150 static HistogramBase* FactoryTimeGet(const std::string& name, 151 base::TimeDelta minimum, 152 base::TimeDelta maximum, 153 size_t bucket_count, 154 int32_t flags); 155 static HistogramBase* FactoryMicrosecondsTimeGet(const std::string& name, 156 base::TimeDelta minimum, 157 base::TimeDelta maximum, 158 size_t bucket_count, 159 int32_t flags); 160 161 static HistogramBase* FactoryGet(const char* name, 162 Sample minimum, 163 Sample maximum, 164 size_t bucket_count, 165 int32_t flags); 166 static HistogramBase* FactoryTimeGet(const char* name, 167 base::TimeDelta minimum, 168 base::TimeDelta maximum, 169 size_t bucket_count, 170 int32_t flags); 171 static HistogramBase* FactoryMicrosecondsTimeGet(const char* name, 172 base::TimeDelta minimum, 173 base::TimeDelta maximum, 174 size_t bucket_count, 175 int32_t flags); 176 177 // Create a histogram using data in persistent storage. 178 static std::unique_ptr<HistogramBase> PersistentCreate( 179 const char* name, 180 const BucketRanges* ranges, 181 const DelayedPersistentAllocation& counts, 182 const DelayedPersistentAllocation& logged_counts, 183 HistogramSamples::Metadata* meta, 184 HistogramSamples::Metadata* logged_meta); 185 186 static void InitializeBucketRanges(Sample minimum, 187 Sample maximum, 188 BucketRanges* ranges); 189 190 // This constant if for FindCorruption. Since snapshots of histograms are 191 // taken asynchronously relative to sampling, and our counting code currently 192 // does not prevent race conditions, it is pretty likely that we'll catch a 193 // redundant count that doesn't match the sample count. We allow for a 194 // certain amount of slop before flagging this as an inconsistency. Even with 195 // an inconsistency, we'll snapshot it again (for UMA in about a half hour), 196 // so we'll eventually get the data, if it was not the result of a corruption. 197 static const int kCommonRaceBasedCountMismatch; 198 199 // Check to see if bucket ranges, counts and tallies in the snapshot are 200 // consistent with the bucket ranges and checksums in our histogram. This can 201 // produce a false-alarm if a race occurred in the reading of the data during 202 // a SnapShot process, but should otherwise be false at all times (unless we 203 // have memory over-writes, or DRAM failures). Flag definitions are located 204 // under "enum Inconsistency" in base/metrics/histogram_base.h. 205 uint32_t FindCorruption(const HistogramSamples& samples) const override; 206 207 //---------------------------------------------------------------------------- 208 // Accessors for factory construction, serialization and testing. 209 //---------------------------------------------------------------------------- 210 const BucketRanges* bucket_ranges() const; 211 Sample declared_min() const; 212 Sample declared_max() const; 213 virtual Sample ranges(size_t i) const; 214 virtual size_t bucket_count() const; 215 216 // This function validates histogram construction arguments. It returns false 217 // if some of the arguments are bad but also corrects them so they should 218 // function on non-dcheck builds without crashing. 219 // Note. Currently it allow some bad input, e.g. 0 as minimum, but silently 220 // converts it to good input: 1. 221 static bool InspectConstructionArguments(std::string_view name, 222 Sample* minimum, 223 Sample* maximum, 224 size_t* bucket_count); 225 226 // HistogramBase implementation: 227 uint64_t name_hash() const override; 228 HistogramType GetHistogramType() const override; 229 bool HasConstructionArguments(Sample expected_minimum, 230 Sample expected_maximum, 231 size_t expected_bucket_count) const override; 232 void Add(Sample value) override; 233 void AddCount(Sample value, int count) override; 234 std::unique_ptr<HistogramSamples> SnapshotSamples() const override; 235 std::unique_ptr<HistogramSamples> SnapshotUnloggedSamples() const override; 236 void MarkSamplesAsLogged(const HistogramSamples& samples) final; 237 std::unique_ptr<HistogramSamples> SnapshotDelta() override; 238 std::unique_ptr<HistogramSamples> SnapshotFinalDelta() const override; 239 bool AddSamples(const HistogramSamples& samples) override; 240 bool AddSamplesFromPickle(base::PickleIterator* iter) override; 241 base::Value::Dict ToGraphDict() const override; 242 243 protected: 244 // This class, defined entirely within the .cc file, contains all the 245 // common logic for building a Histogram and can be overridden by more 246 // specific types to alter details of how the creation is done. It is 247 // defined as an embedded class (rather than an anonymous one) so it 248 // can access the protected constructors. 249 class Factory; 250 251 // |ranges| should contain the underflow and overflow buckets. See top 252 // comments for example. 253 Histogram(const char* name, const BucketRanges* ranges); 254 255 // Traditionally, histograms allocate their own memory for the bucket 256 // vector but "shared" histograms use memory regions allocated from a 257 // special memory segment that is passed in here. It is assumed that 258 // the life of this memory is managed externally and exceeds the lifetime 259 // of this object. Practically, this memory is never released until the 260 // process exits and the OS cleans it up. 261 Histogram(const char* name, 262 const BucketRanges* ranges, 263 const DelayedPersistentAllocation& counts, 264 const DelayedPersistentAllocation& logged_counts, 265 HistogramSamples::Metadata* meta, 266 HistogramSamples::Metadata* logged_meta); 267 268 // HistogramBase implementation: 269 void SerializeInfoImpl(base::Pickle* pickle) const override; 270 271 // Return a string description of what goes in a given bucket. 272 // Most commonly this is the numeric value, but in derived classes it may 273 // be a name (or string description) given to the bucket. 274 virtual std::string GetAsciiBucketRange(size_t it) const; 275 276 private: 277 // Allow tests to corrupt our innards for testing purposes. 278 friend class HistogramTest; 279 friend class HistogramThreadsafeTest; 280 FRIEND_TEST_ALL_PREFIXES(HistogramTest, BoundsTest); 281 FRIEND_TEST_ALL_PREFIXES(HistogramTest, BucketPlacementTest); 282 FRIEND_TEST_ALL_PREFIXES(HistogramTest, CorruptSampleCounts); 283 284 friend class StatisticsRecorder; // To allow it to delete duplicates. 285 friend class StatisticsRecorderTest; 286 287 friend BASE_EXPORT HistogramBase* DeserializeHistogramInfo( 288 base::PickleIterator* iter); 289 static HistogramBase* DeserializeInfoImpl(base::PickleIterator* iter); 290 291 static HistogramBase* FactoryGetInternal(std::string_view name, 292 Sample minimum, 293 Sample maximum, 294 size_t bucket_count, 295 int32_t flags); 296 static HistogramBase* FactoryTimeGetInternal(std::string_view name, 297 base::TimeDelta minimum, 298 base::TimeDelta maximum, 299 size_t bucket_count, 300 int32_t flags); 301 static HistogramBase* FactoryMicrosecondsTimeGetInternal( 302 std::string_view name, 303 base::TimeDelta minimum, 304 base::TimeDelta maximum, 305 size_t bucket_count, 306 int32_t flags); 307 308 // Create a snapshot containing all samples (both logged and unlogged). 309 // Implementation of SnapshotSamples method with a more specific type for 310 // internal use. 311 std::unique_ptr<SampleVector> SnapshotAllSamples() const; 312 313 // Returns a copy of unlogged samples as the underlying SampleVector class, 314 // instead of the HistogramSamples base class. Used for tests and to avoid 315 // virtual dispatch from some callsites. 316 std::unique_ptr<SampleVector> SnapshotUnloggedSamplesImpl() const; 317 318 // Writes the type, min, max, and bucket count information of the histogram in 319 // |params|. 320 Value::Dict GetParameters() const override; 321 322 // Samples that have not yet been logged with SnapshotDelta(). 323 std::unique_ptr<SampleVectorBase> unlogged_samples_; 324 325 // Accumulation of all samples that have been logged with SnapshotDelta(). 326 std::unique_ptr<SampleVectorBase> logged_samples_; 327 328 #if DCHECK_IS_ON() // Don't waste memory if it won't be used. 329 // Flag to indicate if PrepareFinalDelta has been previously called. It is 330 // used to DCHECK that a final delta is not created multiple times. 331 mutable bool final_delta_created_ = false; 332 #endif 333 }; 334 335 //------------------------------------------------------------------------------ 336 337 // LinearHistogram is a more traditional histogram, with evenly spaced 338 // buckets. 339 class BASE_EXPORT LinearHistogram : public Histogram { 340 public: 341 LinearHistogram(const LinearHistogram&) = delete; 342 LinearHistogram& operator=(const LinearHistogram&) = delete; 343 344 ~LinearHistogram() override; 345 346 /* minimum should start from 1. 0 is as minimum is invalid. 0 is an implicit 347 default underflow bucket. */ 348 static HistogramBase* FactoryGet(std::string_view name, 349 Sample minimum, 350 Sample maximum, 351 size_t bucket_count, 352 int32_t flags); 353 static HistogramBase* FactoryTimeGet(std::string_view name, 354 TimeDelta minimum, 355 TimeDelta maximum, 356 size_t bucket_count, 357 int32_t flags); 358 359 // Overloads of the above two functions that take a const std::string& or 360 // const char* |name| param, to avoid code bloat from the std::string 361 // constructor being inlined into call sites. 362 static HistogramBase* FactoryGet(const std::string& name, 363 Sample minimum, 364 Sample maximum, 365 size_t bucket_count, 366 int32_t flags); 367 static HistogramBase* FactoryTimeGet(const std::string& name, 368 TimeDelta minimum, 369 TimeDelta maximum, 370 size_t bucket_count, 371 int32_t flags); 372 373 static HistogramBase* FactoryGet(const char* name, 374 Sample minimum, 375 Sample maximum, 376 size_t bucket_count, 377 int32_t flags); 378 static HistogramBase* FactoryTimeGet(const char* name, 379 TimeDelta minimum, 380 TimeDelta maximum, 381 size_t bucket_count, 382 int32_t flags); 383 384 // Create a histogram using data in persistent storage. 385 static std::unique_ptr<HistogramBase> PersistentCreate( 386 const char* name, 387 const BucketRanges* ranges, 388 const DelayedPersistentAllocation& counts, 389 const DelayedPersistentAllocation& logged_counts, 390 HistogramSamples::Metadata* meta, 391 HistogramSamples::Metadata* logged_meta); 392 393 struct DescriptionPair { 394 Sample sample; 395 const char* description; // Null means end of a list of pairs. 396 }; 397 398 // Create a LinearHistogram and store a list of number/text values for use in 399 // writing the histogram graph. 400 // |descriptions| can be NULL, which means no special descriptions to set. If 401 // it's not NULL, the last element in the array must has a NULL in its 402 // "description" field. 403 static HistogramBase* FactoryGetWithRangeDescription( 404 std::string_view name, 405 Sample minimum, 406 Sample maximum, 407 size_t bucket_count, 408 int32_t flags, 409 const DescriptionPair descriptions[]); 410 411 static void InitializeBucketRanges(Sample minimum, 412 Sample maximum, 413 BucketRanges* ranges); 414 415 // Overridden from Histogram: 416 HistogramType GetHistogramType() const override; 417 418 protected: 419 class Factory; 420 421 LinearHistogram(const char* name, const BucketRanges* ranges); 422 423 LinearHistogram(const char* name, 424 const BucketRanges* ranges, 425 const DelayedPersistentAllocation& counts, 426 const DelayedPersistentAllocation& logged_counts, 427 HistogramSamples::Metadata* meta, 428 HistogramSamples::Metadata* logged_meta); 429 430 // If we have a description for a bucket, then return that. Otherwise 431 // let parent class provide a (numeric) description. 432 std::string GetAsciiBucketRange(size_t i) const override; 433 434 private: 435 friend BASE_EXPORT HistogramBase* DeserializeHistogramInfo( 436 base::PickleIterator* iter); 437 static HistogramBase* DeserializeInfoImpl(base::PickleIterator* iter); 438 439 static HistogramBase* FactoryGetInternal(std::string_view name, 440 Sample minimum, 441 Sample maximum, 442 size_t bucket_count, 443 int32_t flags); 444 static HistogramBase* FactoryTimeGetInternal(std::string_view name, 445 TimeDelta minimum, 446 TimeDelta maximum, 447 size_t bucket_count, 448 int32_t flags); 449 450 // For some ranges, we store a printable description of a bucket range. 451 // If there is no description, then GetAsciiBucketRange() uses parent class 452 // to provide a description. 453 typedef std::map<Sample, std::string> BucketDescriptionMap; 454 BucketDescriptionMap bucket_description_; 455 }; 456 457 //------------------------------------------------------------------------------ 458 459 // ScaledLinearHistogram is a wrapper around a linear histogram that scales the 460 // counts down by some factor. Remainder values are kept locally but lost when 461 // uploaded or serialized. The integral counts are rounded up/down so should 462 // average to the correct value when many reports are added. 463 // 464 // This is most useful when adding many counts at once via AddCount() that can 465 // cause overflows of the 31-bit counters, usually with an enum as the value. 466 class BASE_EXPORT ScaledLinearHistogram { 467 using AtomicCount = Histogram::AtomicCount; 468 using Sample = Histogram::Sample; 469 470 public: 471 // Currently only works with "exact" linear histograms: minimum=1, maximum=N, 472 // and bucket_count=N+1. 473 ScaledLinearHistogram(std::string_view name, 474 Sample minimum, 475 Sample maximum, 476 size_t bucket_count, 477 int32_t scale, 478 int32_t flags); 479 480 // Overload of the above function that take a const std::string& or const 481 // char* |name| param, to avoid code bloat from the std::string constructor 482 // being inlined into call sites. 483 ScaledLinearHistogram(const char* name, 484 Sample minimum, 485 Sample maximum, 486 size_t bucket_count, 487 int32_t scale, 488 int32_t flags); 489 ScaledLinearHistogram(const std::string& name, 490 Sample minimum, 491 Sample maximum, 492 size_t bucket_count, 493 int32_t scale, 494 int32_t flags); 495 496 ScaledLinearHistogram(const ScaledLinearHistogram&) = delete; 497 ScaledLinearHistogram& operator=(const ScaledLinearHistogram&) = delete; 498 499 ~ScaledLinearHistogram(); 500 501 // Like AddCount() but actually accumulates |count|/|scale| and increments 502 // the accumulated remainder by |count|%|scale|. An additional increment 503 // is done when the remainder has grown sufficiently large. 504 // The value after scaling must fit into 32-bit signed integer. 505 void AddScaledCount(Sample value, int64_t count); 506 scale()507 int32_t scale() const { return scale_; } histogram()508 HistogramBase* histogram() { return histogram_; } 509 510 private: 511 // Pointer to the underlying histogram. Ownership of it remains with 512 // the statistics-recorder. This is typed as HistogramBase because it may be a 513 // DummyHistogram if expired. 514 const raw_ptr<HistogramBase> histogram_; 515 516 // The scale factor of the sample counts. 517 const int32_t scale_; 518 519 // A vector of "remainder" counts indexed by bucket number. These values 520 // may be negative as the scaled count is actually bumped once the 521 // remainder is 1/2 way to the scale value (thus "rounding"). 522 std::vector<AtomicCount> remainders_; 523 }; 524 525 //------------------------------------------------------------------------------ 526 527 // BooleanHistogram is a histogram for booleans. 528 class BASE_EXPORT BooleanHistogram : public LinearHistogram { 529 public: 530 static HistogramBase* FactoryGet(std::string_view name, int32_t flags); 531 532 // Overload of the above function that take a const std::string& or const 533 // char* |name| param, to avoid code bloat from the std::string constructor 534 // being inlined into call sites. 535 static HistogramBase* FactoryGet(const std::string& name, int32_t flags); 536 static HistogramBase* FactoryGet(const char* name, int32_t flags); 537 538 BooleanHistogram(const BooleanHistogram&) = delete; 539 BooleanHistogram& operator=(const BooleanHistogram&) = delete; 540 541 // Create a histogram using data in persistent storage. 542 static std::unique_ptr<HistogramBase> PersistentCreate( 543 const char* name, 544 const BucketRanges* ranges, 545 const DelayedPersistentAllocation& counts, 546 const DelayedPersistentAllocation& logged_counts, 547 HistogramSamples::Metadata* meta, 548 HistogramSamples::Metadata* logged_meta); 549 550 HistogramType GetHistogramType() const override; 551 552 protected: 553 class Factory; 554 555 private: 556 static HistogramBase* FactoryGetInternal(std::string_view name, 557 int32_t flags); 558 559 BooleanHistogram(const char* name, const BucketRanges* ranges); 560 BooleanHistogram(const char* name, 561 const BucketRanges* ranges, 562 const DelayedPersistentAllocation& counts, 563 const DelayedPersistentAllocation& logged_counts, 564 HistogramSamples::Metadata* meta, 565 HistogramSamples::Metadata* logged_meta); 566 567 friend BASE_EXPORT HistogramBase* DeserializeHistogramInfo( 568 base::PickleIterator* iter); 569 static HistogramBase* DeserializeInfoImpl(base::PickleIterator* iter); 570 }; 571 572 //------------------------------------------------------------------------------ 573 574 // CustomHistogram is a histogram for a set of custom integers. 575 class BASE_EXPORT CustomHistogram : public Histogram { 576 public: 577 // |custom_ranges| contains a vector of limits on ranges. Each limit should be 578 // > 0 and < kSampleType_MAX. (Currently 0 is still accepted for backward 579 // compatibility). The limits can be unordered or contain duplication, but 580 // client should not depend on this. 581 static HistogramBase* FactoryGet(std::string_view name, 582 const std::vector<Sample>& custom_ranges, 583 int32_t flags); 584 585 // Overload of the above function that take a const std::string& or const 586 // char* |name| param, to avoid code bloat from the std::string constructor 587 // being inlined into call sites. 588 static HistogramBase* FactoryGet(const std::string& name, 589 const std::vector<Sample>& custom_ranges, 590 int32_t flags); 591 static HistogramBase* FactoryGet(const char* name, 592 const std::vector<Sample>& custom_ranges, 593 int32_t flags); 594 595 CustomHistogram(const CustomHistogram&) = delete; 596 CustomHistogram& operator=(const CustomHistogram&) = delete; 597 598 // Create a histogram using data in persistent storage. 599 static std::unique_ptr<HistogramBase> PersistentCreate( 600 const char* name, 601 const BucketRanges* ranges, 602 const DelayedPersistentAllocation& counts, 603 const DelayedPersistentAllocation& logged_counts, 604 HistogramSamples::Metadata* meta, 605 HistogramSamples::Metadata* logged_meta); 606 607 // Overridden from Histogram: 608 HistogramType GetHistogramType() const override; 609 610 // Helper method for transforming an array of valid enumeration values 611 // to the std::vector<int> expected by UMA_HISTOGRAM_CUSTOM_ENUMERATION. 612 // This function ensures that a guard bucket exists right after any 613 // valid sample value (unless the next higher sample is also a valid value), 614 // so that invalid samples never fall into the same bucket as valid samples. 615 static std::vector<Sample> ArrayToCustomEnumRanges( 616 base::span<const Sample> values); 617 618 protected: 619 class Factory; 620 621 CustomHistogram(const char* name, const BucketRanges* ranges); 622 623 CustomHistogram(const char* name, 624 const BucketRanges* ranges, 625 const DelayedPersistentAllocation& counts, 626 const DelayedPersistentAllocation& logged_counts, 627 HistogramSamples::Metadata* meta, 628 HistogramSamples::Metadata* logged_meta); 629 630 // HistogramBase implementation: 631 void SerializeInfoImpl(base::Pickle* pickle) const override; 632 633 private: 634 friend BASE_EXPORT HistogramBase* DeserializeHistogramInfo( 635 base::PickleIterator* iter); 636 static HistogramBase* DeserializeInfoImpl(base::PickleIterator* iter); 637 638 static HistogramBase* FactoryGetInternal( 639 std::string_view name, 640 const std::vector<Sample>& custom_ranges, 641 int32_t flags); 642 643 static bool ValidateCustomRanges(const std::vector<Sample>& custom_ranges); 644 }; 645 646 namespace internal { 647 648 // Controls whether invocations of UMA_HISTOGRAM_SPLIT_BY_PROCESS_PRIORITY in 649 // this process log to their ".BestEffort" suffix or not. Timing metrics 650 // reported through UMA_HISTOGRAM_SPLIT_BY_PROCESS_PRIORITY which overlap a 651 // best-effort range will be suffixed with ".BestEffort". 652 BASE_EXPORT void SetSharedLastForegroundTimeForMetrics( 653 const std::atomic<TimeTicks>* last_foreground_time_ref); 654 655 // Returns the pointer passed to SetSharedLastForegroundTimeForMetrics, or 656 // nullptr if it was never called. 657 BASE_EXPORT const std::atomic<TimeTicks>* 658 GetSharedLastForegroundTimeForMetricsForTesting(); 659 660 // Reports whether the interval [`now - range`, `now`] overlaps with a period 661 // where this process was running at Process::Priority::kBestEffort. Defaults to 662 // false if `last_foreground_time_ref` was never set (e.g. in processes not 663 // affected by priorities) but otherwise defaults to true if there's ambiguity 664 // (might have overlapped a best-effort range; as the reported timing might have 665 // been affected and shouldn't be reported as "definitely measured in 666 // foreground"). 667 // This method is atomic and suitable for performance critical histogram 668 // samples. 669 BASE_EXPORT bool OverlapsBestEffortRange(TimeTicks now, TimeDelta range); 670 671 } // namespace internal 672 673 } // namespace base 674 675 #endif // BASE_METRICS_HISTOGRAM_H_ 676