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
33class SamplingStatsdClient extends StatsdClient {
34 protected $samplingRates = [];
35
43 public function setSamplingRates( array $samplingRates ) {
44 $this->samplingRates = $samplingRates;
45 }
46
53 public function appendSampleRate( $data, $sampleRate = 1 ) {
54 $samplingRates = $this->samplingRates;
55 if ( !$samplingRates && $sampleRate !== 1 ) {
56 $samplingRates = [ '*' => $sampleRate ];
57 }
58 if ( $samplingRates ) {
59 array_walk( $data, static function ( $item ) use ( $samplingRates ) {
61 foreach ( $samplingRates as $pattern => $rate ) {
62 if ( fnmatch( $pattern, $item->getKey(), FNM_NOESCAPE ) ) {
63 $item->setSampleRate( $item->getSampleRate() * $rate );
64 break;
65 }
66 }
67 } );
68 }
69
70 return $data;
71 }
72
83 public function send( $data, $sampleRate = 1 ) {
84 if ( !is_array( $data ) ) {
85 $data = [ $data ];
86 }
87 if ( !$data ) {
88 return 0;
89 }
90 foreach ( $data as $item ) {
91 if ( !( $item instanceof StatsdDataInterface ) ) {
92 throw new InvalidArgumentException(
93 'SamplingStatsdClient does not accept stringified messages' );
94 }
95 }
96
97 // add sampling
98 $data = $this->appendSampleRate( $data, $sampleRate );
99 $data = $this->sampleData( $data );
100
101 $data = array_map( 'strval', $data );
102
103 // reduce number of packets
104 if ( $this->getReducePacket() ) {
105 $data = $this->reduceCount( $data );
106 }
107
108 // failures in any of this should be silently ignored if ..
109 $written = 0;
110 try {
111 $fp = $this->getSender()->open();
112 if ( !$fp ) {
113 return 0;
114 }
115 foreach ( $data as $message ) {
116 $written += $this->getSender()->write( $fp, $message );
117 }
118 $this->getSender()->close( $fp );
119 } catch ( TimeoutException $e ) {
120 throw $e;
121 } catch ( Exception $e ) {
122 $this->throwException( $e );
123 }
124
125 return $written;
126 }
127
134 protected function sampleData( $data ) {
135 $newData = [];
136 $mt_rand_max = mt_getrandmax();
137 foreach ( $data as $item ) {
138 $samplingRate = $item->getSampleRate();
139 if ( $samplingRate <= 0.0 || $samplingRate > 1.0 ) {
140 throw new LogicException( 'Sampling rate shall be within ]0, 1]' );
141 }
142 if (
143 $samplingRate === 1 ||
144 ( mt_rand() / $mt_rand_max <= $samplingRate )
145 ) {
146 $newData[] = $item;
147 }
148 }
149 return $newData;
150 }
151
158 private function throwException( Exception $exception ) {
159 if ( !$this->getFailSilently() ) {
160 throw $exception;
161 }
162 }
163}
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.