MediaWiki REL1_39
MetricUtils.php
Go to the documentation of this file.
1<?php
30declare( strict_types=1 );
31
32namespace Wikimedia\Metrics;
33
36
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}
if(!defined('MW_SETUP_CALLBACK'))
The persistent session ID (if any) loaded at startup.
Definition WebStart.php:82
setTypeIndicator(string $typeIndicator)
Sets the StatsD protocol type indicator.
addSample(Sample $sample)
Adds a sample to cache.