MediaWiki master
StatsUtils.php
Go to the documentation of this file.
1<?php
7declare( strict_types=1 );
8
9namespace Wikimedia\Stats;
10
11use InvalidArgumentException;
13
21
22 public const RE_VALID_NAME_AND_LABEL_NAME = "/^[a-zA-Z_][a-zA-Z0-9_]*$/";
23 public const DEFAULT_SAMPLE_RATE = 1.0;
24
31 public static function validateNewSampleRate( float $newSampleRate ): void {
32 if ( $newSampleRate < 0.0 || $newSampleRate > 1.0 ) {
33 throw new InvalidArgumentException( "Sample rate can only be between 0.0 and 1.0. Got: " . $newSampleRate );
34 }
35 }
36
44 public static function getFilteredSamples( float $sampleRate, array $samples ): array {
45 if ( $sampleRate === 1.0 ) {
46 return $samples;
47 }
48 $output = [];
49 $randMax = mt_getrandmax();
50 foreach ( $samples as $sample ) {
51 if ( mt_rand() / $randMax < $sampleRate ) {
52 $output[] = $sample;
53 }
54 }
55 return $output;
56 }
57
66 public static function validateMetricName( string $name ) {
67 if ( $name === "" ) {
68 throw new InvalidArgumentException( "Stats: Metric name cannot be empty." );
69 }
70 if ( !preg_match( self::RE_VALID_NAME_AND_LABEL_NAME, $name ) ) {
71 throw new InvalidConfigurationException( "Invalid metric name: '" . $name . "'" );
72 }
73 }
74
83 public static function validateLabelKey( string $key ) {
84 if ( $key === "" ) {
85 throw new InvalidArgumentException( "Stats: Label key cannot be empty." );
86 }
87 if ( !preg_match( self::RE_VALID_NAME_AND_LABEL_NAME, $key ) ) {
88 throw new InvalidConfigurationException( "Invalid label key: '" . $key . "'" );
89 }
90 }
91
92 public static function validateLabelValue( string $value ) {
93 if ( $value === "" ) {
94 throw new InvalidArgumentException( "Stats: Label value cannot be empty." );
95 }
96 }
97
104 public static function normalizeArray( array $entities ): array {
105 $normalizedEntities = [];
106 foreach ( $entities as $entity ) {
107 $normalizedEntities[] = self::normalizeString( $entity );
108 }
109 return $normalizedEntities;
110 }
111
125 public static function normalizeString( string $entity ): string {
126 $entity = preg_replace( '/[^a-zA-Z0-9]+/', '_', $entity );
127 return trim( $entity, '_' );
128 }
129
134 private const E12 = [
135 1.0, 1.2, 1.5, 1.8, 2.2, 2.7, 3.3, 3.9, 4.7, 5.6, 6.8, 8.2, 10.0
136 ];
137
176 public static function makeBucketsFromMean( float $mean, int $skip ): array {
177 // assert $mean > 0 and $skip > 0
178 if ( $mean <= 0 ) {
179 throw new InvalidArgumentException( 'mean must be positive' );
180 }
181 if ( $skip < 1 ) {
182 throw new InvalidArgumentException( 'skip must be at least 1' );
183 }
184 // Find the appropriate starting location in the E12 series.
185 $pos = (int)round( log10( $mean ) * 12 );
186 // Further quantize $pos according to $skip, so changes in $mean
187 // don't shift all the buckets
188 $pos -= ( $pos % $skip );
189 // Compute buckets around the quantized starting position
190 // By using the E12 series and powers of ten our cutoffs will
191 // be compact (not too many digits) and consistent.
192 return array_map( static function ( int $x ) use ( $pos, $skip ) {
193 $y = $pos + ( $x * $skip );
194 $rem = $y % 12;
195 if ( $rem < 0 ) {
196 $rem += 12;
197 }
198 $decade = intdiv( $y - $rem, 12 ); // floor($y/12)
199 // Use an explicit round() here to ensure float math doesn't create
200 // extra tiny variances.
201 return round( ( 10 ** $decade ) * self::E12[$rem], 1 - $decade );
202 }, [
203 // 9 buckets, centered around the (quantized) mean
204 -4, -3, -2, -1, 0, 1, 2, 3, 4
205 ] );
206 }
207}
if(!defined('MW_SETUP_CALLBACK'))
Definition WebStart.php:69
Functionality common to all metric types.
static normalizeString(string $entity)
Normalize strings to a metrics-compatible format.
static normalizeArray(array $entities)
Normalize an array of strings.
static validateMetricName(string $name)
Determines if provided string is a valid name.
static getFilteredSamples(float $sampleRate, array $samples)
Returns a subset of samples based on configured sample rate.
static validateLabelKey(string $key)
Determines if provided string is a valid label key.
static validateLabelValue(string $value)
static makeBucketsFromMean(float $mean, int $skip)
Make a set of HistogramMetric buckets from a mean and skip value.
static validateNewSampleRate(float $newSampleRate)
Validates the new sample rate.