diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..2454616 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,11 @@ +; top-most EditorConfig file +root = true + +# All files. +[*] +end_of_line = LF +indent_style = space +indent_size = 4 +charset = utf-8 +trim_trailing_whitespace = true +insert_final_newline = true diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..c2f3cbd --- /dev/null +++ b/.gitattributes @@ -0,0 +1,5 @@ +/tests/ export-ignore +/.gitignore export-ignore +/.gitattributes export-ignore +/phpcs.xml.dist export-ignore +/phpunit.xml.dist export-ignore diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..1f534b6 --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,48 @@ +on: + push: ~ + pull_request: ~ + +jobs: + phpcs: + name: PHPCS + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v2 + + - uses: shivammathur/setup-php@v2 + with: + php-version: 7.4 + coverage: none + tools: composer:v2, cs2pr + + - run: composer update --no-progress + + - run: vendor/bin/phpcs -q --report=checkstyle | cs2pr + + phpunit: + name: PHPUnit on ${{ matrix.php }} + runs-on: ubuntu-latest + continue-on-error: ${{ !matrix.stable }} + strategy: + fail-fast: false + matrix: + php: ['7.4', '8.0', '8.1'] + stable: [true] + + steps: + - uses: actions/checkout@v2 + with: + fetch-depth: 0 + + - uses: shivammathur/setup-php@v2 + with: + php-version: ${{ matrix.php }} + coverage: pcov + tools: composer:v2 + + - run: echo "::add-matcher::${{ runner.tool_cache }}/phpunit.json" + + - run: composer update --no-progress + + - run: vendor/bin/phpunit --coverage-text diff --git a/.gitignore b/.gitignore index 7579f74..0dba648 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,4 @@ -vendor -composer.lock +/vendor +/composer.lock +/.phpcs-cache +/.phpunit.result.cache diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index aed13b8..0000000 --- a/.travis.yml +++ /dev/null @@ -1,13 +0,0 @@ -language: php - -php: - - 5.6 - - 7.0 - - 7.1 - - 7.2 - -before_script: - - composer install - -script: - - vendor/bin/phpunit --coverage-text diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..9a475fd --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,96 @@ +# Change Log +All notable changes to this project will be documented in this file. +Updates should follow the [Keep a CHANGELOG](https://keepachangelog.com/) principles. + +## [Unreleased][unreleased] +### Added + - Added new `StatsDClient` interface, which `Client` now implements + - Added new `Exception` interface, which all exceptions now implement + +### Changed + - Supported PHP versions are now 7.4, 8.0, and 8.1 + - All properties and methods now have type hints where applicable + - The following methods return the `StatsDClient` interface instead of `Client`: + - `ConfigurationException::getInstance()` + - `ConnectionException::getInstance()` + - The following `Client` methods now return `void` instead of returning `$this`: + - `increment()` + - `decrement()` + - `startTiming()` + - `endTiming()` + - `timing()` + - `timings()` + - `time()` + - `gauge()` + - `set()` + - `send()` + - Renamed `Client::$instance_id` to `Client::$instanceId` + +## [1.5.0] - 2018-10-09 +### Added + - Added tags supporting Datadog format (#52) + +## [1.4.3] - 2017-07-17 +### Added + - Added Silex 2 support (#43) + +### Changed + - Dropped support for PHP <5.6 + - Test against PHP 7.1 + +## [1.4.2] - 2017-02-09 +### Changed + - Use `config` to allow publishing differently to views or assets within Laravel + +## [1.4.1] - 2017-02-02 +### Added + - Added Laravel 5.4 support + +## [1.4.0] - 2016-04-21 +### Added + - Custom timeout configurations + - Exception handling is now configurable + - Built-in Laravel 5 support + +### Fixed + - DNS lookup failures no longer raise exceptions + +## [1.3.0] - 2015-06-11 +### Changed + - Throwing an exception is now optional during connections to server and can be silently ignored + +## [1.2.0] - 2015-05-15 +### Added + - Configurable timeouts + - SET method: Count the number of unique values passed to a key + - PHP 5.6 testing on Travis + - Various test patches and improvements + +## [1.1.0] - 2014-02-01 +### Added + - PSR-4 support + - New documentation + +## [1.0.0] - 2013-08-27 + +This is the first fully stable version of StatsD library. This version has the following features: + + - Counters + - Gauges + - Timers + - Timing Blocks + - 100% Code Coverage + - Silex Service Provider + +[unreleased]: https://github.com/thephpleague/statsd/compare/1.5.0...master +[1.5.0]: https://github.com/thephpleague/statsd/compare/1.4.5...1.5.0 +[1.4.5]: https://github.com/thephpleague/statsd/compare/1.4.4...1.4.5 +[1.4.4]: https://github.com/thephpleague/statsd/compare/1.4.3...1.4.4 +[1.4.3]: https://github.com/thephpleague/statsd/compare/1.4.2...1.4.3 +[1.4.2]: https://github.com/thephpleague/statsd/compare/1.4.1...1.4.2 +[1.4.1]: https://github.com/thephpleague/statsd/compare/1.4.0...1.4.1 +[1.4.0]: https://github.com/thephpleague/statsd/compare/1.3.0...1.4.0 +[1.3.0]: https://github.com/thephpleague/statsd/compare/1.2.0...1.3.0 +[1.2.0]: https://github.com/thephpleague/statsd/compare/1.1.0...1.2.0 +[1.1.0]: https://github.com/thephpleague/statsd/compare/v1.0...1.1.0 +[1.0.0]: https://github.com/thephpleague/statsd/releases/tag/v1.0 diff --git a/README.md b/README.md index c3c2a96..a4d771b 100644 --- a/README.md +++ b/README.md @@ -32,18 +32,18 @@ To use the Statsd Service Provider, you must register the provider when bootstra ```php $statsd = new League\StatsD\Client(); -$statsd->configure(array( +$statsd->configure([ 'host' => '127.0.0.1', 'port' => 8125, 'namespace' => 'example' -)); +]); ``` OR ```php -$statsd1 = StatsD\Client::instance('server1')->configure(array(...)); -$statsd2 = StatsD\Client::instance('server2')->configure(array(...)); +$statsd1 = StatsD\Client::instance('server1')->configure([...]); +$statsd2 = StatsD\Client::instance('server2')->configure([...]); ``` The StatsD client wait for `ini_get('default_socket_timeout')` seconds when opening the socket by default. To reduce @@ -65,10 +65,10 @@ If omitted, this option defaults to `true`. ```php $statsd->increment('web.pageview'); $statsd->decrement('storage.remaining'); -$statsd->increment(array( +$statsd->increment([ 'first.metric', 'second.metric' -), 2); +], 2); $statsd->increment('web.clicks', 1, 0.5); ``` @@ -112,18 +112,18 @@ $statsd->time('api.dbcall', function () { ***Attention!** That functionality support of tags in Datadog format!* -You may configure it for all the metrics sending by the client. +You may configure it for all the metrics sending by the client. ```php -$statsd->configure(array( - 'tags' => array('some_general_tag' => 'value') -)); +$statsd->configure([ + 'tags' => ['some_general_tag' => 'value'] +]); ``` Or you may send it for a single metric. ```php -$statsd->increment('web.clicks', 1, 1, array('host' => $_SERVER['HTTP_HOST'])); +$statsd->increment('web.clicks', 1, 1, ['host' => $_SERVER['HTTP_HOST']]); ``` ## Framework integration @@ -136,19 +136,19 @@ integrate it quickly with the most popular ones via included adapters. Find the `providers` key in your `app/config/app.php` and register the Statsd Service Provider. ```php - 'providers' => array( + 'providers' => [ // ... 'League\StatsD\Laravel\Provider\StatsdServiceProvider', - ) + ] ``` Find the `aliases` key in your `app/config/app.php` and add the Statsd Facade Alias. ```php - 'aliases' => array( + 'aliases' => [ // ... 'Statsd' => 'League\StatsD\Laravel\Facade\StatsdFacade', - ) + ] ``` ### Laravel 5.x diff --git a/composer.json b/composer.json index 9531772..6b410e8 100644 --- a/composer.json +++ b/composer.json @@ -16,8 +16,12 @@ "role": "Developer" } ], + "require": { + "php": "^7.4 || ^8.0" + }, "require-dev": { - "phpunit/phpunit": "^5.7 || ^6.5" + "phpunit/phpunit": "^9.5", + "squizlabs/php_codesniffer": "^3.6" }, "autoload": { "psr-4": { diff --git a/docs/Getting Started.md b/docs/Getting Started.md index 961831e..51951f6 100644 --- a/docs/Getting Started.md +++ b/docs/Getting Started.md @@ -24,11 +24,11 @@ Creating a new instance within your application is very easy. ```php $statsd = new League\StatsD\Client(); -$statsd->configure(array( +$statsd->configure([ 'host' => 'localhost', 'port' => 8125, 'namespace' => 'ns1' -)); +]); ``` **Note** The namespace is optional, but recommended. diff --git a/phpcs.xml.dist b/phpcs.xml.dist new file mode 100644 index 0000000..c1606bc --- /dev/null +++ b/phpcs.xml.dist @@ -0,0 +1,20 @@ + + + + + + + + + + + + + src + tests + + \ No newline at end of file diff --git a/phpunit.xml.dist b/phpunit.xml.dist index 379cbb3..6af4cd6 100644 --- a/phpunit.xml.dist +++ b/phpunit.xml.dist @@ -1,13 +1,19 @@ - + + + + + src/ + + + tests - - - src/ - - + diff --git a/src/Client.php b/src/Client.php index 163991d..e1f21bc 100644 --- a/src/Client.php +++ b/src/Client.php @@ -2,139 +2,92 @@ namespace League\StatsD; -use League\StatsD\Exception\ConnectionException; use League\StatsD\Exception\ConfigurationException; +use League\StatsD\Exception\ConnectionException; /** * StatsD Client Class * * @author Marc Qualie */ -class Client +class Client implements StatsDClient { + /** Instance instances array */ + protected static array $instances = []; - /** - * Instance instances array - * @var array - */ - protected static $instances = array(); + /** Instance ID */ + protected string $instanceId; + /** Server Host */ + protected string $host = '127.0.0.1'; - /** - * Instance ID - * @var string - */ - protected $instance_id; + /** Server Port */ + protected int $port = 8125; + /** Last message sent to the server */ + protected string $message = ''; - /** - * Server Host - * @var string - */ - protected $host = '127.0.0.1'; + /** Class namespace */ + protected string $namespace = ''; + /** imeout for creating the socket connection */ + protected ?float $timeout = null; - /** - * Server Port - * @var integer - */ - protected $port = 8125; - - - /** - * Last message sent to the server - * @var string - */ - protected $message = ''; - + /** Whether an exception should be thrown on failed connections */ + protected bool $throwConnectionExceptions = true; - /** - * Class namespace - * @var string - */ - protected $namespace = ''; + /** Record metric start time */ + protected array $metricTiming; - /** - * Timeout for creating the socket connection - * @var null|float - */ - protected $timeout; - - /** - * Whether or not an exception should be thrown on failed connections - * @var bool - */ - protected $throwConnectionExceptions = true; - - /** - * Record metric start time - * @var array - */ - protected $metricTiming; - - /** - * Socket pointer for sending metrics - * @var resource - */ + /** @var resource|false|null Socket pointer for sending metrics */ protected $socket; - /** - * Generic tags - * @var array - */ - protected $tags = []; + /** Generic tags */ + protected array $tags = []; /** * Singleton Reference - * @param string $name Instance name - * @return Client Client instance */ - public static function instance($name = 'default') + public static function instance(string $name = 'default'): StatsDClient { if (! isset(self::$instances[$name])) { self::$instances[$name] = new static($name); } + return self::$instances[$name]; } - /** * Create a new instance - * @param string $instance_id - * @return void */ - public function __construct($instance_id = null) + public function __construct(?string $instanceId = null) { - $this->instance_id = $instance_id ?: uniqid(); - - if (empty($this->timeout)) { + $this->instanceId = $instanceId ?? uniqid(); + if ($this->timeout === null) { $this->timeout = ini_get('default_socket_timeout'); } } - /** - * Get string value of instance - * @return string String representation of this instance - */ - public function __toString() + public function __toString(): string { - return 'StatsD\Client::[' . $this->instance_id . ']'; + return 'StatsD\Client::[' . $this->instanceId . ']'; } - /** * Initialize Connection Details + * * @param array $options Configuration options + * * @return Client This instance * @throws ConfigurationException If port is invalid */ - public function configure(array $options = array()) + public function configure(array $options = []): self { if (isset($options['host'])) { $this->host = $options['host']; } if (isset($options['port'])) { - if (!is_numeric($options['port']) || is_float($options['port']) || $options['port'] < 0 || $options['port'] > 65535) { + if (! is_numeric($options['port']) || is_float($options['port']) || $options['port'] < 0 || $options['port'] > 65535) { throw new ConfigurationException($this, 'Port is out of range'); } $this->port = $options['port']; @@ -159,60 +112,43 @@ public function configure(array $options = array()) return $this; } - - /** - * Get Host - * @return string Host - */ - public function getHost() + public function getHost(): string { return $this->host; } - - /** - * Get Port - * @return string Port - */ - public function getPort() + public function getPort(): int { return $this->port; } - - /** - * Get Namespace - * @return string Namespace - */ - public function getNamespace() + public function getNamespace(): string { return $this->namespace; } - /** - * Get Last Message - * @return string Last message sent to server + * Get Last message sent to server */ - public function getLastMessage() + public function getLastMessage(): string { return $this->message; } - /** * Increment a metric - * @param string|array $metrics Metric(s) to increment - * @param int $delta Value to decrement the metric by - * @param int $sampleRate Sample rate of metric - * @param array $tags A list of metric tags values - * @return $this + * + * @param string|array $metrics Metric(s) to increment + * @param int $delta Value to decrement the metric by + * @param float $sampleRate Sample rate of metric + * @param array $tags A list of metric tags values + * * @throws ConnectionException */ - public function increment($metrics, $delta = 1, $sampleRate = 1, array $tags = []) + public function increment($metrics, int $delta = 1, float $sampleRate = 1, array $tags = []): void { - $metrics = (array) $metrics; - $data = array(); + $metrics = (array)$metrics; + $data = []; if ($sampleRate < 1) { foreach ($metrics as $metric) { if ((mt_rand() / mt_getrandmax()) <= $sampleRate) { @@ -224,150 +160,142 @@ public function increment($metrics, $delta = 1, $sampleRate = 1, array $tags = [ $data[$metric] = $delta . '|c'; } } - return $this->send($data, $tags); - } + $this->send($data, $tags); + } /** * Decrement a metric - * @param string|array $metrics Metric(s) to decrement - * @param int $delta Value to increment the metric by - * @param int $sampleRate Sample rate of metric - * @param array $tags A list of metric tags values - * @return $this + * + * @param string|array $metrics Metric(s) to decrement + * @param int $delta Value to increment the metric by + * @param float $sampleRate Sample rate of metric + * @param array $tags A list of metric tags values + * * @throws ConnectionException */ - public function decrement($metrics, $delta = 1, $sampleRate = 1, array $tags = []) + public function decrement($metrics, int $delta = 1, float $sampleRate = 1, array $tags = []): void { - return $this->increment($metrics, 0 - $delta, $sampleRate, $tags); + $this->increment($metrics, 0 - $delta, $sampleRate, $tags); } /** * Start timing the given metric - * @param string $metric Metric to time - * @return $this + * + * @param string $metric Metric to time */ - public function startTiming($metric) + public function startTiming(string $metric): void { $this->metricTiming[$metric] = microtime(true); - return $this; } /** * End timing the given metric and record - * @param string $metric Metric to time - * @param array $tags A list of metric tags values - * @return $this + * + * @param string $metric Metric to time + * @param array $tags A list of metric tags values + * * @throws ConnectionException */ - public function endTiming($metric, array $tags = array()) + public function endTiming(string $metric, array $tags = []): void { $timer_start = $this->metricTiming[$metric]; - $timer_end = microtime(true); - $time = round(($timer_end - $timer_start) * 1000, 4); - return $this->timing($metric, $time, $tags); + $timer_end = microtime(true); + $time = round(($timer_end - $timer_start) * 1000, 4); + $this->timing($metric, $time, $tags); } /** * Timing - * @param string $metric Metric to track - * @param float $time Time in milliseconds - * @param array $tags A list of metric tags values - * @return $this + * + * @param string $metric Metric to track + * @param float $time Time in milliseconds + * @param array $tags A list of metric tags values + * * @throws ConnectionException */ - public function timing($metric, $time, array $tags = array()) + public function timing(string $metric, float $time, array $tags = []): void { - return $this->send( - array( - $metric => $time . '|ms' - ), + $this->send( + [$metric => $time . '|ms'], $tags ); } /** * Send multiple timing metrics at once + * * @param array $metrics key value map of metric name -> timing value - * @return Client + * * @throws ConnectionException */ - public function timings($metrics) + public function timings(array $metrics): void { // add |ms to values $data = []; foreach ($metrics as $metric => $timing) { - $data[$metric] = $timing.'|ms'; + $data[$metric] = $timing . '|ms'; } - return $this->send($data); + $this->send($data); } /** * Time a function - * @param string $metric Metric to time - * @param callable $func Function to record - * @param array $tags A list of metric tags values - * @return $this + * + * @param string $metric Metric to time + * @param callable $func Function to record + * @param array $tags A list of metric tags values + * * @throws ConnectionException */ - public function time($metric, $func, array $tags = array()) + public function time(string $metric, $func, array $tags = []): void { $timer_start = microtime(true); $func(); $timer_end = microtime(true); - $time = round(($timer_end - $timer_start) * 1000, 4); - return $this->timing($metric, $time, $tags); + $time = round(($timer_end - $timer_start) * 1000, 4); + $this->timing($metric, $time, $tags); } /** * Gauges - * @param string $metric Metric to gauge - * @param int $value Set the value of the gauge - * @param array $tags A list of metric tags values - * @return $this + * + * @param string $metric Metric to gauge + * @param int $value Set the value of the gauge + * @param array $tags A list of metric tags values + * * @throws ConnectionException */ - public function gauge($metric, $value, array $tags = array()) + public function gauge(string $metric, int $value, array $tags = []): void { - return $this->send( - array( - $metric => $value . '|g' - ), - $tags - ); + $this->send([$metric => $value . '|g'], $tags); } - /** * Sets - count the number of unique values passed to a key - * @param $metric + * + * @param string $metric * @param mixed $value * @param array $tags A list of metric tags values - * @return $this + * * @throws ConnectionException */ - public function set($metric, $value, array $tags = array()) + public function set(string $metric, $value, array $tags = []): void { - return $this->send( - array( - $metric => $value . '|s' - ), - $tags - ); + $this->send([$metric => $value . '|s'], $tags); } - /** - * @throws ConnectionException * @return resource + * @throws ConnectionException */ protected function getSocket() { - if (!$this->socket) { + if (! $this->socket) { $this->socket = @fsockopen('udp://' . $this->host, $this->port, $errno, $errstr, $this->timeout); - if (!$this->socket) { + if (! $this->socket) { throw new ConnectionException($this, '(' . $errno . ') ' . $errstr); } } @@ -375,38 +303,35 @@ protected function getSocket() return $this->socket; } - /** - * @param array $tags - * @return string - */ - protected function serializeTags(array $tags) + protected function serializeTags(array $tags): string { - if (!is_array($tags) || count($tags) === 0) { + if (! is_array($tags) || count($tags) === 0) { return ''; } - $data = array(); + $data = []; foreach ($tags as $tagKey => $tagValue) { $data[] = isset($tagValue) ? $tagKey . ':' . $tagValue : $tagKey; } + return '|#' . implode(',', $data); } - /** * Send Data to StatsD Server - * @param array $data A list of messages to send to the server - * @param array $tags A list of tags to send to the server - * @return $this + * + * @param array $data A list of messages to send to the server + * @param array $tags A list of tags to send to the server + * * @throws ConnectionException If there is a connection problem with the host */ - protected function send(array $data, array $tags = array()) + protected function send(array $data, array $tags = []): void { $tagsData = $this->serializeTags(array_replace($this->tags, $tags)); try { - $socket = $this->getSocket(); - $messages = array(); - $prefix = $this->namespace ? $this->namespace . '.' : ''; + $socket = $this->getSocket(); + $messages = []; + $prefix = $this->namespace ? $this->namespace . '.' : ''; foreach ($data as $key => $value) { $messages[] = $prefix . $key . ':' . $value . $tagsData; } @@ -423,7 +348,5 @@ protected function send(array $data, array $tags = array()) ); } } - - return $this; } } diff --git a/src/Exception/ConfigurationException.php b/src/Exception/ConfigurationException.php index 05f94d6..fd7ce8d 100644 --- a/src/Exception/ConfigurationException.php +++ b/src/Exception/ConfigurationException.php @@ -2,28 +2,25 @@ namespace League\StatsD\Exception; -use League\StatsD\Client; +use League\StatsD\StatsDClient; /** * Configuration Exception Class */ -class ConfigurationException extends \Exception +class ConfigurationException extends \Exception implements Exception { - - /** * Client instance that threw the exception - * @var Client */ - protected $instance; - + protected StatsDClient $instance; /** * Create new instance - * @param Client $instance Client instance that threw the exception - * @param string $message Exception message + * + * @param StatsDClient $instance Client instance that threw the exception + * @param string $message Exception message */ - public function __construct($instance, $message) + public function __construct(StatsDClient $instance, string $message) { $this->instance = $instance; parent::__construct($message); @@ -31,9 +28,8 @@ public function __construct($instance, $message) /** * Get Client instance that threw the exception - * @return Client Client instance */ - public function getInstance() + public function getInstance(): StatsDClient { return $this->instance; } diff --git a/src/Exception/ConnectionException.php b/src/Exception/ConnectionException.php index 6742dac..3d25314 100644 --- a/src/Exception/ConnectionException.php +++ b/src/Exception/ConnectionException.php @@ -2,28 +2,25 @@ namespace League\StatsD\Exception; -use League\StatsD\Client; +use League\StatsD\StatsDClient; /** * Connection Exception Class */ -class ConnectionException extends \Exception +class ConnectionException extends \Exception implements Exception { - - /** * Client instance that threw the exception - * @var Client */ - protected $instance; - + protected StatsDClient $instance; /** * Create new instance - * @param Client $instance Client instance that threw the exception - * @param string $message Exception message + * + * @param StatsDClient $instance Client instance that threw the exception + * @param string $message Exception message */ - public function __construct($instance, $message) + public function __construct(StatsDClient $instance, string $message) { $this->instance = $instance; parent::__construct($message); @@ -31,9 +28,8 @@ public function __construct($instance, $message) /** * Get Client instance that threw the exception - * @return Client Client instance */ - public function getInstance() + public function getInstance(): StatsDClient { return $this->instance; } diff --git a/src/Exception/Exception.php b/src/Exception/Exception.php new file mode 100644 index 0000000..ea798e8 --- /dev/null +++ b/src/Exception/Exception.php @@ -0,0 +1,9 @@ +app['statsd'] = $this->app->share( function ($app) { // Set Default host and port - $options = array(); + $options = []; $config = $app['config']; if (isset($config['statsd.host'])) { @@ -63,7 +62,7 @@ function ($app) { } if (isset($config['statsd.throwConnectionExceptions'])) { - $options['throwConnectionExceptions'] = (boolean) $config['statsd.throwConnectionExceptions']; + $options['throwConnectionExceptions'] = (bool) $config['statsd.throwConnectionExceptions']; } // Create diff --git a/src/Laravel5/Provider/StatsdServiceProvider.php b/src/Laravel5/Provider/StatsdServiceProvider.php index 6924542..3394999 100644 --- a/src/Laravel5/Provider/StatsdServiceProvider.php +++ b/src/Laravel5/Provider/StatsdServiceProvider.php @@ -47,10 +47,11 @@ public function register() */ protected function registerStatsD() { - $this->app->singleton('statsd', + $this->app->singleton( + 'statsd', function ($app) { // Set Default host and port - $options = array(); + $options = []; $config = $app['config']; if (isset($config['statsd.host'])) { @@ -70,7 +71,7 @@ function ($app) { } if (isset($config['statsd.throwConnectionExceptions'])) { - $options['throwConnectionExceptions'] = (boolean) $config['statsd.throwConnectionExceptions']; + $options['throwConnectionExceptions'] = (bool) $config['statsd.throwConnectionExceptions']; } // Create diff --git a/src/StatsDClient.php b/src/StatsDClient.php new file mode 100644 index 0000000..4383cbc --- /dev/null +++ b/src/StatsDClient.php @@ -0,0 +1,107 @@ + + */ +interface StatsDClient +{ + /** + * Increment a metric + * + * @param string|array $metrics Metric(s) to increment + * @param int $delta Value to decrement the metric by + * @param float $sampleRate Sample rate of metric + * @param array $tags A list of metric tags values + * + * @throws ConnectionException + */ + public function increment($metrics, int $delta = 1, float $sampleRate = 1, array $tags = []): void; + + /** + * Decrement a metric + * + * @param string|array $metrics Metric(s) to decrement + * @param int $delta Value to increment the metric by + * @param float $sampleRate Sample rate of metric + * @param array $tags A list of metric tags values + * + * @throws ConnectionException + */ + public function decrement($metrics, int $delta = 1, float $sampleRate = 1, array $tags = []): void; + + /** + * Start timing the given metric + * + * @param string $metric Metric to time + */ + public function startTiming(string $metric): void; + + /** + * End timing the given metric and record + * + * @param string $metric Metric to time + * @param array $tags A list of metric tags values + * + * @throws ConnectionException + */ + public function endTiming(string $metric, array $tags = []): void; + + /** + * Timing + * + * @param string $metric Metric to track + * @param float $time Time in milliseconds + * @param array $tags A list of metric tags values + * + * @throws ConnectionException + */ + public function timing(string $metric, float $time, array $tags = []): void; + + /** + * Send multiple timing metrics at once + * + * @param array $metrics key value map of metric name -> timing value + * + * @throws ConnectionException + */ + public function timings(array $metrics): void; + + /** + * Time a function + * + * @param string $metric Metric to time + * @param callable $func Function to record + * @param array $tags A list of metric tags values + * + * @throws ConnectionException + */ + public function time(string $metric, $func, array $tags = []): void; + + /** + * Gauges + * + * @param string $metric Metric to gauge + * @param int $value Set the value of the gauge + * @param array $tags A list of metric tags values + * + * @throws ConnectionException + */ + public function gauge(string $metric, int $value, array $tags = []): void; + + /** + * Sets - count the number of unique values passed to a key + * + * @param string $metric + * @param mixed $value + * @param array $tags A list of metric tags values + * + * @throws ConnectionException + */ + public function set(string $metric, $value, array $tags = []): void; +} diff --git a/tests/ClientTest.php b/tests/ClientTest.php index 1a2db03..baff8da 100644 --- a/tests/ClientTest.php +++ b/tests/ClientTest.php @@ -1,29 +1,26 @@ assertInstanceOf(Client::class, $client); - $this->assertRegExp('/^StatsD\\\Client::\[[a-zA-Z0-9]+\]$/', (String) $client); + $this->assertMatchesRegularExpression('/^StatsD\\\Client::\[[a-zA-Z0-9]+\]$/', (string) $client); } - public function testStaticInstance() { $client1 = Client::instance('instance1'); $this->assertInstanceOf(Client::class, $client1); $client2 = Client::instance('instance2'); $client3 = Client::instance('instance1'); - $this->assertEquals('StatsD\Client::[instance2]', (String) $client2); - $this->assertFalse((String) $client1 === (String) $client2); - $this->assertTrue((String) $client1 === (String) $client3); + $this->assertEquals('StatsD\Client::[instance2]', (string) $client2); + $this->assertFalse((string) $client1 === (string) $client2); + $this->assertTrue((string) $client1 === (string) $client3); } - } diff --git a/tests/ConfigurationTest.php b/tests/ConfigurationTest.php index 31877f1..5c773e1 100644 --- a/tests/ConfigurationTest.php +++ b/tests/ConfigurationTest.php @@ -2,18 +2,17 @@ namespace League\StatsD\Test; +use League\StatsD\Exception\ConfigurationException; + class ConfigurationTest extends TestCase { - /** * Large ports should be out of range - * @expectedException League\StatsD\Exception\ConfigurationException */ public function testLargePort() { - $this->client->configure(array( - 'port' => 65536 - )); + $this->expectException(ConfigurationException::class); + $this->client->configure(['port' => 65536]); } /** @@ -21,44 +20,42 @@ public function testLargePort() */ public function testPort0() { - $this->client->configure(array( - 'port' => 0 - )); + $this->client->configure(['port' => 0]); $this->assertEquals($this->client->getPort(), 0); } /** * Non-integer ports are not acceptable - * @expectedException League\StatsD\Exception\ConfigurationException */ public function testStringPort() { - $this->client->configure(array( + $this->expectException(ConfigurationException::class); + $this->client->configure([ 'port' => 'not-integer' - )); + ]); } /** * Decimal ports are not acceptable - * @expectedException League\StatsD\Exception\ConfigurationException */ public function testDecimalPort() { - $this->client->configure(array( + $this->expectException(ConfigurationException::class); + $this->client->configure([ 'port' => 1.24, - )); + ]); } /** * Negative ports are not acceptable - * @expectedException League\StatsD\Exception\ConfigurationException */ public function testNegativePort() { - $this->client->configure(array( + $this->expectException(ConfigurationException::class); + $this->client->configure([ 'port' => -1 - )); + ]); } /** @@ -75,10 +72,9 @@ public function testDefaultPort() */ public function testValidPort() { - $this->client->configure(array( + $this->client->configure([ 'port' => 1234 - )); + ]); $this->assertEquals($this->client->getPort(), 1234); } - } diff --git a/tests/ConnectionTest.php b/tests/ConnectionTest.php index a8d087d..e127716 100644 --- a/tests/ConnectionTest.php +++ b/tests/ConnectionTest.php @@ -2,41 +2,44 @@ namespace League\StatsD\Test; +use League\StatsD\Client; +use League\StatsD\Exception\ConnectionException; + class ConnectionTest extends TestCase { /** * Non-integer ports are not acceptable - * @expectedException League\StatsD\Exception\ConnectionException */ public function testInvalidHost() { - $this->client->configure(array( + $this->expectException(ConnectionException::class); + $this->client->configure([ 'host' => 'hostdoesnotexiststalleverlol.stupidtld' - )); + ]); $this->client->increment('test'); } public function testTimeoutSettingIsUsedWhenCreatingSocketIfProvided() { - $this->client->configure(array( + $client = (new TestClient())->configure([ 'host' => 'localhost', 'timeout' => 123 - )); - $this->assertAttributeSame(123, 'timeout', $this->client); + ]); + $this->assertSame((float)123, $client->getTimeout()); } public function testCanBeConfiguredNotToThrowConnectionExceptions() { - $this->client->configure(array( + $this->client->configure([ 'host' => 'hostdoesnotexiststalleverlol.stupidtld', 'throwConnectionExceptions' => false - )); + ]); $handlerInvoked = false; $testCase = $this; set_error_handler( - function ($errno, $errstr, $errfile, $errline, $errcontext) use ($testCase, &$handlerInvoked) { + function ($errno, $errstr, $errfile) use ($testCase, &$handlerInvoked) { $handlerInvoked = true; $testCase->assertSame(E_USER_WARNING, $errno); @@ -57,6 +60,6 @@ function ($errno, $errstr, $errfile, $errline, $errcontext) use ($testCase, &$ha public function testTimeoutDefaultsToPhpIniDefaultSocketTimeout() { - $this->assertAttributeSame(ini_get('default_socket_timeout'), 'timeout', $this->client); + $this->assertSame((float)ini_get('default_socket_timeout'), (new TestClient())->configure()->getTimeout()); } } diff --git a/tests/CounterTest.php b/tests/CounterTest.php index 155aeee..3de19d9 100644 --- a/tests/CounterTest.php +++ b/tests/CounterTest.php @@ -4,41 +4,35 @@ class CounterTest extends TestCase { - public function testIncrement() { $this->client->increment('test_metric'); $this->assertEquals('test_metric:1|c', $this->client->getLastMessage()); } - public function testIncrementDelta() { $this->client->increment('test_metric', 2); $this->assertEquals('test_metric:2|c', $this->client->getLastMessage()); } - public function testIncrementSample() { while ($this->client->getLastMessage() === '') { - $this->client->increment('test_metric', 1, 0.75); + $this->client->increment('test_metric', 1, 0.75); } $this->assertEquals('test_metric:1|c|@0.75', $this->client->getLastMessage()); } - public function testDecrement() { $this->client->decrement('test_metric'); $this->assertEquals('test_metric:-1|c', $this->client->getLastMessage()); } - public function testDecrementDelta() { $this->client->decrement('test_metric', 3); $this->assertEquals('test_metric:-3|c', $this->client->getLastMessage()); } - } diff --git a/tests/ExceptionTest.php b/tests/ExceptionTest.php index 8bc23d8..a49ca5b 100644 --- a/tests/ExceptionTest.php +++ b/tests/ExceptionTest.php @@ -1,14 +1,13 @@ getInstance(); $this->assertInstanceOf(Client::class, $client); $this->assertEquals('Could not connect', $e->getMessage()); - return; } - throw new \Exception('Connection Exception not caught'); } - public function testConfigurationException() { try { @@ -31,9 +27,6 @@ public function testConfigurationException() $client = $e->getInstance(); $this->assertInstanceOf(Client::class, $client); $this->assertEquals('Configuration error', $e->getMessage()); - return; } - throw new \Exception('Configuration Exception not caught'); } - } diff --git a/tests/GaugeTest.php b/tests/GaugeTest.php index d457e23..58d2aff 100644 --- a/tests/GaugeTest.php +++ b/tests/GaugeTest.php @@ -4,11 +4,9 @@ class GaugeTest extends TestCase { - public function testGauge() { $this->client->gauge('test_metric', 456); $this->assertEquals('test_metric:456|g', $this->client->getLastMessage()); } - } diff --git a/tests/LaravelFacadeTest.php b/tests/LaravelFacadeTest.php index 647431c..81a7281 100644 --- a/tests/LaravelFacadeTest.php +++ b/tests/LaravelFacadeTest.php @@ -19,4 +19,4 @@ public function testFacadeCanBeResolvedToServiceInstance() $statsd = Statsd::instance(); $this->assertInstanceOf(Client::class, $statsd); } -} \ No newline at end of file +} diff --git a/tests/LaravelProviderTest.php b/tests/LaravelProviderTest.php index 0d7af1a..6cc5c64 100644 --- a/tests/LaravelProviderTest.php +++ b/tests/LaravelProviderTest.php @@ -6,7 +6,6 @@ class LaravelProviderTest extends LaravelTestCase { - public function testProvider() { $app = $this->setupApplication(); @@ -23,10 +22,8 @@ public function testProvider() // Make sure messages are tracked properly $app['statsd']->increment('test_metric'); $this->assertEquals('test_namespace.test_metric:1|c', $app['statsd']->getLastMessage()); - } - public function testProviderDefaults() { $app = $this->setupApplication(false); @@ -40,7 +37,5 @@ public function testProviderDefaults() // Make sure messages are tracked properly $app['statsd']->increment('test_metric', 2); $this->assertEquals('test_metric:2|c', $app['statsd']->getLastMessage()); - } - } diff --git a/tests/LaravelTestCase.php b/tests/LaravelTestCase.php index f12ff4d..4dde96e 100644 --- a/tests/LaravelTestCase.php +++ b/tests/LaravelTestCase.php @@ -9,8 +9,7 @@ class LaravelTestCase extends TestCase { - - public function setUp() + protected function setUp(): void { parent::setUp(); if (!class_exists(Application::class)) { @@ -22,15 +21,15 @@ public function setupApplication($config = true) { $app = new Application(); $app->instance('path', 'foobar'); - $app->instance('files', new Filesystem); + $app->instance('files', new Filesystem()); $app->instance('config', new Repository($app->getConfigLoader(), 'foobar')); if ($config) { - $app['config']->set('statsd', array( + $app['config']->set('statsd', [ 'host' => "localhost", 'port' => 7890, 'namespace' => 'test_namespace' - )); + ]); } return $app; @@ -45,4 +44,4 @@ public function setupServiceProvider(Application $app) return $provider; } -} \ No newline at end of file +} diff --git a/tests/LateStaticClient.php b/tests/LateStaticClient.php deleted file mode 100644 index 9f06fb5..0000000 --- a/tests/LateStaticClient.php +++ /dev/null @@ -1,8 +0,0 @@ -assertInstanceOf(LateStaticClient::class, $instance); + $client = TestClient::instance(); + $this->assertSame($client, TestClient::instance()); } - } diff --git a/tests/NamespaceTest.php b/tests/NamespaceTest.php index 3a2856f..3730962 100644 --- a/tests/NamespaceTest.php +++ b/tests/NamespaceTest.php @@ -4,27 +4,25 @@ class NamespaceTest extends TestCase { - public function testNamespace() { - $this->client->configure(array( + $this->client->configure([ 'host' => '127.0.0.1', 'port' => 8125, 'namespace' => 'test_namespace' - )); + ]); $this->assertEquals($this->client->getNamespace(), 'test_namespace'); } public function testNamespaceIncrement() { - $this->client->configure(array( + $this->client->configure([ 'host' => '127.0.0.1', 'port' => 8125, 'namespace' => 'test_namespace' - )); + ]); $this->client->increment('test_metric'); $this->assertEquals($this->client->getLastMessage(), 'test_namespace.test_metric:1|c'); } - } diff --git a/tests/SetTest.php b/tests/SetTest.php index 58e5604..3e36c86 100644 --- a/tests/SetTest.php +++ b/tests/SetTest.php @@ -4,11 +4,9 @@ class SetTest extends TestCase { - public function testSet() { $this->client->set('test_metric', 456); $this->assertEquals('test_metric:456|s', $this->client->getLastMessage()); } - } diff --git a/tests/TestCase.php b/tests/TestCase.php index 9e716e1..0981680 100644 --- a/tests/TestCase.php +++ b/tests/TestCase.php @@ -1,19 +1,16 @@ client = new Client(); $this->client->configure(); - } - } diff --git a/tests/TestClient.php b/tests/TestClient.php new file mode 100644 index 0000000..8ca9d83 --- /dev/null +++ b/tests/TestClient.php @@ -0,0 +1,11 @@ +timeout; + } +} diff --git a/tests/TimerTest.php b/tests/TimerTest.php index 8002090..8cab347 100644 --- a/tests/TimerTest.php +++ b/tests/TimerTest.php @@ -4,20 +4,18 @@ class TimerTest extends TestCase { - public function testTiming() { $this->client->timing('test_metric', 123); $this->assertEquals('test_metric:123|ms', $this->client->getLastMessage()); } - public function testFunctionTiming() { $this->client->time('test_metric', function () { usleep(50000); }); - $this->assertRegExp('/test_metric:5[0-9]{1}\.[0-9]+\|ms/', $this->client->getLastMessage()); + $this->assertMatchesRegularExpression('/test_metric:5[0-9]{1}\.[0-9]+\|ms/', $this->client->getLastMessage()); } public function testStartEndTiming() @@ -25,6 +23,6 @@ public function testStartEndTiming() $this->client->startTiming('test_metric'); usleep(50000); $this->client->endTiming('test_metric'); - $this->assertRegExp('/test_metric:5[0-9]{1}\.[0-9]+\|ms/', $this->client->getLastMessage()); + $this->assertMatchesRegularExpression('/test_metric:5[0-9]{1}\.[0-9]+\|ms/', $this->client->getLastMessage()); } } diff --git a/tests/TimingsTest.php b/tests/TimingsTest.php index 5c1c3e7..8ebb7fb 100644 --- a/tests/TimingsTest.php +++ b/tests/TimingsTest.php @@ -4,17 +4,16 @@ class TimingsTest extends TestCase { - public function testTiming() { - $timings = array( + $timings = [ 'test_metric1' => 123, 'test_metric2' => 234, 'test_metric3' => .234, - ); + ]; $this->client->timings($timings); $this->assertEquals( - 'test_metric1:123|ms'.PHP_EOL.'test_metric2:234|ms'.PHP_EOL.'test_metric3:0.234|ms', + 'test_metric1:123|ms' . PHP_EOL . 'test_metric2:234|ms' . PHP_EOL . 'test_metric3:0.234|ms', $this->client->getLastMessage() ); }