diff --git a/.travis.yml b/.travis.yml index 6e669d0d3..fe9229a81 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,23 +1,26 @@ language: php + php: -- 5.4 -- 5.5 -- 5.6 + - 5.5 + - 5.6 + before_install: -- sudo apt-get update -- sudo apt-get install libcurl4-openssl-dev libjson0-dev -- wget http://s3.amazonaws.com/influxdb/influxdb_latest_amd64.deb -- sudo useradd influxdb -- sudo dpkg -i influxdb_latest_amd64.deb -- sudo cp ./scripts/influxdb_conf.toml /opt/influxdb/shared/config.toml -- travis_retry sudo service influxdb restart -- sudo service influxdb status + - sudo apt-get update + - sudo apt-get install libcurl4-openssl-dev libjson0-dev + - wget http://get.influxdb.org/influxdb_0.9.0-rc33_amd64.deb + - sudo useradd influxdb + - sudo dpkg -i influxdb_0.9.0-rc33_amd64.deb + - sudo cp ./scripts/influxdb_conf.toml /etc/opt/influxdb/influxdb.conf + - travis_retry sudo service influxdb restart + - sudo service influxdb status + before_script: -- composer selfupdate -- composer install --prefer-source + - composer selfupdate + - composer install --prefer-source + script: -- vendor/bin/phpspec run -n -- vendor/bin/phpunit + - vendor/bin/phpunit + notifications: slack: secure: UN4V33CfLzEcb+5/LWcfcbwROZobbUawgFSiM3TzagBC+7w0DH2rK8DczxkUBs5rNAaYBj+DkxmmF9tiDb0BLB7Jezlq0vmrNBOhregLodOG44/bFwg58YOwTGxt/Iak38A+8VskGj0sSybNq4TB1/K0040wXS5bA+M/9NqyQeo= diff --git a/LICENSE b/LICENSE index a29931ccd..db1e02eeb 100644 --- a/LICENSE +++ b/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2014 Corley S.r.l. +Copyright (c) 2015 Corley S.r.l. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/README.md b/README.md index 5d766d332..90e9bb1c4 100644 --- a/README.md +++ b/README.md @@ -7,6 +7,13 @@ Send metrics to InfluxDB and query for any data. +This project support InfluxDB API `>= 0.9` - **For InfluxDB v0.8 checkout branch 0.3** + +Supported adapters: + + * HTTP + * UDP/IP + ## Install it Just use composer @@ -34,22 +41,41 @@ $client->mark("app.search", [ ]); ``` +Or use InfluxDB direct messages + +```php +$client->mark([ + "tags" => [ + "dc" => "eu-west-1", + ], + "points" => [ + [ + "measurement" => "instance", + "fields" => [ + "cpu" => 18.12, + "free" => 712423, + ], + ], + ] +]); +``` + + Retrieve existing points: ```php -$results = $client->query("select * from app.search"); +$results = $client->query('select * from "app.search"'); ``` ## InfluxDB client adapters -Actually we supports two adapters +Actually we supports two network adapters - * UDP/IP - in order to send data via UDP (datagram) - * HTTP JSON - in order to send/retrieve using HTTP (connection oriented) + * UDP/IP - in order to send data via UDP/IP (datagram) + * HTTP JSON - in order to send/retrieve using HTTP messages (connection oriented) ### Using UDP/IP Adapter - In order to use the UDP/IP adapter your must have PHP compiled with the `sockets` extension. To verify if you have the `sockets` extension just issue a: @@ -60,8 +86,9 @@ php -m | grep sockets If you don't have the `sockets` extension, you can proceed in two ways: -- Recompile your PHP whith the `--enable-sockets` flag -- Or just compile the `sockets` extension extracting it from the PHP source. + - Recompile your PHP whith the `--enable-sockets` flag + - Or just compile the `sockets` extension extracting it from the PHP source. + 1. Download the source relative to the PHP version that you on from [here](https://github.com/php/php-src/releases) 2. Enter in the `ext/sockets` directory 3. Issue a `phpize && ./configure && make -j && sudo make install` @@ -83,23 +110,16 @@ Actually Guzzle is used as HTTP client library ```php setAdapter($adapter); ``` -#### Supported types of exceptions - -* InfluxGeneralException -* InfluxAuthorizationException (extends InfluxGeneralException) -* InfluxBadResponseException (extends InfluxGeneralException) -* InfluxNoSeriesException (extends InfluxGeneralException) -* InfluxUnexpectedResponseException (extends InfluxGeneralException) - -### Create your client with the factory method +## Create your client with the factory method Effectively the client creation is not so simple, for that reason you can you the factory method provided with the library. @@ -107,81 +127,108 @@ reason you can you the factory method provided with the library. ```php $options = [ "adapter" => [ - "name" => "InfluxDB\\Adapter\\HttpAdapter", + "name" => "InfluxDB\\Adapter\\GuzzleAdapter", "options" => [ // guzzle options ], ], "options" => [ "host" => "my.influx.domain.tld", + "db" => "mydb", + "retention_policy" => "myPolicy", + "tags" => [ + "env" => "prod", + "app" => "myApp", + ], ] ]; $client = \InfluxDB\ClientFactory::create($options); - -$client->mark("error.404", ["page" => "/a-missing-page"]); ``` -Of course you can always use the DiC or your service manager in order to create +Of course you can always use a DiC (eg `symfony/dependency-injection`) or your service manager in order to create a valid client instance. -### Time Precision write/read queries - -You can set the `time_precision` for query query - -```php -$client->mark("app.search", $points, "s"); //points contains "time" that is in seconds -``` - -```php -$client->query("select * from app.search", "s"); // retrieve points using seconds for time column -``` - ### Query InfluxDB You can query the time series database using the query method. ```php -$influx->query("select * from mine"); -$influx->query("select * from mine", "s"); // with time_precision +$influx->query('select * from "mine"'); ``` You can query the database only if the adapter is queryable (implements -`QueryableInterface`), actually `HttpAdapter`. +`QueryableInterface`), actually `GuzzleAdapter`. The adapter returns the json decoded body of the InfluxDB response, something like: ``` array(1) { - [0] => - class stdClass#1 (3) { - public $name => - string(8) "tcp.test" - public $columns => - array(3) { - [0] => - string(4) "time" - [1] => - string(15) "sequence_number" - [2] => - string(4) "mark" - } - public $points => + 'results' => + array(1) { + [0] => array(1) { - [0] => - array(3) { - [0] => - int(1410545635590) - [1] => - int(2390001) - [2] => - string(7) "element" + 'series' => + array(1) { + ... } } } } ``` +## UDP/IP support + +As you know InfluxDB support UDP/IP with a "line protocol", that is a string +line, like: + +``` +cpu,region=us-west,host=serverA,env=prod,target=servers,zone=1c cpu=18.12,free=712432 1257894000 +``` + +In order to simplify the SDK usage, you will use a single method signature +for both adapters, UDP/IP and HTTP: + +**Concise Format** + +```php +$client->mark("serie-name", [ + "power" => 124.21, + "voltage" => 12.4, +]); +``` + +**Extended Format** + +```php +$client->mark([ + "tags" => [ + "region" => "us-west", + "host" => "serverA", + "env" => "prod", + "target" => "servers", + "zone" => "1c", + ], + "time" => "2009-11-10T23:00:00Z", + "points" => [ + [ + "measurement" => "cpu", + "fields" => [ + "cpu" => 18.12, + "free" => 712432, + ], + ], + ], +]); +``` + +If you want to use the inline protocol directly you have to use the UDP/IP adapter directly + +``` +$udp = new UdpAdapter($options); +$udp->write("cpu,region=us-west,host=serverA,env=prod,target=servers,zone=1c cpu=18.12,free=712432 1257894000"); +``` + ## Database operations You can create, list or destroy databases using dedicated methods @@ -195,16 +242,57 @@ $client->deleteDatabase("my.name"); // delete an existing database with name "my Actually only queryable adapters can handle databases (implements the `QueryableInterface`) +## Global tags and retention policy + +You can set a set of default tags, that the SDK will add to your metrics: + +```php +$options = new Options(); +$options->setTags([ + "env" => "prod", + "region" => "eu-west-1", +]); +``` + +The SDK mark all point adding those tags. + +You can set a default retentionPolicy using + +``` +$options->setRetentionPolicy("myPolicy"); +``` + +In that way the SDK use that policy instead of `default` policy. + ## Benchmarks +Simple benchmarks executed on a Sony Vaio T13 (SVT1311C5E) + ### Adapters -The impact using UDP or HTTP adapters +The impact using UDP/IP or HTTP adapters ``` Corley\Benchmarks\InfluxDB\AdapterEvent Method Name Iterations Average Time Ops/second ------------------------ ------------ -------------- ------------- - sendDataUsingHttpAdapter: [1,000 ] [0.0026700308323] [374.52751] - sendDataUsingUdpAdapter : [1,000 ] [0.0000436344147] [22,917.69026] + sendDataUsingHttpAdapter: [1,000 ] [0.0162619416714] [61.49327] + sendDataUsingUdpAdapter : [1,000 ] [0.0000890662670] [11,227.59529] ``` + +### Message to inline protocol conversion + +As you know the SDK will provide a single interface in order to send data to +InfluxDB (concise or expanded). + +The impact of message to inline protocol conversion is: + +``` +Corley\Benchmarks\InfluxDB\MessageToInlineProtocolEvent + Method Name Iterations Average Time Ops/second + ---------------------------------------------------- ------------ -------------- ------------- + convertMessageToInlineProtocolWithNoTags : [10,000 ] [0.0000230122805] [43,455.05877] + convertMessageToInlineProtocolWithGlobalTags : [10,000 ] [0.0000301691532] [33,146.43911] + convertMessageToInlineProtocolWithDifferentTagLevels: [10,000 ] [0.0000327563763] [30,528.40741] +``` + diff --git a/VERSION b/VERSION index 1c09c74e2..1d0ba9ea1 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -0.3.3 +0.4.0 diff --git a/benchmarks/Corley/Benchmarks/InfluxDB/AdapterEvent.php b/benchmarks/Benchmarks/InfluxDB/AdapterEvent.php similarity index 81% rename from benchmarks/Corley/Benchmarks/InfluxDB/AdapterEvent.php rename to benchmarks/Benchmarks/InfluxDB/AdapterEvent.php index 55b418358..ba43adac0 100644 --- a/benchmarks/Corley/Benchmarks/InfluxDB/AdapterEvent.php +++ b/benchmarks/Benchmarks/InfluxDB/AdapterEvent.php @@ -17,16 +17,22 @@ class AdapterEvent extends AthleticEvent { $client = new Client(); $options = new Options(); + $options->setHost("localhost"); + $options->setPort(8086); $options->setUsername("root"); $options->setPassword("root"); - $options->setDatabase("bench"); + $options->setDatabase("tcp.test"); $client->setAdapter( new GuzzleAdapter(new HttpClient(), $options) ); $this->httpClient = $client; + $opts = new Options(); + $opts->setPort(4444); + $client = new Client(); - $client->setAdapter(new UdpAdapter(new Options())); + $client->setAdapter(new UdpAdapter($opts)); + $this->udpClient = $client; } diff --git a/benchmarks/Benchmarks/InfluxDB/MessageToInlineProtocolEvent.php b/benchmarks/Benchmarks/InfluxDB/MessageToInlineProtocolEvent.php new file mode 100644 index 000000000..4bfce6ee9 --- /dev/null +++ b/benchmarks/Benchmarks/InfluxDB/MessageToInlineProtocolEvent.php @@ -0,0 +1,92 @@ +getMethod("serialize"); + $method->setAccessible(true); + + $this->method = $method; + $this->object = $object; + } + + /** + * @iterations 10000 + */ + public function convertMessageToInlineProtocolWithNoTags() + { + $this->method->invokeArgs($this->object, [ + [ + "points" => [ + [ + "measurement" => "vm-serie", + "fields" => [ + "cpu" => 18.12, + "free" => 712423, + ], + ], + ] + ] + ]); + } + + /** + * @iterations 10000 + */ + public function convertMessageToInlineProtocolWithGlobalTags() + { + $this->method->invokeArgs($this->object, [ + [ + "tags" => [ + "dc" => "eu-west-1", + ], + "points" => [ + [ + "measurement" => "vm-serie", + "fields" => [ + "cpu" => 18.12, + "free" => 712423, + ], + ], + ] + ] + ]); + } + + /** + * @iterations 10000 + */ + public function convertMessageToInlineProtocolWithDifferentTagLevels() + { + $this->method->invokeArgs($this->object, [ + [ + "tags" => [ + "dc" => "eu-west-1", + ], + "points" => [ + [ + "measurement" => "vm-serie", + "tags" => [ + "server" => "tc12", + ], + "fields" => [ + "cpu" => 18.12, + "free" => 712423, + ], + ], + ] + ] + ]); + } +} diff --git a/benchmarks/Corley/Benchmarks/InfluxDB/FilterEvent.php b/benchmarks/Corley/Benchmarks/InfluxDB/FilterEvent.php deleted file mode 100644 index e12ebaf4d..000000000 --- a/benchmarks/Corley/Benchmarks/InfluxDB/FilterEvent.php +++ /dev/null @@ -1,111 +0,0 @@ -testData = [ - (object)[ - "name" => "test", - "columns" => [ - "time", - "sequence_number", - "value", - ], - "points" => [ - ], - ] - ]; - - $prophet = new Prophet; - $adapter = $prophet->prophesize('InfluxDB\Adapter\GuzzleAdapter'); - $adapter->query(Argument::any(), Argument::Any())->willReturn($this->testData); - - $this->withFilter = new Client(); - $this->withFilter->setAdapter($adapter->reveal()); - $this->withFilter->setFilter(new ColumnsPointsFilter()); - - $this->withoutFilter = new Client(); - $this->withoutFilter->setAdapter($adapter->reveal()); - } - - /** - * @iterations 10000 - */ - public function get10PointDirectData() - { - for ($i=0; $i<10; $i++) { - $this->testData[0]->points[] = [1985718957, 12519287519, 12589175198]; - } - - $this->withoutFilter->query("THE QUERY", "s"); - } - - /** - * @iterations 10000 - */ - public function get10PointFilteredData() - { - for ($i=0; $i<10; $i++) { - $this->testData[0]->points[] = [1985718957, 12519287519, 12589175198]; - } - $this->withFilter->query("THE QUERY", "s"); - } - - /** - * @iterations 1000 - */ - public function get100PointDirectData() - { - for ($i=0; $i<100; $i++) { - $this->testData[0]->points[] = [1985718957, 12519287519, 12589175198]; - } - - $this->withoutFilter->query("THE QUERY", "s"); - } - - /** - * @iterations 1000 - */ - public function get100PointFilteredData() - { - for ($i=0; $i<100; $i++) { - $this->testData[0]->points[] = [1985718957, 12519287519, 12589175198]; - } - $this->withFilter->query("THE QUERY", "s"); - } - - /** - * @iterations 100 - */ - public function get1000PointDirectData() - { - for ($i=0; $i<1000; $i++) { - $this->testData[0]->points[] = [1985718957, 12519287519, 12589175198]; - } - - $this->withoutFilter->query("THE QUERY", "s"); - } - - /** - * @iterations 100 - */ - public function get1000PointFilteredData() - { - for ($i=0; $i<1000; $i++) { - $this->testData[0]->points[] = [1985718957, 12519287519, 12589175198]; - } - $this->withFilter->query("THE QUERY", "s"); - } -} diff --git a/composer.json b/composer.json index c04e461c5..7c0fce5de 100644 --- a/composer.json +++ b/composer.json @@ -10,7 +10,6 @@ "zendframework/zend-servicemanager": "~2" }, "require-dev": { - "phpspec/phpspec": "2.*", "phpunit/phpunit": "4.*", "athletic/athletic": "~0.1", "ext-sockets": "*" @@ -32,11 +31,16 @@ } ], "autoload": { - "psr-0": { - "InfluxDB\\": ["./src/", "./tests"], + "psr-4": { + "InfluxDB\\": ["./src/"], "Corley\\": ["./benchmarks/"] } }, + "autoload-dev": { + "psr-4": { + "InfluxDB\\": ["./tests/"] + } + }, "suggest": { "fabpot/pimple": "Allows to prepare the client dependencies in order to require an initialized instance", "zendframework/zend-servicemanager": "Use a service locator in order to prepare a valid instance", diff --git a/composer.lock b/composer.lock index 596fdd473..805bb9737 100644 --- a/composer.lock +++ b/composer.lock @@ -4,30 +4,30 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file", "This file is @generated automatically" ], - "hash": "f2dbbf00b528de2e350ff4550629e1b4", + "hash": "96faa156d58fde5c5c3cf3df60d74ae1", "packages": [ { "name": "guzzlehttp/guzzle", - "version": "5.2.0", + "version": "5.3.0", "source": { "type": "git", "url": "https://github.com/guzzle/guzzle.git", - "reference": "475b29ccd411f2fa8a408e64576418728c032cfa" + "reference": "f3c8c22471cb55475105c14769644a49c3262b93" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/guzzle/guzzle/zipball/475b29ccd411f2fa8a408e64576418728c032cfa", - "reference": "475b29ccd411f2fa8a408e64576418728c032cfa", + "url": "https://api.github.com/repos/guzzle/guzzle/zipball/f3c8c22471cb55475105c14769644a49c3262b93", + "reference": "f3c8c22471cb55475105c14769644a49c3262b93", "shasum": "" }, "require": { - "guzzlehttp/ringphp": "~1.0", + "guzzlehttp/ringphp": "^1.1", "php": ">=5.4.0" }, "require-dev": { "ext-curl": "*", - "phpunit/phpunit": "~4.0", - "psr/log": "~1.0" + "phpunit/phpunit": "^4.0", + "psr/log": "^1.0" }, "type": "library", "extra": { @@ -62,20 +62,20 @@ "rest", "web service" ], - "time": "2015-01-28 01:03:29" + "time": "2015-05-20 03:47:55" }, { "name": "guzzlehttp/ringphp", - "version": "1.0.7", + "version": "1.1.0", "source": { "type": "git", "url": "https://github.com/guzzle/RingPHP.git", - "reference": "52d868f13570a9a56e5fce6614e0ec75d0f13ac2" + "reference": "dbbb91d7f6c191e5e405e900e3102ac7f261bc0b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/guzzle/RingPHP/zipball/52d868f13570a9a56e5fce6614e0ec75d0f13ac2", - "reference": "52d868f13570a9a56e5fce6614e0ec75d0f13ac2", + "url": "https://api.github.com/repos/guzzle/RingPHP/zipball/dbbb91d7f6c191e5e405e900e3102ac7f261bc0b", + "reference": "dbbb91d7f6c191e5e405e900e3102ac7f261bc0b", "shasum": "" }, "require": { @@ -93,7 +93,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "1.0-dev" + "dev-master": "1.1-dev" } }, "autoload": { @@ -113,7 +113,7 @@ } ], "description": "Provides a simple API and specification that abstracts away the details of HTTP into a single PHP function.", - "time": "2015-03-30 01:43:20" + "time": "2015-05-20 03:37:09" }, { "name": "guzzlehttp/streams", @@ -211,29 +211,31 @@ }, { "name": "zendframework/zend-filter", - "version": "2.4.2", + "version": "2.5.1", "source": { "type": "git", "url": "https://github.com/zendframework/zend-filter.git", - "reference": "a3711101850078b2aa69586c71897acaada2e9cb" + "reference": "93e6990a198e6cdd811064083acac4693f4b29ae" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/zendframework/zend-filter/zipball/a3711101850078b2aa69586c71897acaada2e9cb", - "reference": "a3711101850078b2aa69586c71897acaada2e9cb", + "url": "https://api.github.com/repos/zendframework/zend-filter/zipball/93e6990a198e6cdd811064083acac4693f4b29ae", + "reference": "93e6990a198e6cdd811064083acac4693f4b29ae", "shasum": "" }, "require": { "php": ">=5.3.23", - "zendframework/zend-stdlib": "self.version" + "zendframework/zend-stdlib": "~2.5" }, "require-dev": { "fabpot/php-cs-fixer": "1.7.*", "phpunit/phpunit": "~4.0", - "satooshi/php-coveralls": "dev-master", - "zendframework/zend-crypt": "self.version", - "zendframework/zend-servicemanager": "self.version", - "zendframework/zend-uri": "self.version" + "zendframework/zend-config": "~2.5", + "zendframework/zend-crypt": "~2.5", + "zendframework/zend-i18n": "~2.5", + "zendframework/zend-loader": "~2.5", + "zendframework/zend-servicemanager": "~2.5", + "zendframework/zend-uri": "~2.5" }, "suggest": { "zendframework/zend-crypt": "Zend\\Crypt component", @@ -244,8 +246,8 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "2.4-dev", - "dev-develop": "2.5-dev" + "dev-master": "2.5-dev", + "dev-develop": "2.6-dev" } }, "autoload": { @@ -263,20 +265,20 @@ "filter", "zf2" ], - "time": "2015-05-07 14:55:31" + "time": "2015-06-03 15:32:01" }, { "name": "zendframework/zend-servicemanager", - "version": "2.4.2", + "version": "2.5.1", "source": { "type": "git", "url": "https://github.com/zendframework/zend-servicemanager.git", - "reference": "855294e12771b4295c26446b6ed2df2f1785f234" + "reference": "3b22c403e351d92526c642cba0bd810bc22e1c56" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/zendframework/zend-servicemanager/zipball/855294e12771b4295c26446b6ed2df2f1785f234", - "reference": "855294e12771b4295c26446b6ed2df2f1785f234", + "url": "https://api.github.com/repos/zendframework/zend-servicemanager/zipball/3b22c403e351d92526c642cba0bd810bc22e1c56", + "reference": "3b22c403e351d92526c642cba0bd810bc22e1c56", "shasum": "" }, "require": { @@ -285,8 +287,8 @@ "require-dev": { "fabpot/php-cs-fixer": "1.7.*", "phpunit/phpunit": "~4.0", - "satooshi/php-coveralls": "dev-master", - "zendframework/zend-di": "self.version" + "zendframework/zend-di": "~2.5", + "zendframework/zend-mvc": "~2.5" }, "suggest": { "ocramius/proxy-manager": "ProxyManager 0.5.* to handle lazy initialization of services", @@ -295,8 +297,8 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "2.4-dev", - "dev-develop": "2.5-dev" + "dev-master": "2.5-dev", + "dev-develop": "2.6-dev" } }, "autoload": { @@ -308,25 +310,25 @@ "license": [ "BSD-3-Clause" ], - "homepage": "https://github.com/zendframework/zend-service-manager", + "homepage": "https://github.com/zendframework/zend-servicemanager", "keywords": [ "servicemanager", "zf2" ], - "time": "2015-05-07 14:55:31" + "time": "2015-06-03 15:32:02" }, { "name": "zendframework/zend-stdlib", - "version": "2.4.2", + "version": "2.5.1", "source": { "type": "git", "url": "https://github.com/zendframework/zend-stdlib.git", - "reference": "a5dd7fd2ba6e8f6c6ea5a12db0605d3aa48af1e7" + "reference": "cc8e90a60dd5d44b9730b77d07b97550091da1ae" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/zendframework/zend-stdlib/zipball/a5dd7fd2ba6e8f6c6ea5a12db0605d3aa48af1e7", - "reference": "a5dd7fd2ba6e8f6c6ea5a12db0605d3aa48af1e7", + "url": "https://api.github.com/repos/zendframework/zend-stdlib/zipball/cc8e90a60dd5d44b9730b77d07b97550091da1ae", + "reference": "cc8e90a60dd5d44b9730b77d07b97550091da1ae", "shasum": "" }, "require": { @@ -335,11 +337,12 @@ "require-dev": { "fabpot/php-cs-fixer": "1.7.*", "phpunit/phpunit": "~4.0", - "satooshi/php-coveralls": "dev-master", - "zendframework/zend-eventmanager": "self.version", - "zendframework/zend-filter": "self.version", - "zendframework/zend-serializer": "self.version", - "zendframework/zend-servicemanager": "self.version" + "zendframework/zend-config": "~2.5", + "zendframework/zend-eventmanager": "~2.5", + "zendframework/zend-filter": "~2.5", + "zendframework/zend-inputfilter": "~2.5", + "zendframework/zend-serializer": "~2.5", + "zendframework/zend-servicemanager": "~2.5" }, "suggest": { "zendframework/zend-eventmanager": "To support aggregate hydrator usage", @@ -350,8 +353,8 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "2.4-dev", - "dev-develop": "2.5-dev" + "dev-master": "2.5-dev", + "dev-develop": "2.6-dev" } }, "autoload": { @@ -368,7 +371,7 @@ "stdlib", "zf2" ], - "time": "2015-05-07 14:55:31" + "time": "2015-06-03 15:32:03" } ], "packages-dev": [ @@ -620,118 +623,6 @@ ], "time": "2015-02-03 12:10:50" }, - { - "name": "phpspec/php-diff", - "version": "v1.0.2", - "source": { - "type": "git", - "url": "https://github.com/phpspec/php-diff.git", - "reference": "30e103d19519fe678ae64a60d77884ef3d71b28a" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/phpspec/php-diff/zipball/30e103d19519fe678ae64a60d77884ef3d71b28a", - "reference": "30e103d19519fe678ae64a60d77884ef3d71b28a", - "shasum": "" - }, - "type": "library", - "autoload": { - "psr-0": { - "Diff": "lib/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Chris Boulton", - "homepage": "http://github.com/chrisboulton", - "role": "Original developer" - } - ], - "description": "A comprehensive library for generating differences between two hashable objects (strings or arrays).", - "time": "2013-11-01 13:02:21" - }, - { - "name": "phpspec/phpspec", - "version": "2.2.0", - "source": { - "type": "git", - "url": "https://github.com/phpspec/phpspec.git", - "reference": "9727d75919a00455433e867565bc022f0b985a39" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/phpspec/phpspec/zipball/9727d75919a00455433e867565bc022f0b985a39", - "reference": "9727d75919a00455433e867565bc022f0b985a39", - "shasum": "" - }, - "require": { - "doctrine/instantiator": "^1.0.1", - "php": ">=5.3.3", - "phpspec/php-diff": "~1.0.0", - "phpspec/prophecy": "~1.4", - "sebastian/exporter": "~1.0", - "symfony/console": "~2.3", - "symfony/event-dispatcher": "~2.1", - "symfony/finder": "~2.1", - "symfony/process": "~2.1", - "symfony/yaml": "~2.1" - }, - "require-dev": { - "behat/behat": "^3.0.11", - "bossa/phpspec2-expect": "~1.0", - "phpunit/phpunit": "~4.4", - "symfony/filesystem": "~2.1", - "symfony/process": "~2.1" - }, - "suggest": { - "phpspec/nyan-formatters": "~1.0 – Adds Nyan formatters" - }, - "bin": [ - "bin/phpspec" - ], - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "2.2.x-dev" - } - }, - "autoload": { - "psr-0": { - "PhpSpec": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Konstantin Kudryashov", - "email": "ever.zet@gmail.com", - "homepage": "http://everzet.com" - }, - { - "name": "Marcello Duarte", - "homepage": "http://marcelloduarte.net/" - } - ], - "description": "Specification-oriented BDD framework for PHP 5.3+", - "homepage": "http://phpspec.net/", - "keywords": [ - "BDD", - "SpecBDD", - "TDD", - "spec", - "specification", - "testing", - "tests" - ], - "time": "2015-04-18 16:22:51" - }, { "name": "phpspec/prophecy", "version": "v1.4.1", @@ -794,16 +685,16 @@ }, { "name": "phpunit/php-code-coverage", - "version": "2.0.16", + "version": "2.1.3", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-code-coverage.git", - "reference": "934fd03eb6840508231a7f73eb8940cf32c3b66c" + "reference": "28a6b34e91d789b2608072ab3c82eaae7cdb973c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/934fd03eb6840508231a7f73eb8940cf32c3b66c", - "reference": "934fd03eb6840508231a7f73eb8940cf32c3b66c", + "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/28a6b34e91d789b2608072ab3c82eaae7cdb973c", + "reference": "28a6b34e91d789b2608072ab3c82eaae7cdb973c", "shasum": "" }, "require": { @@ -826,7 +717,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "2.0.x-dev" + "dev-master": "2.1.x-dev" } }, "autoload": { @@ -852,7 +743,7 @@ "testing", "xunit" ], - "time": "2015-04-11 04:35:00" + "time": "2015-06-03 07:01:01" }, { "name": "phpunit/php-file-iterator", @@ -1040,16 +931,16 @@ }, { "name": "phpunit/phpunit", - "version": "4.6.6", + "version": "4.6.10", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/phpunit.git", - "reference": "3afe303d873a4d64c62ef84de491b97b006fbdac" + "reference": "7b5fe98b28302a8b25693b2298bca74463336975" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/3afe303d873a4d64c62ef84de491b97b006fbdac", - "reference": "3afe303d873a4d64c62ef84de491b97b006fbdac", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/7b5fe98b28302a8b25693b2298bca74463336975", + "reference": "7b5fe98b28302a8b25693b2298bca74463336975", "shasum": "" }, "require": { @@ -1108,20 +999,20 @@ "testing", "xunit" ], - "time": "2015-04-29 15:18:52" + "time": "2015-06-03 05:03:30" }, { "name": "phpunit/phpunit-mock-objects", - "version": "2.3.1", + "version": "2.3.3", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/phpunit-mock-objects.git", - "reference": "74ffb87f527f24616f72460e54b595f508dccb5c" + "reference": "253c005852591fd547fc18cd5b7b43a1ec82d8f7" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/phpunit-mock-objects/zipball/74ffb87f527f24616f72460e54b595f508dccb5c", - "reference": "74ffb87f527f24616f72460e54b595f508dccb5c", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit-mock-objects/zipball/253c005852591fd547fc18cd5b7b43a1ec82d8f7", + "reference": "253c005852591fd547fc18cd5b7b43a1ec82d8f7", "shasum": "" }, "require": { @@ -1163,7 +1054,7 @@ "mock", "xunit" ], - "time": "2015-04-02 05:36:41" + "time": "2015-05-29 05:19:18" }, { "name": "pimple/pimple", @@ -1582,240 +1473,22 @@ "homepage": "https://github.com/sebastianbergmann/version", "time": "2015-02-24 06:35:25" }, - { - "name": "symfony/console", - "version": "v2.6.7", - "target-dir": "Symfony/Component/Console", - "source": { - "type": "git", - "url": "https://github.com/symfony/Console.git", - "reference": "ebc5679854aa24ed7d65062e9e3ab0b18a917272" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/Console/zipball/ebc5679854aa24ed7d65062e9e3ab0b18a917272", - "reference": "ebc5679854aa24ed7d65062e9e3ab0b18a917272", - "shasum": "" - }, - "require": { - "php": ">=5.3.3" - }, - "require-dev": { - "psr/log": "~1.0", - "symfony/event-dispatcher": "~2.1", - "symfony/phpunit-bridge": "~2.7", - "symfony/process": "~2.1" - }, - "suggest": { - "psr/log": "For using the console logger", - "symfony/event-dispatcher": "", - "symfony/process": "" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "2.6-dev" - } - }, - "autoload": { - "psr-0": { - "Symfony\\Component\\Console\\": "" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Symfony Console Component", - "homepage": "https://symfony.com", - "time": "2015-05-02 15:18:45" - }, - { - "name": "symfony/event-dispatcher", - "version": "v2.6.7", - "target-dir": "Symfony/Component/EventDispatcher", - "source": { - "type": "git", - "url": "https://github.com/symfony/EventDispatcher.git", - "reference": "672593bc4b0043a0acf91903bb75a1c82d8f2e02" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/EventDispatcher/zipball/672593bc4b0043a0acf91903bb75a1c82d8f2e02", - "reference": "672593bc4b0043a0acf91903bb75a1c82d8f2e02", - "shasum": "" - }, - "require": { - "php": ">=5.3.3" - }, - "require-dev": { - "psr/log": "~1.0", - "symfony/config": "~2.0,>=2.0.5", - "symfony/dependency-injection": "~2.6", - "symfony/expression-language": "~2.6", - "symfony/phpunit-bridge": "~2.7", - "symfony/stopwatch": "~2.3" - }, - "suggest": { - "symfony/dependency-injection": "", - "symfony/http-kernel": "" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "2.6-dev" - } - }, - "autoload": { - "psr-0": { - "Symfony\\Component\\EventDispatcher\\": "" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Symfony EventDispatcher Component", - "homepage": "https://symfony.com", - "time": "2015-05-02 15:18:45" - }, - { - "name": "symfony/finder", - "version": "v2.6.7", - "target-dir": "Symfony/Component/Finder", - "source": { - "type": "git", - "url": "https://github.com/symfony/Finder.git", - "reference": "704c64c8b12c8882640d5c0330a8414b1e06dc99" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/Finder/zipball/704c64c8b12c8882640d5c0330a8414b1e06dc99", - "reference": "704c64c8b12c8882640d5c0330a8414b1e06dc99", - "shasum": "" - }, - "require": { - "php": ">=5.3.3" - }, - "require-dev": { - "symfony/phpunit-bridge": "~2.7" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "2.6-dev" - } - }, - "autoload": { - "psr-0": { - "Symfony\\Component\\Finder\\": "" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Symfony Finder Component", - "homepage": "https://symfony.com", - "time": "2015-05-02 15:18:45" - }, - { - "name": "symfony/process", - "version": "v2.6.7", - "target-dir": "Symfony/Component/Process", - "source": { - "type": "git", - "url": "https://github.com/symfony/Process.git", - "reference": "9f3c4baaf840ed849e1b1f7bfd5ae246e8509562" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/Process/zipball/9f3c4baaf840ed849e1b1f7bfd5ae246e8509562", - "reference": "9f3c4baaf840ed849e1b1f7bfd5ae246e8509562", - "shasum": "" - }, - "require": { - "php": ">=5.3.3" - }, - "require-dev": { - "symfony/phpunit-bridge": "~2.7" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "2.6-dev" - } - }, - "autoload": { - "psr-0": { - "Symfony\\Component\\Process\\": "" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Symfony Process Component", - "homepage": "https://symfony.com", - "time": "2015-05-02 15:18:45" - }, { "name": "symfony/yaml", - "version": "v2.6.7", - "target-dir": "Symfony/Component/Yaml", + "version": "v2.7.0", "source": { "type": "git", "url": "https://github.com/symfony/Yaml.git", - "reference": "f157ab074e453ecd4c0fa775f721f6e67a99d9e2" + "reference": "4a29a5248aed4fb45f626a7bbbd330291492f5c3" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/Yaml/zipball/f157ab074e453ecd4c0fa775f721f6e67a99d9e2", - "reference": "f157ab074e453ecd4c0fa775f721f6e67a99d9e2", + "url": "https://api.github.com/repos/symfony/Yaml/zipball/4a29a5248aed4fb45f626a7bbbd330291492f5c3", + "reference": "4a29a5248aed4fb45f626a7bbbd330291492f5c3", "shasum": "" }, "require": { - "php": ">=5.3.3" + "php": ">=5.3.9" }, "require-dev": { "symfony/phpunit-bridge": "~2.7" @@ -1823,11 +1496,11 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "2.6-dev" + "dev-master": "2.7-dev" } }, "autoload": { - "psr-0": { + "psr-4": { "Symfony\\Component\\Yaml\\": "" } }, @@ -1847,7 +1520,7 @@ ], "description": "Symfony Yaml Component", "homepage": "https://symfony.com", - "time": "2015-05-02 15:18:45" + "time": "2015-05-02 15:21:08" }, { "name": "zeptech/annotations", diff --git a/phpunit.xml.dist b/phpunit.xml.dist index 2b12f4ecb..64303a46a 100644 --- a/phpunit.xml.dist +++ b/phpunit.xml.dist @@ -1,7 +1,6 @@ - + diff --git a/scripts/influxdb_conf.toml b/scripts/influxdb_conf.toml index 4c946e0b3..9c2568114 100644 --- a/scripts/influxdb_conf.toml +++ b/scripts/influxdb_conf.toml @@ -1,187 +1,74 @@ -# Welcome to the InfluxDB configuration file. +[meta] + dir = "/var/opt/influxdb/meta" + hostname = "localhost" + bind-address = ":8088" + retention-autocreate = true + election-timeout = "1s" + heartbeat-timeout = "1s" + leader-lease-timeout = "500ms" + commit-timeout = "50ms" -# If hostname (on the OS) doesn't return a name that can be resolved by the other -# systems in the cluster, you'll have to set the hostname to an IP or something -# that can be resolved here. -# hostname = "" - -bind-address = "0.0.0.0" - -# Once every 24 hours InfluxDB will report anonymous data to m.influxdb.com -# The data includes raft name (random 8 bytes), os, arch and version -# We don't track ip addresses of servers reporting. This is only used -# to track the number of instances running and the versions which -# is very helpful for us. -# Change this option to true to disable reporting. -reporting-disabled = false - -[logging] -# logging level can be one of "debug", "info", "warn" or "error" -level = "info" -file = "/opt/influxdb/shared/log.txt" # stdout to log to standard out - -# Configure the admin server -[admin] -port = 8083 # binding is disabled if the port isn't set -assets = "/opt/influxdb/current/admin" - -# Configure the http api -[api] -port = 8086 # binding is disabled if the port isn't set -# ssl-port = 8084 # Ssl support is enabled if you set a port and cert -# ssl-cert = /path/to/cert.pem - -# connections will timeout after this amount of time. Ensures that clients that misbehave -# and keep alive connections they don't use won't end up connection a million times. -# However, if a request is taking longer than this to complete, could be a problem. -read-timeout = "5s" - -[input_plugins] - - # Configure the graphite api - [input_plugins.graphite] - enabled = false - # port = 2003 - # database = "" # store graphite data in this database - # udp_enabled = true # enable udp interface on the same port as the tcp interface - - # Configure the udp api - #[input_plugins.udp] - #enabled = true - #port = 4444 - # database = "" - - # Configure multiple udp apis each can write to separate db. Just - # repeat the following section to enable multiple udp apis on - # different ports. - [[input_plugins.udp_servers]] # array of tables - enabled = true - port = 5551 - database = "udp.test" - -# Raft configuration -[raft] -# The raft port should be open between all servers in a cluster. -# However, this port shouldn't be accessible from the internet. - -port = 8090 - -# Where the raft logs are stored. The user running InfluxDB will need read/write access. -dir = "/opt/influxdb/shared/data/raft" - -# election-timeout = "1s" - -[storage] - -dir = "/opt/influxdb/shared/data/db" -# How many requests to potentially buffer in memory. If the buffer gets filled then writes -# will still be logged and once the local storage has caught up (or compacted) the writes -# will be replayed from the WAL -write-buffer-size = 10000 - -# the engine to use for new shards, old shards will continue to use the same engine -default-engine = "rocksdb" - -# The default setting on this is 0, which means unlimited. Set this to something if you want to -# limit the max number of open files. max-open-files is per shard so this * that will be max. -max-open-shards = 0 - -# The default setting is 100. This option tells how many points will be fetched from LevelDb before -# they get flushed into backend. -point-batch-size = 100 - -# The number of points to batch in memory before writing them to leveldb. Lowering this number will -# reduce the memory usage, but will result in slower writes. -write-batch-size = 5000000 - -# The server will check this often for shards that have expired that should be cleared. -retention-sweep-period = "10m" - -[storage.engines.leveldb] - -# Maximum mmap open files, this will affect the virtual memory used by -# the process -max-open-files = 1000 - -# LRU cache size, LRU is used by leveldb to store contents of the -# uncompressed sstables. You can use `m` or `g` prefix for megabytes -# and gigabytes, respectively. -lru-cache-size = "200m" - -[storage.engines.rocksdb] - -# Maximum mmap open files, this will affect the virtual memory used by -# the process -max-open-files = 1000 - -# LRU cache size, LRU is used by rocksdb to store contents of the -# uncompressed sstables. You can use `m` or `g` prefix for megabytes -# and gigabytes, respectively. -lru-cache-size = "200m" - -[storage.engines.hyperleveldb] - -# Maximum mmap open files, this will affect the virtual memory used by -# the process -max-open-files = 1000 - -# LRU cache size, LRU is used by rocksdb to store contents of the -# uncompressed sstables. You can use `m` or `g` prefix for megabytes -# and gigabytes, respectively. -lru-cache-size = "200m" - -[storage.engines.lmdb] - -map-size = "100g" +[data] + dir = "/var/opt/influxdb/data" + retention-auto-create = true + retention-check-enabled = true + retention-check-period = "10m0s" + retention-create-period = "45m0s" [cluster] -# A comma separated list of servers to seed -# this server. this is only relevant when the -# server is joining a new cluster. Otherwise -# the server will use the list of known servers -# prior to shutting down. Any server can be pointed to -# as a seed. It will find the Raft leader automatically. + shard-writer-timeout = "5s" -# Here's an example. Note that the port on the host is the same as the raft port. -# seed-servers = ["hosta:8090","hostb:8090"] +[retention] + enabled = true + check-interval = "10m0s" -# Replication happens over a TCP connection with a Protobuf protocol. -# This port should be reachable between all servers in a cluster. -# However, this port shouldn't be accessible from the internet. +[admin] + enabled = true + bind-address = ":8083" -protobuf_port = 8099 -protobuf_timeout = "2s" # the write timeout on the protobuf conn any duration parseable by time.ParseDuration -protobuf_heartbeat = "200ms" # the heartbeat interval between the servers. must be parseable by time.ParseDuration -protobuf_min_backoff = "1s" # the minimum backoff after a failed heartbeat attempt -protobuf_max_backoff = "10s" # the maxmimum backoff after a failed heartbeat attempt +[http] + enabled = true + bind-address = ":8086" + auth-enabled = false + log-enabled = true + write-tracing = false + pprof-enabled = false -# How many write requests to potentially buffer in memory per server. If the buffer gets filled then writes -# will still be logged and once the server has caught up (or come back online) the writes -# will be replayed from the WAL -write-buffer-size = 1000 +[collectd] + enabled = false + bind-address = "" + database = "" + typesdb = "" -# the maximum number of responses to buffer from remote nodes, if the -# expected number of responses exceed this number then querying will -# happen sequentially and the buffer size will be limited to this -# number -max-response-buffer-size = 100 +[opentsdb] + enabled = false + bind-address = "" + database = "" + retention-policy = "" -# When queries get distributed out to shards, they go in parallel. This means that results can get buffered -# in memory since results will come in any order, but have to be processed in the correct time order. -# Setting this higher will give better performance, but you'll need more memory. Setting this to 1 will ensure -# that you don't need to buffer in memory, but you won't get the best performance. -concurrent-shard-query-limit = 10 +[udp] + enabled = true + bind-address = ":4444" + database = "udp.test" + batch-size = 0 + batch-timeout = "10ns" -[wal] +[monitoring] + enabled = false + write-interval = "1m0s" -dir = "/opt/influxdb/shared/data/wal" -flush-after = 1000 # the number of writes after which wal will be flushed, 0 for flushing on every write -bookmark-after = 1000 # the number of writes after which a bookmark will be created +[continuous_queries] + enabled = true + recompute-previous-n = 2 + recompute-no-older-than = "10m0s" + compute-runs-per-interval = 10 + compute-no-more-than = "2m0s" -# the number of writes after which an index entry is created pointing -# to the offset of the first request, default to 1k -index-after = 1000 +[hinted-handoff] + enabled = true + dir = "/var/opt/influxdb/hh" + max-size = 1073741824 + max-age = "168h0m0s" + retry-rate-limit = 0 + retry-interval = "1s" -# the number of requests per one log file, if new requests came in a -# new log file will be created -requests-per-logfile = 10000 diff --git a/spec/InfluxDB/Adapter/GuzzleAdapterSpec.php b/spec/InfluxDB/Adapter/GuzzleAdapterSpec.php deleted file mode 100644 index 815fa87a7..000000000 --- a/spec/InfluxDB/Adapter/GuzzleAdapterSpec.php +++ /dev/null @@ -1,90 +0,0 @@ -getHttpSeriesEndpoint()->willReturn("localhost"); - $options->getHttpDatabaseEndpoint()->willReturn("localhost"); - $options->getUsername()->willReturn("one"); - $options->getPassword()->willReturn("two"); - $this->beConstructedWith($client, $options); - } - - function it_is_initializable() - { - $this->shouldHaveType('InfluxDB\Adapter\GuzzleAdapter'); - } - - function it_should_send_data_via_post(Client $client, Options $options) - { - $client->post("localhost", [ - 'auth' => ["one", "two"], - 'body' => json_encode(['pippo']) - ])->shouldBeCalledTimes(1); - - $this->send(["pippo"]); - } - - function it_should_query_data(Client $client, Options $options) - { - $client->get( - "localhost", - [ - "auth" => ["one", "two"], - "query" => [ - "q" => "select * from tcp.test", - ] - ] - )->willReturn(new Response(200,[],null)); - $this->query("select * from tcp.test")->shouldReturn(null); - } - - function it_should_query_data_with_time_precision(Client $client, Options $options) - { - $client->get( - "localhost", - [ - "auth" => ["one", "two"], - "query" => [ - "time_precision" => "s", - "q" => "select * from tcp.test", - ] - ] - )->willReturn(new Response(200, [], null)); - $this->query("select * from tcp.test", "s")->shouldReturn(null); - } - - function it_should_list_all_databases(Client $client, Options $options) - { - $client->get( - "localhost", - [ - "auth" => ["one", "two"] - ] - )->shouldBeCalledTimes(1)->willReturn(new Response(200, [], null)); - - $this->getDatabases()->shouldReturn(null); - } - - function it_should_create_a_new_database(Client $client, Options $options) - { - $client->post( - "localhost", - [ - "auth" => ["one", "two"], - "body" => json_encode(["name" => "db_name"]) - ] - )->shouldBeCalledTimes(1)->willReturn(new Response(200, [], null)); - - $this->createDatabase("db_name")->shouldReturn(null); - } -} diff --git a/spec/InfluxDB/Adapter/HttpAdapterSpec.php b/spec/InfluxDB/Adapter/HttpAdapterSpec.php deleted file mode 100755 index fac255668..000000000 --- a/spec/InfluxDB/Adapter/HttpAdapterSpec.php +++ /dev/null @@ -1,194 +0,0 @@ -shouldHaveType('InfluxDB\Adapter\HttpAdapter'); - } - - function let(Options $options, Client $client) - { - $options->getHttpSeriesEndpoint()->willReturn("localhost"); - $options->getHttpDatabaseEndpoint()->willReturn("localhost"); - $options->getUsername()->willReturn("one"); - $options->getPassword()->willReturn("two"); - $this->beConstructedWith($options, $client); - } - - function it_should_send_data_via_post(Client $client) - { - $responseBody = ['key'=>'value']; - $response = new Response(200,[], Stream::factory(json_encode($responseBody))); - $client->post("localhost", [ - 'auth' => ["one", "two"], - 'exceptions' => false, - 'body' => json_encode(['pippo']) - ])->willReturn($response) - ->shouldBeCalledTimes(1); - $this->send(["pippo"])->shouldReturn($responseBody); - } - - function it_should_query_data(Client $client, Options $options) - { - $client->get( - "localhost", - [ - "auth" => ["one", "two"], - "exceptions" => false, - "query" => [ - "q" => "select * from tcp.test", - ] - ] - )->willReturn(new Response(200,[],null)); - $this->query("select * from tcp.test")->shouldReturn(null); - } - - function it_should_query_data_with_time_precision(Client $client, Options $options) - { - $client->get( - "localhost", - [ - "auth" => ["one", "two"], - "exceptions" => false, - "query" => [ - "time_precision" => "s", - "q" => "select * from tcp.test", - ] - ] - )->willReturn(new Response(200, [], null)); - $this->query("select * from tcp.test", "s")->shouldReturn(null); - } - - function it_should_list_all_databases(Client $client, Options $options) - { - $client->get( - "localhost", - [ - "auth" => ["one", "two"], - "exceptions" => false, - ] - )->shouldBeCalledTimes(1)->willReturn(new Response(200, [], null)); - - $this->getDatabases()->shouldReturn(null); - } - - function it_should_create_a_new_database(Client $client, Options $options) - { - $client->post( - "localhost", - [ - "auth" => ["one", "two"], - "exceptions" => false, - "body" => json_encode(["name" => "db_name"]) - ] - )->shouldBeCalledTimes(1)->willReturn(new Response(201, [], null)); - - $this->createDatabase("db_name")->shouldReturn(true); - } - - function it_should_return_true_with_success(Client $client) { - foreach ([201,204,299] as $code) { - $client->post(Argument::any(), Argument::any(), Argument::any())->willReturn(new Response($code, [], null)); - - $this->createDatabase("db_name")->shouldReturn(true); - } - } - - - - function it_should_throw_no_series_exception (Client $client) - { - $client->get( - "localhost", - [ - "auth" => ["one", "two"], - "exceptions" => false, - "query" => [ - "q" => "select * from tcp.test", - ] - ] - )->willReturn(new Response(HttpAdapter::STATUS_CODE_BAD_REQUEST,[], Stream::factory("Couldn't find series: tcp.test"))); - $this->shouldThrow(new InfluxNoSeriesException("Couldn't find series: tcp.test", HttpAdapter::STATUS_CODE_BAD_REQUEST)) - ->during("query", ["select * from tcp.test"]); - } - - function it_should_throw_authorization_exception (Client $client) - { - $codes = [HttpAdapter::STATUS_CODE_UNAUTHORIZED, HttpAdapter::STATUS_CODE_FORBIDDEN]; - foreach ($codes as $code) { - $client->get( - "localhost", - [ - "auth" => ["one", "two"], - "exceptions" => false, - "query" => [ - "q" => "select * from tcp.test", - ] - ] - )->willReturn(new Response($code,[], Stream::factory("Message"))); - $this->shouldThrow(new InfluxAuthorizationException("Message", $code)) - ->during("query", ["select * from tcp.test"]); - } - } - - function it_should_throw_general_exception (Client $client) - { - $client->get( - "localhost", - [ - "auth" => ["one", "two"], - "exceptions" => false, - "query" => [ - "q" => "select * from tcp.test", - ] - ] - )->willReturn(new Response(409,[], Stream::factory("Message"))); - $this->shouldThrow(new InfluxGeneralException("Message", 409)) - ->during("query", ["select * from tcp.test"]); - } - - function it_should_throw_general_exception_with_default_message (Client $client) - { - $client->get(Argument::any(), Argument::any())->willReturn(new Response(409)); - $this->shouldThrow(new InfluxGeneralException("Conflict", 409)) - ->during("query", ["select * from tcp.test"]); - } - - function it_should_throw_bad_response_exception(Client $client) - { - $response = new Response(200,[], Stream::factory('bad response')); - $client->post("localhost", [ - 'auth' => ["one", "two"], - 'exceptions' => false, - 'body' => json_encode(['pippo']) - ])->willReturn($response) - ->shouldBeCalledTimes(1); - $this->shouldThrow(new InfluxBadResponseException("Unable to parse JSON data: JSON_ERROR_SYNTAX - Syntax error, malformed JSON; Response is 'bad response'", 0)) - ->during("send", [["pippo"]]); - } - - function it_should_throw_unexpected_response_exception (Client $client) - { - foreach ([0, 300, 500] as $code) { - $client->get(Argument::any(), Argument::any())->willReturn(new Response($code, [], Stream::factory("Message"))); - $this->shouldThrow(new InfluxUnexpectedResponseException("Message", $code)) - ->during("query", ["select * from tcp.test"]); - } - } -} diff --git a/spec/InfluxDB/Adapter/UdpAdapterSpec.php b/spec/InfluxDB/Adapter/UdpAdapterSpec.php deleted file mode 100644 index 48e14198f..000000000 --- a/spec/InfluxDB/Adapter/UdpAdapterSpec.php +++ /dev/null @@ -1,25 +0,0 @@ -beConstructedWith($options); - } - - function it_is_initializable() - { - $this->shouldHaveType('InfluxDB\Adapter\UdpAdapter'); - } - - function it_should_implement_adapter_interface() - { - $this->shouldImplement("InfluxDB\Adapter\AdapterInterface"); - } -} diff --git a/spec/InfluxDB/ClientSpec.php b/spec/InfluxDB/ClientSpec.php deleted file mode 100644 index 84e5753db..000000000 --- a/spec/InfluxDB/ClientSpec.php +++ /dev/null @@ -1,86 +0,0 @@ -setAdapter($adapter); - } - - function it_is_initializable() - { - $this->shouldHaveType('InfluxDB\Client'); - } - - function it_should_send_data(AdapterInterface $adapter) - { - $adapter->send([[ - "name" => "video.search", - "columns" => ["author", "title"], - "points" => [ - ["Guccini", "Autogrill"] - ] - ]], false)->shouldBeCalledTimes(1); - - $this->mark("video.search", [ - "author" => "Guccini", - "title" => "Autogrill" - ]); - } - - function it_should_send_data_with_time_precision(AdapterInterface $adapter) - { - $adapter->send([[ - "name" => "video.search", - "columns" => ["time", "author", "title"], - "points" => [ - ["1410591552", "Guccini", "Autogrill"] - ] - ]], "s")->shouldBeCalledTimes(1); - - $this->mark("video.search", [ - "time" => "1410591552", - "author" => "Guccini", - "title" => "Autogrill" - ], "s"); - } - - function it_should_query_on_querable_adapter(GuzzleAdapter $adapter) - { - $this->setAdapter($adapter); - $adapter->query("select * from tcp.test", false)->willReturn([]); - - $this->query("select * from tcp.test")->shouldReturn([]); - } - - function it_should_query_with_time_precision(GuzzleAdapter $adapter) - { - $this->setAdapter($adapter); - $adapter->query("select * from tcp.test", "s")->willReturn([]); - - $this->query("select * from tcp.test", "s")->shouldReturn([]); - } - - function it_should_query_but_skip_invalid_time_precision(GuzzleAdapter $adapter) - { - $this->setAdapter($adapter); - $adapter->query("select * from tcp.test", false)->willReturn([]); - - $this->query("select * from tcp.test", "r")->shouldReturn([]); - } - - function it_should_thrown_an_exception_on_unquerable_adapter(UdpAdapter $adapter) - { - $this->setAdapter($adapter); - - $this->shouldThrow("\\BadMethodCallException")->duringQuery("select * from tcp.test"); - } -} diff --git a/spec/InfluxDB/OptionsSpec.php b/spec/InfluxDB/OptionsSpec.php deleted file mode 100644 index d926faf83..000000000 --- a/spec/InfluxDB/OptionsSpec.php +++ /dev/null @@ -1,40 +0,0 @@ -shouldHaveType('InfluxDB\Options'); - } - - function it_should_create_a_valid_tcp_endpoint() - { - $this->setDatabase("mine"); - $this->getHttpSeriesEndpoint() - ->shouldReturn("http://localhost:8086/db/mine/series"); - } - - function it_should_allows_option_override_for_tcp_endpoint() - { - $this->setHost("influx.1.prod.tld"); - $this->setPort(19385); - $this->setUsername("walter"); - $this->setPassword("walter"); - $this->setDatabase("me"); - $this->getHttpSeriesEndpoint() - ->shouldReturn("http://influx.1.prod.tld:19385/db/me/series"); - } - - function it_should_allows_https_for_tcp_endpoint() - { - $this->setProtocol("https"); - $this->setDatabase("me"); - $this->getHttpSeriesEndpoint() - ->shouldReturn("https://localhost:8086/db/me/series"); - } -} diff --git a/src/Adapter/AdapterAbstract.php b/src/Adapter/AdapterAbstract.php new file mode 100644 index 000000000..b03d47681 --- /dev/null +++ b/src/Adapter/AdapterAbstract.php @@ -0,0 +1,36 @@ +options = $options; + } + + /** + * @return Options + */ + public function getOptions() + { + return $this->options; + } + + protected function getMessageDefaults() + { + return [ + "database" => $this->getOptions()->getDatabase(), + "retentionPolicy" => $this->getOptions()->getRetentionPolicy(), + "tags" => $this->getOptions()->getTags(), + ]; + } + + abstract public function send(array $message); +} diff --git a/src/InfluxDB/Adapter/AdapterInterface.php b/src/Adapter/AdapterInterface.php similarity index 80% rename from src/InfluxDB/Adapter/AdapterInterface.php rename to src/Adapter/AdapterInterface.php index 73d1b2fe5..23bdf7a68 100644 --- a/src/InfluxDB/Adapter/AdapterInterface.php +++ b/src/Adapter/AdapterInterface.php @@ -11,5 +11,5 @@ interface AdapterInterface * @param mixed $message * @param string|boolean $timePrecision */ - public function send($message, $timePrecision = false); + public function send(array $message); } diff --git a/src/Adapter/GuzzleAdapter.php b/src/Adapter/GuzzleAdapter.php new file mode 100644 index 000000000..96b861158 --- /dev/null +++ b/src/Adapter/GuzzleAdapter.php @@ -0,0 +1,59 @@ +httpClient = $httpClient; + } + + public function send(array $message) + { + $message = array_replace_recursive($this->getMessageDefaults(), $message); + + if (!count($message["tags"])) { + unset($message["tags"]); + } + + $httpMessage = [ + "auth" => [$this->getOptions()->getUsername(), $this->getOptions()->getPassword()], + "body" => json_encode($message) + ]; + + $endpoint = $this->getOptions()->getHttpSeriesEndpoint(); + return $this->httpClient->post($endpoint, $httpMessage); + } + + public function query($query) + { + $options = [ + "auth" => [$this->getOptions()->getUsername(), $this->getOptions()->getPassword()], + 'query' => [ + "q" => $query, + "db" => $this->getOptions()->getDatabase(), + ] + ]; + + return $this->get($options); + } + + private function get(array $httpMessage) + { + $endpoint = $this->getOptions()->getHttpQueryEndpoint(); + return $this->httpClient->get($endpoint, $httpMessage)->json(); + } +} diff --git a/src/Adapter/QueryableInterface.php b/src/Adapter/QueryableInterface.php new file mode 100644 index 000000000..9ce4440dc --- /dev/null +++ b/src/Adapter/QueryableInterface.php @@ -0,0 +1,7 @@ +getMessageDefaults(), $message); + $message = $this->serialize($message); + + $this->write($message); + } + + public function write($message) + { + $socket = socket_create(AF_INET, SOCK_DGRAM, SOL_UDP); + socket_sendto($socket, $message, strlen($message), 0, $this->getOptions()->getHost(), $this->getOptions()->getPort()); + socket_close($socket); + } + + private function serialize(array $message) + { + $tags = $this->getOptions()->getTags(); + + if (array_key_exists("tags", $message)) { + $tags = array_replace_recursive($tags, $message["tags"]); + } + + $now = new DateTime(); + $unixepoch = (int)($now->format("U") * 1e9); + if (array_key_exists("time", $message)) { + $dt = new DateTime($message["time"]); + $unixepoch = (int)($dt->format("U") * 1e9); + } + + $lines = []; + foreach ($message["points"] as $point) { + if (array_key_exists("tags", $point)) { + $tags = array_replace_recursive($tags, $point["tags"]); + } + + if (!$tags) { + $lines[] = trim( + sprintf( + "%s %s %d", + $point["measurement"], $this->toKeyValue($point["fields"], true), $unixepoch + ) + ); + } else { + $lines[] = trim( + sprintf( + "%s,%s %s %d", + $point["measurement"], $this->toKeyValue($tags), $this->toKeyValue($point["fields"], true), $unixepoch + ) + ); + } + } + return implode("\n", $lines); + } + + private function toKeyValue(array $elems, $escape=false) + { + $list = []; + foreach ($elems as $key => $value) { + if ($escape && is_string($value)) { + $value = "\"{$value}\""; + } + $list[] = sprintf("%s=%s", $key, $value); + } + + return implode(",", $list); + } +} diff --git a/src/Client.php b/src/Client.php new file mode 100644 index 000000000..e9f7c7d89 --- /dev/null +++ b/src/Client.php @@ -0,0 +1,87 @@ +adapter = $adapter; + return $this; + } + + public function getAdapter() + { + return $this->adapter; + } + + public function mark($name, array $values = []) + { + $data = $name; + if (!is_array($name)) { + $data =[]; + + $data['points'][0]['measurement'] = $name; + $data['points'][0]['fields'] = $values; + } + + return $this->getAdapter()->send($data); + } + + public function query($query) + { + if (!($this->getAdapter() instanceOf QueryableInterface)) { + throw new \BadMethodCallException("You can query the database only if the adapter supports it!"); + } + + $return = $this->getAdapter()->query($query); + + return $return; + } + + public function getDatabases() + { + if (!($this->getAdapter() instanceOf QueryableInterface)) { + throw new \BadMethodCallException("You can query the database only if the adapter supports it!"); + } + return $this->getAdapter()->query("show databases"); + } + + public function createDatabase($name) + { + if (!($this->getAdapter() instanceOf QueryableInterface)) { + throw new \BadMethodCallException("You can query the database only if the adapter supports it!"); + } + return $this->getAdapter()->query("create database \"{$name}\""); + } + + public function deleteDatabase($name) + { + if (!($this->getAdapter() instanceOf QueryableInterface)) { + throw new \BadMethodCallException("You can query the database only if the adapter supports it!"); + } + return $this->getAdapter()->query("drop database \"{$name}\""); + } + + private function clearTimePrecision($timePrecision) + { + switch ($timePrecision) { + case 's': + case 'u': + case 'ms': + break; + default: + $timePrecision = false; + } + + return $timePrecision; + } +} diff --git a/src/InfluxDB/ClientFactory.php b/src/ClientFactory.php similarity index 85% rename from src/InfluxDB/ClientFactory.php rename to src/ClientFactory.php index 9fdeb4d25..33789ec8a 100644 --- a/src/InfluxDB/ClientFactory.php +++ b/src/ClientFactory.php @@ -44,15 +44,11 @@ abstract class ClientFactory case 'InfluxDB\\Adapter\\GuzzleAdapter': $adapter = new $adapterName(new GuzzleClient($options["adapter"]["options"]), $adapterOptions); break; - case 'InfluxDB\\Adapter\\HttpAdapter': - $adapter = new $adapterName($adapterOptions, new GuzzleClient($options["adapter"]["options"])); - break; default: throw new \InvalidArgumentException("Missing adapter {$adapter}"); } - $client = new Client(); - $client->setAdapter($adapter); + $client = new Client($adapter); return $client; } diff --git a/src/InfluxDB/Adapter/GuzzleAdapter.php b/src/InfluxDB/Adapter/GuzzleAdapter.php deleted file mode 100644 index f8fe908fc..000000000 --- a/src/InfluxDB/Adapter/GuzzleAdapter.php +++ /dev/null @@ -1,122 +0,0 @@ -httpClient = $httpClient; - $this->options = $options; - } - - /** - * @return Options - */ - public function getOptions() - { - return $this->options; - } - - /** - * {@inheritDoc} - */ - public function send($message, $timePrecision = false) - { - $httpMessage = [ - "auth" => [$this->options->getUsername(), $this->options->getPassword()], - "body" => json_encode($message) - ]; - - if ($timePrecision) { - $httpMessage["query"]["time_precision"] = $timePrecision; - } - - $endpoint = $this->options->getHttpSeriesEndpoint(); - return $this->httpClient->post($endpoint, $httpMessage); - } - - /** - * {@inheritDoc} - */ - public function query($query, $timePrecision = false) - { - $options = [ - "auth" => [$this->options->getUsername(), $this->options->getPassword()], - 'query' => [ - "q" => $query, - ] - ]; - - if ($timePrecision) { - $options["query"]["time_precision"] = $timePrecision; - } - - $endpoint = $this->options->getHttpSeriesEndpoint(); - - return $this->httpClient->get($endpoint, $options)->json(); - } - - /** - * {@inheritDoc} - */ - public function getDatabases() - { - $options = [ - "auth" => [$this->options->getUsername(), $this->options->getPassword()], - ]; - - $endpoint = $this->options->getHttpDatabaseEndpoint(); - - return $this->httpClient->get($endpoint, $options)->json(); - } - - /** - * {@inheritDoc} - */ - public function createDatabase($name) - { - $httpMessage = [ - "auth" => [$this->options->getUsername(), $this->options->getPassword()], - "body" => json_encode(["name" => $name]) - ]; - - $endpoint = $this->options->getHttpDatabaseEndpoint(); - return $this->httpClient->post($endpoint, $httpMessage)->json(); - } - - /** - * {@inheritDoc} - */ - public function deleteDatabase($name) - { - $httpMessage = [ - "auth" => [$this->options->getUsername(), $this->options->getPassword()], - ]; - - $endpoint = $this->options->getHttpDatabaseEndpoint($name); - return $this->httpClient->delete($endpoint, $httpMessage)->json(); - } -} diff --git a/src/InfluxDB/Adapter/HttpAdapter.php b/src/InfluxDB/Adapter/HttpAdapter.php deleted file mode 100644 index 691b3b6d3..000000000 --- a/src/InfluxDB/Adapter/HttpAdapter.php +++ /dev/null @@ -1,199 +0,0 @@ -options = $options; - $this->client = $client ?: new Client(); - } - - /** - * @return Options - */ - public function getOptions() - { - return $this->options; - } - - /** - * @param array $body - * @param array $query - * @param bool $timePrecision - * @return array - */ - protected function getRequest(array $body = [], array $query = [], $timePrecision = false) - { - $request = [ - "auth" => [$this->options->getUsername(), $this->options->getPassword()], - "exceptions" => false - ]; - if (count($body)) { - $request['body'] = json_encode($body); - } - if (count($query)) { - $request['query'] = $query; - } - if ($timePrecision) { - $request["query"]["time_precision"] = $timePrecision; - } - return $request; - } - - /** - * @param ResponseInterface $response - * @return mixed - * @throws \InfluxDB\Exception\InfluxGeneralException - * @throws \InfluxDB\Exception\InfluxAuthorizationException - * @throws \InfluxDB\Exception\InfluxNoSeriesException - */ - protected function parseResponse(ResponseInterface $response) - { - $statusCode = $response->getStatusCode(); - if ($statusCode >= 400 && $statusCode < 500) { - $message = (string)$response->getBody(); - if (!$message) { - $message = $response->getReasonPhrase(); - } - switch ($statusCode) { - case self::STATUS_CODE_UNAUTHORIZED: - case self::STATUS_CODE_FORBIDDEN: - throw new InfluxAuthorizationException($message, $statusCode); - case self::STATUS_CODE_BAD_REQUEST: - if (strpos($message, "Couldn't find series:") !== false) { - throw new InfluxNoSeriesException($message, $statusCode); - } - } - throw new InfluxGeneralException($message, $statusCode); - } else if ($statusCode == self::STATUS_CODE_OK) { - try { - return $response->json(); - } catch (ParseException $ex) { - throw new InfluxBadResponseException( - sprintf("%s; Response is '%s'", $ex->getMessage(), (string)$response->getBody()), - $ex->getCode(), $ex - ); - } - } else if ($statusCode > 200 && $statusCode < 300) { - return true; - } - throw new InfluxUnexpectedResponseException((string)$response->getBody(), $statusCode); - } - - /** - * @param $message - * @param bool $timePrecision - * @return \GuzzleHttp\Message\ResponseInterface - */ - public function send($message, $timePrecision = false) - { - try { - $response = $this->client->post( - $this->options->getHttpSeriesEndpoint(), - $this->getRequest($message, [], $timePrecision) - ); - } catch (\Exception $ex) { - throw new InfluxGeneralException($ex->getMessage(), $ex->getCode(), $ex); - } - return $this->parseResponse($response); - } - - /** - * @param $query - * @param bool $timePrecision - * @return mixed - */ - public function query($query, $timePrecision = false) - { - try { - $response = $this->client->get( - $this->options->getHttpSeriesEndpoint(), - $this->getRequest([], ["q" => $query], $timePrecision) - ); - } catch (\Exception $ex) { - throw new InfluxGeneralException($ex->getMessage(), $ex->getCode(), $ex); - } - return $this->parseResponse($response); - } - - /** - * @return mixed - */ - public function getDatabases() - { - try { - $response = $this->client->get( - $this->options->getHttpDatabaseEndpoint(), - $this->getRequest() - ); - } catch (\Exception $ex) { - throw new InfluxGeneralException($ex->getMessage(), $ex->getCode(), $ex); - } - return $this->parseResponse($response); - } - - /** - * @param $name - * @return mixed - */ - public function createDatabase($name) - { - try { - $response = $this->client->post( - $this->options->getHttpDatabaseEndpoint(), - $this->getRequest(["name" => $name]) - ); - } catch (\Exception $ex) { - throw new InfluxGeneralException($ex->getMessage(), $ex->getCode(), $ex); - } - return $this->parseResponse($response); - } - - /** - * @param $name - * @return mixed - */ - public function deleteDatabase($name) - { - try { - $response = $this->client->delete( - $this->options->getHttpDatabaseEndpoint($name), - $this->getRequest() - ); - } catch (\Exception $ex) { - throw new InfluxGeneralException($ex->getMessage(), $ex->getCode(), $ex); - } - return $this->parseResponse($response); - } -} - diff --git a/src/InfluxDB/Adapter/QueryableInterface.php b/src/InfluxDB/Adapter/QueryableInterface.php deleted file mode 100644 index 3bed92384..000000000 --- a/src/InfluxDB/Adapter/QueryableInterface.php +++ /dev/null @@ -1,34 +0,0 @@ -options = $options; - } - - /** - * @return Options - */ - public function getOptions() - { - return $this->options; - } - - /** - * {@inheritDoc} - */ - public function send($message, $timePrecision = false) - { - $message = json_encode($message); - $socket = socket_create(AF_INET, SOCK_DGRAM, SOL_UDP); - socket_sendto($socket, $message, strlen($message), 0, $this->options->getHost(), $this->options->getPort()); - socket_close($socket); - } -} diff --git a/src/InfluxDB/Client.php b/src/InfluxDB/Client.php deleted file mode 100644 index 8baa37d4a..000000000 --- a/src/InfluxDB/Client.php +++ /dev/null @@ -1,131 +0,0 @@ -adapter = $adapter; - return $this; - } - - /** - * Get adapter - * @return Adapter\AdapterInterface - */ - public function getAdapter() - { - return $this->adapter; - } - - /** - * Insert point into series - * @param string $name - * @param array $value - * @param bool|string $timePrecision - * @return mixed - */ - public function mark($name, array $values, $timePrecision = false) - { - $data =[]; - - $timePrecision = $this->clearTimePrecision($timePrecision); - - $data['name'] = $name; - $data['columns'] = array_keys($values); - $data['points'][] = array_values($values); - - return $this->getAdapter()->send([$data], $timePrecision); - } - - /** - * Make a query into database - * @param string $query - * @param bool|string $timePrecision - * @return array - */ - public function query($query, $timePrecision = false) - { - if (!($this->getAdapter() instanceOf QueryableInterface)) { - throw new \BadMethodCallException("You can query the database only if the adapter supports it!"); - } - - $timePrecision = $this->clearTimePrecision($timePrecision); - - $return = $this->getAdapter()->query($query, $timePrecision); - - return $return; - } - - /** - * List of databases - * @return array - */ - public function getDatabases() - { - if (!($this->getAdapter() instanceOf QueryableInterface)) { - throw new \BadMethodCallException("You can query the database only if the adapter supports it!"); - } - return $this->getAdapter()->getDatabases(); - } - - /** - * Create database by name - * @param string $name - */ - public function createDatabase($name) - { - if (!($this->getAdapter() instanceOf QueryableInterface)) { - throw new \BadMethodCallException("You can query the database only if the adapter supports it!"); - } - return $this->getAdapter()->createDatabase($name); - } - - /** - * Delete database by name - * @param string $name - */ - public function deleteDatabase($name) - { - if (!($this->getAdapter() instanceOf QueryableInterface)) { - throw new \BadMethodCallException("You can query the database only if the adapter supports it!"); - } - return $this->getAdapter()->deleteDatabase($name); - } - - /** - * List of time precision choose - * @param string $timePrecision - * @return bool|string - */ - private function clearTimePrecision($timePrecision) - { - switch ($timePrecision) { - case 's': - case 'u': - case 'ms': - break; - default: - $timePrecision = false; - } - - return $timePrecision; - } -} diff --git a/src/InfluxDB/Exception/InfluxAuthorizationException.php b/src/InfluxDB/Exception/InfluxAuthorizationException.php deleted file mode 100644 index 83dcd32c7..000000000 --- a/src/InfluxDB/Exception/InfluxAuthorizationException.php +++ /dev/null @@ -1,9 +0,0 @@ -host = "localhost"; - $this->port = 8086; - $this->username = "root"; - $this->password = "root"; + $this->setHost("localhost"); + $this->setPort(8086); + $this->setUsername("root"); + $this->setPassword("root"); $this->setProtocol("http"); + + $this->setRetentionPolicy("default"); + $this->setTags([]); + } + + public function getTags() + { + return $this->tags; + } + + public function setTags($tags) + { + $this->tags = $tags; + return $this; + } + + public function getRetentionPolicy() + { + return $this->retentionPolicy; + } + + public function setRetentionPolicy($retentionPolicy) + { + $this->retentionPolicy = $retentionPolicy; + return $this; } /** @@ -57,19 +65,12 @@ class Options return $this->protocol; } - /** - * @param string $protocol - * @return Options - */ public function setProtocol($protocol) { $this->protocol = $protocol; return $this; } - /** - * @return string - */ public function getHost() { return $this->host; @@ -81,111 +82,69 @@ class Options return $this; } - /** - * @return string|int - */ public function getPort() { return $this->port; } - /** - * @param string|int $port - * @return Options - */ public function setPort($port) { $this->port = $port; return $this; } - /** - * @return string - */ public function getUsername() { return $this->username; } - /** - * @param string $usarname - * @return Options - */ public function setUsername($username) { $this->username = $username; return $this; } - /** - * @return string - */ public function getPassword() { return $this->password; } - /** - * @param string $password - * @return Options - */ public function setPassword($password) { $this->password = $password; return $this; } - /** - * @return string - */ public function getDatabase() { return $this->database; } - /** - * @param string $database - * @return Options - */ public function setDatabase($database) { $this->database = $database; return $this; } - /** - * Build http series edpoint - * @return string - */ public function getHttpSeriesEndpoint() { return sprintf( - "%s://%s:%d/db/%s/series", + "%s://%s:%d/write", $this->getProtocol(), $this->getHost(), - $this->getPort(), - $this->getDatabase() + $this->getPort() ); } - /** - * Build http database endpoint by name - * @param string $name - * @return string - */ - public function getHttpDatabaseEndpoint($name = false) + public function getHttpQueryEndpoint($name = false) { $url = sprintf( - "%s://%s:%d/db", + "%s://%s:%d/query", $this->getProtocol(), $this->getHost(), $this->getPort() ); - if ($name !== false) { - $url .= "/{$name}"; - } - return $url; } } diff --git a/tests/Adapter/UdpAdapterTest.php b/tests/Adapter/UdpAdapterTest.php new file mode 100644 index 000000000..fa5908086 --- /dev/null +++ b/tests/Adapter/UdpAdapterTest.php @@ -0,0 +1,94 @@ +getMethod("serialize"); + $method->setAccessible(true); + + $message = $method->invokeArgs($object, [$input]); + + $this->assertEquals($response, $message); + } + + public function getMessages() + { + return [ + [ + [ + "time" => "2009-11-10T23:00:00Z", + "points" => [ + [ + "measurement" => "cpu", + "fields" => [ + "value" => 1, + ], + ], + ], + ], + "cpu value=1 1257894000000000000" + ], + [ + [ + "tags" => [ + "region" => "us-west", + "host" => "serverA", + "env" => "prod", + "target" => "servers", + "zone" => "1c", + ], + "time" => "2009-11-10T23:00:00Z", + "points" => [ + [ + "measurement" => "cpu", + "fields" => [ + "cpu" => 18.12, + "free" => 712432, + ], + ], + ], + ], + "cpu,region=us-west,host=serverA,env=prod,target=servers,zone=1c cpu=18.12,free=712432 1257894000000000000" + ], + [ + [ + "tags" => [ + "region" => "us-west", + "host" => "serverA", + "env" => "prod", + "target" => "servers", + "zone" => "1c", + ], + "time" => "2009-11-10T23:00:00Z", + "points" => [ + [ + "measurement" => "cpu", + "fields" => [ + "cpu" => 18.12, + ], + ], + [ + "measurement" => "mem", + "fields" => [ + "free" => 712432, + ], + ], + ], + ], + <<assertEquals("pass", $client->getAdapter()->getOptions()->getPassword()); } - public function getTcpAdapters() - { - return [ - ["InfluxDB\\Adapter\\GuzzleAdapter"], - ["InfluxDB\\Adapter\\HttpAdapter"], - ]; - } - /** * @group factory - * @dataProvider getTcpAdapters + * @dataProvider getHttpAdapters */ - public function testCreateTcpClientWithFilter($adapter) + public function testCreateTcpClientWithAllOptions($adapter) { $options = [ "adapter" => [ @@ -97,6 +89,11 @@ class ClientFactoryTest extends \PHPUnit_Framework_TestCase "host" => "127.0.0.1", "username" => "user", "password" => "pass", + "retention_policy" => "too_many_data", + "tags" => [ + "region" => "eu", + "env" => "prod", + ], ], ]; @@ -107,5 +104,14 @@ class ClientFactoryTest extends \PHPUnit_Framework_TestCase $this->assertEquals("127.0.0.1", $client->getAdapter()->getOptions()->getHost()); $this->assertEquals("user", $client->getAdapter()->getOptions()->getUsername()); $this->assertEquals("pass", $client->getAdapter()->getOptions()->getPassword()); + $this->assertEquals(["region" => "eu", "env" => "prod"], $client->getAdapter()->getOptions()->getTags()); + $this->assertEquals("too_many_data", $client->getAdapter()->getOptions()->getRetentionPolicy()); + } + + public function getHttpAdapters() + { + return [ + ["InfluxDB\\Adapter\\GuzzleAdapter"], + ]; } } diff --git a/tests/ClientTest.php b/tests/ClientTest.php new file mode 100644 index 000000000..1bfb33db3 --- /dev/null +++ b/tests/ClientTest.php @@ -0,0 +1,399 @@ +rawOptions = $options; + + $tcpOptions = $options["tcp"]; + + $options = new Options(); + $options->setHost($tcpOptions["host"]); + $options->setPort($tcpOptions["port"]); + $options->setUsername($tcpOptions["username"]); + $options->setPassword($tcpOptions["password"]); + $options->setDatabase($tcpOptions["database"]); + + $this->options = $options; + + $guzzleHttp = new GuzzleHttpClient(); + $adapter = new InfluxHttpAdapter($guzzleHttp, $options); + + $influx = new Client($adapter); + $this->object = $influx; + + $databases = $this->object->getDatabases(); + if (array_key_exists("values", $databases["results"][0]["series"][0])) { + foreach ($databases["results"][0]["series"][0]["values"] as $database) { + $this->object->deleteDatabase($database[0]); + } + } + + $this->object->createDatabase($this->rawOptions["udp"]["database"]); + $this->object->createDatabase($this->rawOptions["tcp"]["database"]); + } + + /** + * @group tcp + */ + public function testGuzzleHttpApiWorksCorrectly() + { + $this->object->mark("tcp.test", ["mark" => "element"]); + + sleep(1); + + $body = $this->object->query("select * from \"tcp.test\""); + $this->assertCount(1, $body["results"][0]["series"][0]["values"]); + $this->assertEquals("mark", $body["results"][0]["series"][0]["columns"][1]); + $this->assertEquals("element", $body["results"][0]["series"][0]["values"][0][1]); + } + + /** + * @group tcp + */ + public function testGuzzleHttpQueryApiWorksCorrectly() + { + $this->object->mark("tcp.test", ["mark" => "element"]); + + sleep(1); + + $body = $this->object->query("select * from \"tcp.test\""); + + $this->assertCount(1, $body["results"][0]["series"][0]["values"]); + $this->assertEquals("mark", $body["results"][0]["series"][0]["columns"][1]); + $this->assertEquals("element", $body["results"][0]["series"][0]["values"][0][1]); + } + + /** + * @group tcp + */ + public function testGuzzleHttpQueryApiWithMultipleData() + { + $this->object->mark("tcp.test", ["mark" => "element"]); + $this->object->mark("tcp.test", ["mark" => "element2"]); + $this->object->mark("tcp.test", ["mark" => "element3"]); + + sleep(1); + + $body = $this->object->query("select mark from \"tcp.test\"", "s"); + + $this->assertCount(3, $body["results"][0]["series"][0]["values"]); + $this->assertEquals("mark", $body["results"][0]["series"][0]["columns"][1]); + $this->assertEquals("element", $body["results"][0]["series"][0]["values"][0][1]); + } + + /** + * @group tcp + */ + public function testWriteDirectMessages() + { + $this->object->mark([ + "tags" => [ + "dc" => "eu-west-1", + ], + "points" => [ + [ + "measurement" => "vm-serie", + "fields" => [ + "cpu" => 18.12, + "free" => 712423, + ], + ], + ] + ]); + + sleep(1); + + $body = $this->object->query("select * from \"vm-serie\""); + + $this->assertCount(1, $body["results"][0]["series"][0]["values"]); + $this->assertEquals("cpu", $body["results"][0]["series"][0]["columns"][1]); + $this->assertEquals(18.12, $body["results"][0]["series"][0]["values"][0][1]); + } + + /** + * @group tcp + */ + public function testOverrideDatabaseNameViaMessage() + { + $this->options->setDatabase("a-wrong-database"); + + $this->object->mark([ + "database" => "tcp.test", + "points" => [ + [ + "measurement" => "vm-serie", + "fields" => [ + "cpu" => 18.12, + "free" => 712423, + ], + ], + ] + ]); + + sleep(1); + + $this->options->setDatabase("tcp.test"); + $body = $this->object->query("select * from \"vm-serie\""); + + $this->assertCount(1, $body["results"][0]["series"][0]["values"]); + $this->assertEquals("cpu", $body["results"][0]["series"][0]["columns"][1]); + $this->assertEquals(18.12, $body["results"][0]["series"][0]["values"][0][1]); + $this->assertEquals(712423, $body["results"][0]["series"][0]["values"][0][2]); + } + + /** + * @group udp + */ + public function testUdpIpWriteData() + { + $object = $this->createClientWithUdpAdapter(); + + $object->mark("udp.test", ["mark" => "element"]); + sleep(1); + $object->mark("udp.test", ["mark" => "element1"]); + sleep(1); + $object->mark("udp.test", ["mark" => "element2"]); + sleep(1); + $object->mark("udp.test", ["mark" => "element3"]); + + // Wait UDP/IP message arrives + sleep(2); + + $this->options->setDatabase("udp.test"); + $body = $this->object->query("select * from \"udp.test\""); + + $this->assertCount(4, $body["results"][0]["series"][0]["values"]); + } + + /** + * @group udp + */ + public function testSendMultipleMeasurementWithUdpIp() + { + $object = $this->createClientWithUdpAdapter(); + + $object->mark([ + "points" => [ + [ + "measurement" => "mem", + "fields" => [ + "free" => 712423, + ], + ], + [ + "measurement" => "cpu", + "fields" => [ + "cpu" => 18.12, + ], + ], + ] + ]); + + sleep(2); + + $this->options->setDatabase("udp.test"); + $body = $this->object->query("select * from \"cpu\""); + + $this->assertCount(1, $body["results"][0]["series"][0]["values"]); + $this->assertEquals("cpu", $body["results"][0]["series"][0]["columns"][1]); + $this->assertEquals(18.12, $body["results"][0]["series"][0]["values"][0][1]); + + $body = $this->object->query("select * from \"mem\""); + + $this->assertCount(1, $body["results"][0]["series"][0]["values"]); + $this->assertEquals("free", $body["results"][0]["series"][0]["columns"][1]); + $this->assertEquals(712423, $body["results"][0]["series"][0]["values"][0][1]); + } + + /** + * @group udp + */ + public function testWriteDirectMessageWithUdpIp() + { + $object = $this->createClientWithUdpAdapter(); + + $object->mark([ + "points" => [ + [ + "measurement" => "vm-serie", + "fields" => [ + "cpu" => 18.12, + "free" => 712423, + ], + ], + ] + ]); + + sleep(2); + + $this->options->setDatabase("udp.test"); + $body = $this->object->query("select * from \"vm-serie\""); + + $this->assertCount(1, $body["results"][0]["series"][0]["values"]); + $this->assertEquals("cpu", $body["results"][0]["series"][0]["columns"][1]); + $this->assertEquals(18.12, $body["results"][0]["series"][0]["values"][0][1]); + $this->assertEquals(712423, $body["results"][0]["series"][0]["values"][0][2]); + } + + /** + * @group udp + * @group date + */ + public function testWriteDirectMessageWillPreserveActualTime() + { + $object = $this->createClientWithUdpAdapter(); + + $object->mark([ + "points" => [ + [ + "measurement" => "vm-serie", + "fields" => [ + "cpu" => 18.12, + "free" => 712423, + ], + ], + ] + ]); + + sleep(2); + + $this->options->setDatabase("udp.test"); + $body = $this->object->query("select * from \"vm-serie\""); + + $this->assertCount(1, $body["results"][0]["series"][0]["values"]); + $this->assertEquals("time", $body["results"][0]["series"][0]["columns"][0]); + $saved = new DateTime($body["results"][0]["series"][0]["values"][0][0]); + $this->assertEquals(date("Y-m-d"), $saved->format("Y-m-d")); + } + + /** + * @group udp + * @group date + */ + public function testWriteDirectMessageWillPreserveDatetime() + { + $object = $this->createClientWithUdpAdapter(); + + $object->mark([ + "time" => "2009-11-10T23:00:00Z", + "points" => [ + [ + "measurement" => "vm-serie", + "fields" => [ + "cpu" => 18.12, + "free" => 712423, + ], + ], + ] + ]); + + sleep(2); + + $this->options->setDatabase("udp.test"); + $body = $this->object->query("select * from \"vm-serie\""); + + $this->assertCount(1, $body["results"][0]["series"][0]["values"]); + $this->assertEquals("time", $body["results"][0]["series"][0]["columns"][0]); + $this->assertEquals("2009-11-10T23:00:00Z", $body["results"][0]["series"][0]["values"][0][0]); + } + + /** + * @group udp + * @group tags + */ + public function testTagsAreWrittenCorrectly() + { + $object = $this->createClientWithUdpAdapter(); + + $object->mark([ + "tags" => [ + "region" => "eu", + ], + "points" => [ + [ + "measurement" => "vm-serie", + "tags" => [ + "dc" => "eu-west-1", + "one" => "two", + ], + "fields" => [ + "cpu" => 18.12, + "free" => 712423, + ], + ], + [ + "measurement" => "vm-serie", + "tags" => [ + "dc" => "us-east-1", + ], + "fields" => [ + "cpu" => 28.12, + "free" => 412923, + ], + ], + ] + ]); + + sleep(2); + + $this->options->setDatabase("udp.test"); + $body = $this->object->query("select * from \"vm-serie\" where dc='eu-west-1'"); + + $this->assertCount(1, $body["results"][0]["series"][0]["values"]); + $this->assertEquals("cpu", $body["results"][0]["series"][0]["columns"][1]); + $this->assertEquals(18.12, $body["results"][0]["series"][0]["values"][0][1]); + $this->assertEquals(712423, $body["results"][0]["series"][0]["values"][0][2]); + } + + public function testListActiveDatabses() + { + $databases = $this->object->getDatabases(); + + $this->assertCount(2, $databases["results"][0]["series"][0]["values"]); + } + + public function testCreateANewDatabase() + { + $this->object->createDatabase("walter"); + + sleep(1); + + $databases = $this->object->getDatabases(); + + $this->assertCount(3, $databases["results"][0]["series"][0]["values"]); + + $this->object->deleteDatabase("walter"); + } + + private function createClientWithUdpAdapter() + { + $rawOptions = $this->rawOptions; + $options = new Options(); + $options->setHost($rawOptions["udp"]["host"]); + $options->setUsername($rawOptions["udp"]["username"]); + $options->setPassword($rawOptions["udp"]["password"]); + $options->setPort($rawOptions["udp"]["port"]); + $options->setDatabase($rawOptions["udp"]["database"]); + + $adapter = new UdpAdapter($options); + $object = new Client($adapter); + + return $object; + } +} diff --git a/tests/InfluxDB/ClientTest.php b/tests/InfluxDB/ClientTest.php deleted file mode 100644 index 45ea0397e..000000000 --- a/tests/InfluxDB/ClientTest.php +++ /dev/null @@ -1,165 +0,0 @@ -rawOptions = $options; - - $tcpOptions = $options["tcp"]; - - $options = new Options(); - $options->setHost($tcpOptions["host"]); - $options->setPort($tcpOptions["port"]); - $options->setUsername($tcpOptions["username"]); - $options->setPassword($tcpOptions["password"]); - $options->setDatabase($tcpOptions["database"]); - - $this->options = $options; - - $guzzleHttp = new GuzzleHttpClient(); - $adapter = new InfluxHttpAdapter($guzzleHttp, $options); - - $influx = new Client(); - $influx->setAdapter($adapter); - $this->object = $influx; - - $databases = $this->object->getDatabases(); - foreach ($databases as $database) { - $this->object->deleteDatabase($database["name"]); - } - - $this->object->createDatabase($this->rawOptions["udp"]["database"]); - $this->object->createDatabase($this->rawOptions["tcp"]["database"]); - } - - /** - * @group tcp - */ - public function testGuzzleHttpApiWorksCorrectly() - { - $this->object->mark("tcp.test", ["mark" => "element"]); - - $body = $this->object->query("select * from tcp.test"); - $this->assertCount(1, $body[0]["points"]); - $this->assertEquals("element", $body[0]["points"][0][2]); - } - - /** - * @group tcp - */ - public function testGuzzleHttpQueryApiWorksCorrectly() - { - $this->object->mark("tcp.test", ["mark" => "element"]); - - $body = $this->object->query("select * from tcp.test"); - - $this->assertCount(1, $body); - $this->assertEquals("tcp.test", $body[0]["name"]); - $this->assertEquals("element", $body[0]["points"][0][2]); - } - - /** - * @group tcp - */ - public function testGuzzleHttpQueryApiWithMultipleData() - { - $this->object->mark("tcp.test", ["mark" => "element"]); - $this->object->mark("tcp.test", ["mark" => "element2"]); - $this->object->mark("tcp.test", ["mark" => "element3"]); - - $body = $this->object->query("select mark from tcp.test", "s"); - - $this->assertCount(3, $body[0]["points"]); - $this->assertEquals("tcp.test", $body[0]["name"]); - } - - /** - * @group tcp - */ - public function testGuzzleHttpQueryApiWithTimePrecision() - { - $this->object->mark("tcp.test", ["mark" => "element"]); - - $body = $this->object->query("select mark from tcp.test", "s"); - - $this->assertCount(1, $body[0]["points"]); - $this->assertEquals("tcp.test", $body[0]["name"]); - } - - /** - * @group tcp - */ - public function testGuzzleHttpWriteApiWithTimePrecision() - { - $this->object->mark("tcp.test", ["time" => 1410591552, "mark" => "element"], "s"); - - $body = $this->object->query("select mark from tcp.test", "ms"); - - $this->assertCount(1, $body[0]["points"]); - $this->assertEquals("tcp.test", $body[0]["name"]); - - $this->assertEquals("1410591552000", $body[0]["points"][0][0]); - } - - /** - * @group udp - */ - public function testUdpIpWriteData() - { - $rawOptions = $this->rawOptions; - $options = new Options(); - $options->setHost($rawOptions["udp"]["host"]); - $options->setUsername($rawOptions["udp"]["username"]); - $options->setPassword($rawOptions["udp"]["password"]); - $options->setPort($rawOptions["udp"]["port"]); - - $adapter = new UdpAdapter($options); - $object = new Client(); - $object->setAdapter($adapter); - - $object->mark("udp.test", ["mark" => "element"]); - $object->mark("udp.test", ["mark" => "element1"]); - $object->mark("udp.test", ["mark" => "element2"]); - $object->mark("udp.test", ["mark" => "element3"]); - - // Wait UDP/IP message arrives - usleep(200e3); - - $this->options->setDatabase("udp.test"); - $body = $this->object->query("select * from udp.test"); - - $this->assertCount(4, $body[0]["points"]); - $this->assertEquals("udp.test", $body[0]["name"]); - } - - public function testListActiveDatabses() - { - $databases = $this->object->getDatabases(); - - $this->assertCount(2, $databases); - } - - public function testCreateANewDatabase() - { - $this->object->createDatabase("walter"); - $databases = $this->object->getDatabases(); - - $this->assertCount(3, $databases); - - $this->object->deleteDatabase("walter"); - } -} diff --git a/tests/InfluxDB/HttpAdapterTest.php b/tests/InfluxDB/HttpAdapterTest.php deleted file mode 100644 index 9cd2fca8f..000000000 --- a/tests/InfluxDB/HttpAdapterTest.php +++ /dev/null @@ -1,129 +0,0 @@ -rawOptions = $options; - - $tcpOptions = $options["tcp"]; - - $options = new Options(); - $options->setHost($tcpOptions["host"]); - $options->setPort($tcpOptions["port"]); - $options->setUsername($tcpOptions["username"]); - $options->setPassword($tcpOptions["password"]); - $options->setDatabase($tcpOptions["database"]); - - $this->options = $options; - - $adapter = new HttpAdapter($options); - - $influx = new Client(); - $influx->setAdapter($adapter); - $this->object = $influx; - - $databases = $this->object->getDatabases(); - foreach ($databases as $database) { - $this->object->deleteDatabase($database["name"]); - } - - $this->object->createDatabase($this->rawOptions["tcp"]["database"]); - } - - /** - * @group tcp - */ - public function testApiWorksCorrectly() - { - $this->object->mark("tcp.test", ["mark" => "element"]); - - $body = $this->object->query("select * from tcp.test"); - $this->assertCount(1, $body[0]["points"]); - $this->assertEquals("element", $body[0]["points"][0][2]); - } - - /** - * @group tcp - */ - public function testQueryApiWorksCorrectly() - { - $this->object->mark("tcp.test", ["mark" => "element"]); - - $body = $this->object->query("select * from tcp.test"); - - $this->assertCount(1, $body); - $this->assertEquals("tcp.test", $body[0]["name"]); - $this->assertEquals("element", $body[0]["points"][0][2]); - } - - /** - * @group tcp - */ - public function testQueryApiWithMultipleData() - { - $this->object->mark("tcp.test", ["mark" => "element"]); - $this->object->mark("tcp.test", ["mark" => "element2"]); - $this->object->mark("tcp.test", ["mark" => "element3"]); - - $body = $this->object->query("select mark from tcp.test", "s"); - - $this->assertCount(3, $body[0]["points"]); - $this->assertEquals("tcp.test", $body[0]["name"]); - } - - /** - * @group tcp - */ - public function testQueryApiWithTimePrecision() - { - $this->object->mark("tcp.test", ["mark" => "element"]); - - $body = $this->object->query("select mark from tcp.test", "s"); - - $this->assertCount(1, $body[0]["points"]); - $this->assertEquals("tcp.test", $body[0]["name"]); - } - - /** - * @group tcp - */ - public function testWriteApiWithTimePrecision() - { - $this->object->mark("tcp.test", ["time" => 1410591552, "mark" => "element"], "s"); - - $body = $this->object->query("select mark from tcp.test", "ms"); - - $this->assertCount(1, $body[0]["points"]); - $this->assertEquals("tcp.test", $body[0]["name"]); - - $this->assertEquals("1410591552000", $body[0]["points"][0][0]); - } - - public function testListActiveDatabses() - { - $databases = $this->object->getDatabases(); - - $this->assertCount(1, $databases); - } - - public function testCreateANewDatabase() - { - $this->object->createDatabase("walter"); - $databases = $this->object->getDatabases(); - - $this->assertCount(2, $databases); - - $this->object->deleteDatabase("walter"); - } -}