diff --git a/Readme.md b/Readme.md index e709aa4..b214323 100644 --- a/Readme.md +++ b/Readme.md @@ -1,15 +1,14 @@ -## statsd-php-client +## statsd-php-client v1.0.6 +Be careful, see the [Upgrading section](Readme.md#upgrade) for <= v1.0.4, there's a BC. [![Build Status](https://secure.travis-ci.org/liuggio/statsd-php-client.png)](http://travis-ci.org/liuggio/statsd-php-client) - - `statsd-php-client` is an Open Source, and **Object Oriented** Client for **etsy/statsd** written in php - `StatsdDataFactory` creates the `Liuggio\StatsdClient\Entity\StatsdDataInterface` Objects -- `Sender` just sends data over the network +- `Sender` just sends data over the network (there are many sender) - `StatsdClient` sends the created objects via the `Sender` to the server @@ -17,7 +16,7 @@ - You are wise. -- This library is totally tested. +- This library is tested. - This library optimizes the messages to send, compressing multiple messages in individual UDP packets. @@ -25,16 +24,32 @@ - This library is made by Objects not array, but it also accepts array. +- You do want to debug the packets, and using `SysLogSender` the packets will be logged in your `syslog` log (on debian-like distro: `tail -f /var/log/syslog`) ## Example +1. create the Sender + +2. create the Client + +3. create the Factory + +4. the Factory will help you to create data + +5. the Client will send the data + ```php -$sender = new SocketSender(); +use Liuggio\StatsdClient\StatsdClient, + Liuggio\StatsdClient\StatsdClient\Factory\StatsdDataFactory, + Liuggio\StatsdClient\StatsdClient\Sender\SocketSender, + Liuggio\StatsdClient\StatsdClient\Sender\SysLogSender; + +$sender = new SocketSender('udp://localhost', 8126); +// $sender = new SysLogSender(); // enable this the packet will not send over the socket -// StatsdClient(SenderInterface $sender, $host = 'udp://localhost', $port = 8126, $reducePacket = true, $fail_silently = true) $client = new StatsdClient($sender); -$factory = new StatsdDataFactory('\\Liuggio\\StatsdClient\\Entity\\StatsdData'); +$factory = new StatsdDataFactory('\Liuggio\StatsdClient\Entity\StatsdData'); // create the data with the factory $data[] = $factory->timing('usageTime', 100); @@ -55,7 +70,6 @@ In order to try this application monitor you have to install etsy/statsd and Gra see this blog post to install it with vagrant [Easy install statsd graphite](http://welcometothebundle.com/easily-install-statsd-and-graphite-with-vagrant/). - #### [StatsD](https://github.com/etsy/statsd) StatsD is a simple daemon for easy stats aggregation @@ -93,3 +107,7 @@ composer.phar install ``` bash phpunit --coverage-html reports ``` + +## Upgrade + +BC from the v1.0.4 version, [see Sender and Client differences](https://github.com/liuggio/statsd-php-client/pull/5/files). diff --git a/src/Liuggio/StatsdClient/Entity/StatsdData.php b/src/Liuggio/StatsdClient/Entity/StatsdData.php index c865b44..35f6f9e 100755 --- a/src/Liuggio/StatsdClient/Entity/StatsdData.php +++ b/src/Liuggio/StatsdClient/Entity/StatsdData.php @@ -4,7 +4,6 @@ use Liuggio\StatsdClient\Entity\StatsdDataInterface; - class StatsdData implements StatsdDataInterface { @@ -56,6 +55,7 @@ public function getMetric() } /** + * @param bool $withMetric * @return string */ public function getMessage($withMetric = true) @@ -74,5 +74,4 @@ public function __toString() { return $this->getMessage(); } - } diff --git a/src/Liuggio/StatsdClient/Factory/StatsdDataFactory.php b/src/Liuggio/StatsdClient/Factory/StatsdDataFactory.php index fc50511..d8193e3 100644 --- a/src/Liuggio/StatsdClient/Factory/StatsdDataFactory.php +++ b/src/Liuggio/StatsdClient/Factory/StatsdDataFactory.php @@ -4,7 +4,6 @@ use Liuggio\StatsdClient\Entity\StatsdDataInterface; - class StatsdDataFactory implements StatsdDataFactoryInterface { /** @@ -86,7 +85,8 @@ public function produceStatsdData($key, $value = 1, $metric = StatsdDataInterfac /** * {@inheritDoc} **/ - public function produceStatsdDataEntity() { + public function produceStatsdDataEntity() + { $statsdData = $this->getEntityClass(); return new $statsdData(); } diff --git a/src/Liuggio/StatsdClient/Factory/StatsdDataFactoryInterface.php b/src/Liuggio/StatsdClient/Factory/StatsdDataFactoryInterface.php index 1161bd2..87d9554 100644 --- a/src/Liuggio/StatsdClient/Factory/StatsdDataFactoryInterface.php +++ b/src/Liuggio/StatsdClient/Factory/StatsdDataFactoryInterface.php @@ -4,7 +4,6 @@ use Liuggio\StatsdClient\Entity\StatsdDataInterface; - Interface StatsdDataFactoryInterface { @@ -12,7 +11,7 @@ * This function creates a 'timing' StatsdData * * @abstract - * @param string|array $stats The metric(s) to set. + * @param string|array $key The metric(s) to set. * @param float $time The elapsed time (ms) to log **/ function timing($key, $time); @@ -21,7 +20,7 @@ function timing($key, $time); * This function creates a 'gauge' StatsdData * * @abstract - * @param string|array $stats The metric(s) to set. + * @param string|array $key The metric(s) to set. * @param float $value The value for the stats. **/ function gauge($key, $value); @@ -30,7 +29,7 @@ function gauge($key, $value); * This function creates a 'set' StatsdData object * A "Set" is a count of unique events. * This data type acts like a counter, but supports counting - * of unique occurences of values between flushes. The backend + * of unique occurrences of values between flushes. The backend * receives the number of unique events that happened since * the last flush. * @@ -39,7 +38,7 @@ function gauge($key, $value); * with each request with a key of "uniques" (or similar). * * @abstract - * @param string|array $stats The metric(s) to set. + * @param string|array $key The metric(s) to set. * @param float $value The value for the stats. * @return array **/ @@ -70,12 +69,9 @@ function decrement($key); * * @abstract * @param string $key The key of the metric - * @param int|1 $value The amount to increment/decrement each metric by. - * @param string|c $metric The metric type ("c" for count, "ms" for timing, "g" for gauge, "s" for set) + * @param int $value The amount to increment/decrement each metric by. + * @param string $metric The metric type ("c" for count, "ms" for timing, "g" for gauge, "s" for set) * @return StatsdDataInterface **/ function produceStatsdData($key, $value = 1, $metric = StatsdDataInterface::STATSD_METRIC_COUNT); - - - } diff --git a/src/Liuggio/StatsdClient/Sender/EchoSender.php b/src/Liuggio/StatsdClient/Sender/EchoSender.php index 1dc227b..d2dcd24 100644 --- a/src/Liuggio/StatsdClient/Sender/EchoSender.php +++ b/src/Liuggio/StatsdClient/Sender/EchoSender.php @@ -8,7 +8,8 @@ /** * {@inheritDoc} */ - public function open($hostname, $port = null, $protocol = null) { + public function open() + { echo "[open]"; return true; } @@ -16,7 +17,8 @@ public function open($hostname, $port = null, $protocol = null) { /** * {@inheritDoc} */ - function write($handle, $message, $length = null){ + function write($handle, $message, $length = null) + { echo "[$message]"; return strlen($message); } @@ -24,7 +26,8 @@ function write($handle, $message, $length = null){ /** * {@inheritDoc} */ - function close($handle){ + function close($handle) + { echo "[closed]"; } } diff --git a/src/Liuggio/StatsdClient/Sender/SenderInterface.php b/src/Liuggio/StatsdClient/Sender/SenderInterface.php index 8090c7c..04e60ea 100644 --- a/src/Liuggio/StatsdClient/Sender/SenderInterface.php +++ b/src/Liuggio/StatsdClient/Sender/SenderInterface.php @@ -6,26 +6,25 @@ { /** * @abstract - * @param $hostname - * @param null $port - * @param null $protocol * @return mixed */ - function open($hostname, $port = null, $protocol = null); + function open(); /** * @abstract * @param $handle * @param $string * @param null $length + * * @return mixed */ - function write($handle, $string, $length = null); + function write($handle, $string, $length = null); /** * @abstract * @param $handle + * * @return mixed */ - function close($handle); + function close($handle); } diff --git a/src/Liuggio/StatsdClient/Sender/SocketSender.php b/src/Liuggio/StatsdClient/Sender/SocketSender.php index b3fb35f..e9c9ad2 100644 --- a/src/Liuggio/StatsdClient/Sender/SocketSender.php +++ b/src/Liuggio/StatsdClient/Sender/SocketSender.php @@ -7,42 +7,84 @@ Class SocketSender implements SenderInterface { private $port; + private $host; - /** - * {@inheritDoc} - */ - public function open($hostname, $port = null, $protocol = null) { + + private $protocol; + + public function __construct($hostname, $port = null, $protocol = 'udp') + { $this->host = $hostname; $this->port = $port; switch ($protocol) { case 'udp': - $protocolSOL = SOL_UDP; + $this->protocol = SOL_UDP; break; case 'tcp': - $protocolSOL = SOL_TCP; + $this->protocol = SOL_TCP; break; default: - throw new InvalidArgumentException('use udp or tcp as protocol'); + throw new InvalidArgumentException(sprintf('Use udp or tcp as protocol given %s', $protocol)); break; } - $fp = socket_create(AF_INET, SOCK_DGRAM, $protocolSOL); - return $fp; } /** * {@inheritDoc} */ - function write($handle, $message, $length = null){ + public function open() + { + $fp = socket_create(AF_INET, SOCK_DGRAM, $this->getProtocol()); - return socket_sendto($handle, $message, strlen($message), 0, $this->host, $this->port); + return $fp; } /** * {@inheritDoc} */ - function close($handle){ + public function write($handle, $message, $length = null) + { + return socket_sendto($handle, $message, strlen($message), 0, $this->getHost(), $this->getPort()); + } + + /** + * {@inheritDoc} + */ + public function close($handle) + { socket_close($handle); } + + + protected function setHost($host) + { + $this->host = $host; + } + + protected function getHost() + { + return $this->host; + } + + protected function setPort($port) + { + $this->port = $port; + } + + protected function getPort() + { + return $this->port; + } + + protected function setProtocol($protocol) + { + $this->protocol = $protocol; + } + + protected function getProtocol() + { + return $this->protocol; + } } diff --git a/src/Liuggio/StatsdClient/Sender/SysLogSender.php b/src/Liuggio/StatsdClient/Sender/SysLogSender.php new file mode 100644 index 0000000..d80138f --- /dev/null +++ b/src/Liuggio/StatsdClient/Sender/SysLogSender.php @@ -0,0 +1,39 @@ +priority = $priority; + } + /** + * {@inheritDoc} + */ + public function open() + { + syslog($this->priority, "statsd-client-open"); + return true; + } + + /** + * {@inheritDoc} + */ + function write($handle, $message, $length = null) + { + syslog($this->priority, sprintf("statsd-client-write \"%s\" %d Bytes", $message, strlen($message))); + return strlen($message); + } + + /** + * {@inheritDoc} + */ + function close($handle) + { + syslog($this->priority, "statsd-client-close"); + } +} diff --git a/src/Liuggio/StatsdClient/StatsdClient.php b/src/Liuggio/StatsdClient/StatsdClient.php index 75e81d5..281b854 100644 --- a/src/Liuggio/StatsdClient/StatsdClient.php +++ b/src/Liuggio/StatsdClient/StatsdClient.php @@ -8,18 +8,6 @@ class StatsdClient implements StatsdClientInterface { - /** - * @var string - */ - private $host; - /** - * @var int - */ - private $port; - /** - * @var string - */ - private $protocol; /** * @var boolean */ @@ -36,28 +24,28 @@ class StatsdClient implements StatsdClientInterface private $reducePacket; /** + * Constructor. * * @param \Liuggio\StatsdClient\Sender\SenderInterface $sender - * @param $host - * @param $port - * @param bool $fail_silently + * @param Boolean $reducePacket + * @param Boolean $fail_silently */ - public function __construct(SenderInterface $sender, $host = 'localhost', $port = 8126, $protocol = 'udp', $reducePacket = true, $fail_silently = true) + public function __construct(SenderInterface $sender, $reducePacket = true, $fail_silently = true) { - $this->host = $host; - $this->port = $port; - $this->protocol = $protocol; $this->sender = $sender; $this->reducePacket = $reducePacket; $this->failSilently = $fail_silently; } /** - * Throws an exc only if failSilently if getFailSilently is false + * Throws an exc only if failSilently if getFailSilently is false. + * * @param \Exception $exception + * * @throws \Exception */ - private function throwException(\Exception $exception) { + private function throwException(\Exception $exception) + { if (!$this->getFailSilently()) { throw $exception; } @@ -69,8 +57,9 @@ private function throwException(\Exception $exception) { * https://github.com/etsy/statsd/blob/master/README.md * All metrics can also be batch send in a single UDP packet, separated by a newline character. * - * @param $result - * @param $item + * @param array $result + * @param array $item + * * @return array */ function doReduce($result, $item) @@ -86,9 +75,9 @@ function doReduce($result, $item) array_push($result, $oldLastItem); } else { //going to modifying the existing - $separator= ''; + $separator = ''; if ($sizeResult > 0) { - $separator= PHP_EOL; + $separator = PHP_EOL; } $oldLastItem = sprintf("%s%s%s", $oldLastItem, $separator, $message); array_push($result, $oldLastItem); @@ -129,6 +118,7 @@ public function appendSampleRate($data, $sampleRate = 1) } return $data; } + /* * Send the metrics over UDP * @@ -153,17 +143,20 @@ public function send($data, $sampleRate = 1) } //failures in any of this should be silently ignored if .. try { - $fp = $this->getSender()->open($this->getHost(), $this->getPort(), $this->getProtocol()); + $fp = $this->getSender()->open(); if (!$fp) { return; } + $written = 0; foreach ($data as $key => $message) { - $written = $this->getSender()->write($fp, $message); + $written += $this->getSender()->write($fp, $message); } $this->getSender()->close($fp); } catch (\Exception $e) { $this->throwException($e); } + + return $written; } /** @@ -182,39 +175,6 @@ public function getFailSilently() return $this->failSilently; } - /** - * @param string $host - */ - public function setHost($host) - { - $this->host = $host; - } - - /** - * @return string - */ - public function getHost() - { - return $this->host; - } - - /** - * @param int $port - */ - public function setPort($port) - { - $this->port = $port; - } - - /** - * @return int - */ - public function getPort() - { - return $this->port; - } - - /** * @param \Liuggio\StatsdClient\Sender\SenderInterface $sender */ @@ -247,21 +207,4 @@ public function getReducePacket() return $this->reducePacket; } - /** - * @param string $protocol - */ - public function setProtocol($protocol) - { - $this->protocol = $protocol; - } - - /** - * @return string - */ - public function getProtocol() - { - return $this->protocol; - } - - } diff --git a/src/Liuggio/StatsdClient/StatsdClientInterface.php b/src/Liuggio/StatsdClient/StatsdClientInterface.php index f91ba99..85e65d6 100644 --- a/src/Liuggio/StatsdClient/StatsdClientInterface.php +++ b/src/Liuggio/StatsdClient/StatsdClientInterface.php @@ -8,7 +8,6 @@ Interface StatsdClientInterface { - const MAX_UDP_SIZE_STR = 548; /* @@ -17,7 +16,8 @@ * @abstract * @param array|string|StatsdDataInterface $data message(s) to sent * @param int $sampleRate Tells StatsD that this counter is being sent sampled every Xth of the time. + * + * @return integer the data sent in bytes */ function send($data, $sampleRate = 1); - } diff --git a/tests/Liuggio/StatsdClient/ReadmeTest.php b/tests/Liuggio/StatsdClient/ReadmeTest.php index 7b99d7c..4608a60 100644 --- a/tests/Liuggio/StatsdClient/ReadmeTest.php +++ b/tests/Liuggio/StatsdClient/ReadmeTest.php @@ -16,7 +16,7 @@ public function testFullUsageWithObject() { // StatsdClient(SenderInterface $sender, $host = 'udp://localhost', $port = 8126, $reducePacket = true, $fail_silently = true) $client = new StatsdClient($sender); - $factory = new StatsdDataFactory('\\Liuggio\\StatsdClient\\Entity\\StatsdData'); + $factory = new StatsdDataFactory('\Liuggio\StatsdClient\Entity\StatsdData'); // create the data with the factory $data[] = $factory->timing('usageTime', 100); @@ -52,7 +52,7 @@ public function testFullUsageArray() { private function mockSender() { - $sender = $this->getMock('\\Liuggio\\StatsdClient\\Sender\\SenderInterface', array('open', 'write', 'close')); + $sender = $this->getMock('\Liuggio\StatsdClient\Sender\SenderInterface', array('open', 'write', 'close')); $sender->expects($this->once()) ->method('open') ->will($this->returnValue(true)); diff --git a/tests/Liuggio/StatsdClient/StatsdClientTest.php b/tests/Liuggio/StatsdClient/StatsdClientTest.php index c9101dc..235d9a9 100644 --- a/tests/Liuggio/StatsdClient/StatsdClientTest.php +++ b/tests/Liuggio/StatsdClient/StatsdClientTest.php @@ -10,7 +10,7 @@ class StatsdClientTest extends \PHPUnit_Framework_TestCase public function mockSenderWithAssertionOnWrite($messageToAssert) { - $mock = $this->getMock('\\Liuggio\\StatsdClient\\Sender\\SocketSender', array('open', 'write', 'close')); + $mock = $this->getMockBuilder('\Liuggio\StatsdClient\Sender\SocketSender') ->disableOriginalConstructor() ->getMock(); $phpUnit = $this; $mock->expects($this->any()) @@ -33,7 +33,6 @@ public function mockSenderWithAssertionOnWrite($messageToAssert) { ->method('write') ->will($this->returnCallBack(function($fp, $message) use ($phpUnit, $messageToAssert) { $phpUnit->assertEquals($message, $messageToAssert); - })); } return $mock; @@ -43,13 +42,13 @@ public function mockStatsdClientWithAssertionOnWrite($messageToAssert) { $mockSender = $this->mockSenderWithAssertionOnWrite($messageToAssert); - $statsdClient = new StatsdClient($mockSender, 'localhost', 100, 'udp', false, false); + $statsdClient = new StatsdClient($mockSender, false, false); return $statsdClient; } public function mockFactory() { - $mock = $this->getMock('\\Liuggio\\StatsdClient\\Factory\\StatsdDataFactory', array('timing')); + $mock = $this->getMock('\Liuggio\StatsdClient\Factory\StatsdDataFactory', array('timing')); $statsData = new StatsdData(); $statsData->setKey('key'); @@ -111,8 +110,6 @@ public function testPrepareAndSend($statsdInput, $assertion) { $statsdMock = $this->mockStatsdClientWithAssertionOnWrite($assertion); $statsdMock->send($statsdInput); - - $this->assertTrue(true); } /** @@ -122,8 +119,6 @@ public function testSend($array, $assertion) { $statsdMock = $this->mockStatsdClientWithAssertionOnWrite($assertion); $statsdMock->send($array); - - $this->assertTrue(true); } public function testReduceCount() @@ -142,7 +137,6 @@ public function testReduceCount() $entity0->setMetric('ms'); $array0[] = $entity0; - $reducedMessage = array('key1:1|c' . PHP_EOL . 'key2:2|ms'); $this->assertEquals($statd->reduceCount($array0), $reducedMessage); diff --git a/tests/Liuggio/StatsdClient/StatsdDataFactoryTest.php b/tests/Liuggio/StatsdClient/StatsdDataFactoryTest.php index 2720206..7bf878d 100755 --- a/tests/Liuggio/StatsdClient/StatsdDataFactoryTest.php +++ b/tests/Liuggio/StatsdClient/StatsdDataFactoryTest.php @@ -2,10 +2,8 @@ namespace Liuggio\StatsdClient\Factory; - use Liuggio\StatsdClient\Factory\StatsdDataFactory; - class StatsDataFactoryTest extends \PHPUnit_Framework_TestCase { private $statsDataFactory;