samplingRates = $samplingRates; } /** * Sets sampling rate for all items in $data. * The sample rate specified in a StatsdData entity overrides the sample rate specified here. * * {@inheritDoc} */ public function appendSampleRate( $data, $sampleRate = 1 ) { $samplingRates = $this->samplingRates; if ( !$samplingRates && $sampleRate !== 1 ) { $samplingRates = [ '*' => $sampleRate ]; } if ( $samplingRates ) { array_walk( $data, function( $item ) use ( $samplingRates ) { /** @var $item StatsdData */ foreach ( $samplingRates as $pattern => $rate ) { if ( fnmatch( $pattern, $item->getKey(), FNM_NOESCAPE ) ) { $item->setSampleRate( $item->getSampleRate() * $rate ); break; } } } ); } return $data; } /* * Send the metrics over UDP * Sample the metrics according to their sample rate and send the remaining ones. * * @param StatsdDataInterface|StatsdDataInterface[] $data message(s) to sent * strings are not allowed here as sampleData requires a StatsdDataInterface * @param int $sampleRate * * @return integer the data sent in bytes */ public function send( $data, $sampleRate = 1 ) { if ( !is_array( $data ) ) { $data = [ $data ]; } if ( !$data ) { return; } foreach ( $data as $item ) { if ( !( $item instanceof StatsdDataInterface ) ) { throw new InvalidArgumentException( 'SamplingStatsdClient does not accept stringified messages' ); } } // add sampling $data = $this->appendSampleRate( $data, $sampleRate ); $data = $this->sampleData( $data ); $data = array_map( 'strval', $data ); // reduce number of packets if ( $this->getReducePacket() ) { $data = $this->reduceCount( $data ); } // failures in any of this should be silently ignored if .. $written = 0; try { $fp = $this->getSender()->open(); if ( !$fp ) { return; } foreach ( $data as $message ) { $written += $this->getSender()->write( $fp, $message ); } $this->getSender()->close( $fp ); } catch ( Exception $e ) { $this->throwException( $e ); } return $written; } /** * Throw away some of the data according to the sample rate. * @param StatsdDataInterface[] $data * @return StatsdDataInterface[] * @throws LogicException */ protected function sampleData( $data ) { $newData = []; $mt_rand_max = mt_getrandmax(); foreach ( $data as $item ) { $samplingRate = $item->getSampleRate(); if ( $samplingRate <= 0.0 || $samplingRate > 1.0 ) { throw new LogicException( 'Sampling rate shall be within ]0, 1]' ); } if ( $samplingRate === 1 || ( mt_rand() / $mt_rand_max <= $samplingRate ) ) { $newData[] = $item; } } return $newData; } /** * {@inheritDoc} */ protected function throwException( Exception $exception ) { if ( !$this->getFailSilently() ) { throw $exception; } } }