MediaWiki master
SamplingStatsdClient.php
Go to the documentation of this file.
1<?php
23use Liuggio\StatsdClient\Entity\StatsdData;
24use Liuggio\StatsdClient\Entity\StatsdDataInterface;
25use Liuggio\StatsdClient\StatsdClient;
26use Wikimedia\RequestTimeout\TimeoutException;
27
34class SamplingStatsdClient extends StatsdClient {
35 protected $samplingRates = [];
36
44 public function setSamplingRates( array $samplingRates ) {
45 $this->samplingRates = $samplingRates;
46 }
47
54 public function appendSampleRate( $data, $sampleRate = 1 ) {
56 if ( !$samplingRates && $sampleRate !== 1 ) {
57 $samplingRates = [ '*' => $sampleRate ];
58 }
59 if ( $samplingRates ) {
60 array_walk( $data, static function ( $item ) use ( $samplingRates ) {
62 foreach ( $samplingRates as $pattern => $rate ) {
63 if ( fnmatch( $pattern, $item->getKey(), FNM_NOESCAPE ) ) {
64 $item->setSampleRate( $item->getSampleRate() * $rate );
65 break;
66 }
67 }
68 } );
69 }
70
71 return $data;
72 }
73
84 public function send( $data, $sampleRate = 1 ) {
85 if ( !is_array( $data ) ) {
86 $data = [ $data ];
87 }
88 if ( !$data ) {
89 return 0;
90 }
91 foreach ( $data as $item ) {
92 if ( !( $item instanceof StatsdDataInterface ) ) {
93 throw new InvalidArgumentException(
94 'SamplingStatsdClient does not accept stringified messages' );
95 }
96 }
97
98 // add sampling
99 $data = $this->appendSampleRate( $data, $sampleRate );
100 $data = $this->sampleData( $data );
101
102 $data = array_map( 'strval', $data );
103
104 // reduce number of packets
105 if ( $this->getReducePacket() ) {
106 $data = $this->reduceCount( $data );
107 }
108
109 // failures in any of this should be silently ignored if ..
110 $written = 0;
111 try {
112 $fp = $this->getSender()->open();
113 if ( !$fp ) {
114 return 0;
115 }
116 foreach ( $data as $message ) {
117 $written += $this->getSender()->write( $fp, $message );
118 }
119 $this->getSender()->close( $fp );
120 } catch ( TimeoutException $e ) {
121 throw $e;
122 } catch ( Exception $e ) {
123 $this->throwException( $e );
124 }
125
126 return $written;
127 }
128
135 protected function sampleData( $data ) {
136 $newData = [];
137 $mt_rand_max = mt_getrandmax();
138 foreach ( $data as $item ) {
139 $samplingRate = $item->getSampleRate();
140 if ( $samplingRate <= 0.0 || $samplingRate > 1.0 ) {
141 throw new LogicException( 'Sampling rate shall be within ]0, 1]' );
142 }
143 if (
144 $samplingRate === 1 ||
145 ( mt_rand() / $mt_rand_max <= $samplingRate )
146 ) {
147 $newData[] = $item;
148 }
149 }
150 return $newData;
151 }
152
159 private function throwException( Exception $exception ) {
160 if ( !$this->getFailSilently() ) {
161 throw $exception;
162 }
163 }
164}
A statsd client that applies the sampling rate to the data items before sending them.
setSamplingRates(array $samplingRates)
Sampling rates as an associative array of patterns and rates.
send( $data, $sampleRate=1)
Send the metrics over UDP Sample the metrics according to their sample rate and send the remaining on...
sampleData( $data)
Throw away some of the data according to the sample rate.
appendSampleRate( $data, $sampleRate=1)
Sets sampling rate for all items in $data.