MediaWiki  master
MetricUtils.php
Go to the documentation of this file.
1 <?php
30 declare( strict_types=1 );
31 
32 namespace Wikimedia\Metrics;
33 
36 
37 class MetricUtils {
38 
40  private const RE_VALID_NAME_AND_LABEL_NAME = '/^[a-zA-Z_][a-zA-Z0-9_]*$/';
41 
43  protected $prefix;
44 
46  protected $extension;
47 
49  protected $format;
50 
52  protected $name;
53 
55  protected $sampleRate;
56 
58  protected $labels;
59 
61  protected $samples = [];
62 
64  protected $typeIndicator;
65 
75  public function validateConfig( $config ) {
76  $this->prefix = $config['prefix'];
77  $this->extension = $config['extension'];
78  $this->name = $config['name'];
79  $this->sampleRate = $config['sampleRate'];
80  $this->format = $config['format'];
81  if ( !preg_match( self::RE_VALID_NAME_AND_LABEL_NAME, $this->name ) ) {
82  throw new InvalidConfigurationException( "Invalid metric name: '" . $this->name . "'" );
83  }
84  $this->labels = $config['labels'];
85  foreach ( $this->labels as $label ) {
86  if ( !preg_match( self::RE_VALID_NAME_AND_LABEL_NAME, $label ) ) {
87  throw new InvalidConfigurationException( "Invalid label name: '" . $label . "'" );
88  }
89  }
90  }
91 
96  public function setTypeIndicator( string $typeIndicator ) {
97  $this->typeIndicator = $typeIndicator;
98  }
99 
104  public function addSample( Sample $sample ) {
105  $this->samples[] = $sample;
106  }
107 
111  public function render(): array {
112  $output = [];
113  switch ( $this->format ) {
114  case 'dogstatsd':
115  foreach ( $this->getFilteredSamples() as $sample ) {
116  $output[] = $this->renderDogStatsD( $sample );
117  }
118  break;
119  case 'statsd':
120  foreach ( $this->getFilteredSamples() as $sample ) {
121  $output[] = $this->renderStatsD( $sample );
122  }
123  break;
124  default: // "null"
125  break;
126  }
127  return $output;
128  }
129 
134  public function validateLabels( array $labels ): void {
135  if ( count( $this->labels ) !== count( $labels ) ) {
136  throw new InvalidLabelsException(
137  'Not enough or too many labels provided to metric instance.'
138  . 'Configured: ' . json_encode( $this->labels ) . ' Provided: ' . json_encode( $labels )
139  );
140  }
141  }
142 
147  private function getFilteredSamples() {
148  if ( $this->sampleRate === 1.0 ) {
149  return $this->samples;
150  }
151  $output = [];
152  $randMax = mt_getrandmax();
153  foreach ( $this->samples as $sample ) {
154  if ( mt_rand() / $randMax < $this->sampleRate ) {
155  $output[] = $sample;
156  }
157  }
158  return $output;
159  }
160 
166  private function renderStatsD( Sample $sample ): string {
167  $stat = implode( '.',
168  array_merge( [ $this->prefix, $this->extension, $this->name ], $sample->getLabels() )
169  );
170  $value = ':' . $sample->getValue();
171  $type = '|' . $this->typeIndicator;
172  $sampleRate = $this->sampleRate !== 1.0 ? '|@' . $this->sampleRate : '';
173 
174  return $stat . $value . $type . $sampleRate;
175  }
176 
184  private function renderDogStatsD( Sample $sample ): string {
185  $stat = implode( '.', [ $this->prefix, $this->extension, $this->name ] );
186  $sampleLabels = $sample->getLabels();
187  $labels = [];
188  foreach ( $this->labels as $i => $label ) {
189  $labels[] = $label . ':' . $sampleLabels[$i];
190  }
191  $value = ':' . $sample->getValue();
192  $type = '|' . $this->typeIndicator;
193  $sampleRate = $this->sampleRate !== 1.0 ? '|@' . $this->sampleRate : '';
194  $tags = $labels === [] ? '' : '|#' . implode( ',', $labels );
195  return $stat . $value . $type . $sampleRate . $tags;
196  }
197 
198 }
Wikimedia\Metrics\MetricUtils\$labels
string[] $labels
Definition: MetricUtils.php:58
Wikimedia\Metrics\MetricUtils\addSample
addSample(Sample $sample)
Adds a sample to cache.
Definition: MetricUtils.php:104
Wikimedia\Metrics\MetricUtils\getFilteredSamples
getFilteredSamples()
Get set of samples filtered according to configured sampleRate.
Definition: MetricUtils.php:147
Wikimedia\Metrics\MetricUtils\$extension
string $extension
Definition: MetricUtils.php:46
Wikimedia\Metrics\MetricUtils\$typeIndicator
string $typeIndicator
Definition: MetricUtils.php:64
Wikimedia\Metrics\MetricUtils\$format
string $format
Definition: MetricUtils.php:49
Wikimedia\Metrics\MetricUtils\validateLabels
validateLabels(array $labels)
Definition: MetricUtils.php:134
Wikimedia\Metrics\MetricUtils\renderDogStatsD
renderDogStatsD(Sample $sample)
Renders metrics in DogStatsD format https://docs.datadoghq.com/developers/dogstatsd/datagram_shell/?...
Definition: MetricUtils.php:184
Wikimedia\Metrics\MetricUtils\$samples
Sample[] $samples
Definition: MetricUtils.php:61
Wikimedia\Metrics\Exceptions\InvalidConfigurationException
Definition: InvalidConfigurationException.php:32
Wikimedia\Metrics\Exceptions\InvalidLabelsException
Definition: InvalidLabelsException.php:32
Wikimedia\Metrics\MetricUtils
Definition: MetricUtils.php:37
Wikimedia\Metrics\Sample
Definition: Sample.php:31
Wikimedia\Metrics\MetricUtils\renderStatsD
renderStatsD(Sample $sample)
Renders metrics in StatsD format.
Definition: MetricUtils.php:166
Wikimedia\Metrics\Sample\getLabels
getLabels()
Definition: Sample.php:49
Wikimedia\Metrics\MetricUtils\$sampleRate
float $sampleRate
Definition: MetricUtils.php:55
Wikimedia\Metrics\Sample\getValue
getValue()
Definition: Sample.php:54
Wikimedia\Metrics\MetricUtils\validateConfig
validateConfig( $config)
Definition: MetricUtils.php:75
Wikimedia\Metrics\MetricUtils\$prefix
string $prefix
Definition: MetricUtils.php:39
Wikimedia\Metrics
Definition: CounterMetric.php:29
Wikimedia\Metrics\MetricUtils\setTypeIndicator
setTypeIndicator(string $typeIndicator)
Sets the StatsD protocol type indicator.
Definition: MetricUtils.php:96
Wikimedia\Metrics\MetricUtils\$name
string $name
Definition: MetricUtils.php:52
Wikimedia\Metrics\MetricUtils\render
render()
Definition: MetricUtils.php:111
$type
$type
Definition: testCompression.php:52