MediaWiki 1.44.0
HistogramMetric.php
Go to the documentation of this file.
1<?php
20declare( strict_types=1 );
21
23
24use InvalidArgumentException;
26
36
38 private const MAX_BUCKETS = 10;
39
40 private StatsFactory $statsFactory;
41 private string $name;
42 private array $buckets;
43 private array $labels = [];
44
45 public function __construct( StatsFactory $statsFactory, string $name, array $buckets ) {
46 $this->statsFactory = $statsFactory;
47 $this->name = $name;
48 if ( !$buckets ) {
49 throw new InvalidArgumentException( 'Stats: Histogram buckets cannot be an empty array.' );
50 }
51 $bucketCount = count( $buckets );
52 if ( $bucketCount > self::MAX_BUCKETS ) {
53 throw new InvalidArgumentException(
54 "Stats: Too many buckets defined. Got:{$bucketCount}, Max:" . self::MAX_BUCKETS
55 );
56 }
57 foreach ( $buckets as $bucket ) {
58 if ( !( is_float( $bucket ) || is_int( $bucket ) ) ) {
59 throw new InvalidArgumentException( 'Stats: Histogram buckets can only be float or int.' );
60 }
61 }
62 $normalizedBuckets = array_unique( $buckets );
63 sort( $normalizedBuckets, SORT_NUMERIC );
64 if ( $buckets !== $normalizedBuckets ) {
65 throw new InvalidArgumentException(
66 'Stats: Histogram buckets must be unique and in order of least to greatest.'
67 );
68 }
69 $this->buckets = $buckets;
70 }
71
76 private function preloadBuckets( CounterMetric $metric ): void {
77 $metric->setBucket( '+Inf' );
78 $metric->incrementBy( 0 );
79 foreach ( $this->buckets as $bucket ) {
80 $metric->setBucket( $bucket );
81 $metric->incrementBy( 0 );
82 }
83 }
84
88 public function observe( float $value ): void {
89 $count = $this->statsFactory->getCounter( "{$this->name}_count" );
90 $bucket = $this->statsFactory->getCounter( "{$this->name}_bucket" );
91 $sum = $this->statsFactory->getCounter( "{$this->name}_sum" );
92
93 foreach ( $this->labels as $k => $v ) {
94 $count->setLabel( $k, $v );
95 $bucket->setLabel( $k, $v );
96 $sum->setLabel( $k, $v );
97 }
98
99 if ( $bucket->getSampleCount() === 0 ) {
100 $this->preloadBuckets( $bucket );
101 }
102
103 $bucket->setBucket( '+Inf' )->increment();
104 foreach ( $this->buckets as $le ) {
105 if ( $value <= $le ) {
106 $bucket->setBucket( $le )->increment();
107 }
108 }
109
110 $count->increment();
111 $sum->incrementBy( $value );
112 }
113
119 public function setLabel( string $key, string $value ): self {
120 // each metric will run its own validation logic
121 $this->labels[$key] = $value;
122 return $this;
123 }
124
130 public function fresh(): self {
131 $this->labels = [];
132 return $this;
133 }
134}
Counter Metric Implementation.
incrementBy(float $value)
Increments metric by provided value.
setBucket( $value)
Sets the bucket value.
Histogram Metric Implementation.
observe(float $value)
Increments bucket associated with the provided value.
setLabel(string $key, string $value)
Adds a label $key with $value.
fresh()
Returns metric with cleared labels.
__construct(StatsFactory $statsFactory, string $name, array $buckets)
This is the primary interface for validating metrics definitions, caching defined metrics,...