diff --git a/README.md b/README.md index 2c19815cc7..6b85296e07 100644 --- a/README.md +++ b/README.md @@ -5,6 +5,25 @@ Send metrics to InfluxDB and query for any data. +## Install it + +Just use composer + +```shell +php composer.phar require corley/influxdb-sdk:dev-master +``` + +Or place it in your require section + +```json +{ + "require": { + // ... + "corley/influxdb-sdk": "dev-master" + } +} +``` + Add new points: ```php @@ -58,7 +77,7 @@ $client->setAdapter($adapter); Effectively the client creation is not so simple, for that reason you can you the factory method provided with the library. -``` +```php $options = [ "adapter" => [ "name" => "InfluxDB\\Adapter\\GuzzleAdapter", @@ -69,6 +88,11 @@ $options = [ "options" => [ "host" => "my.influx.domain.tld", ], + "filters" => [ + "query" => [ + "name" => "InfluxDB\\Filter\\ColumnsPointsFilter" + ], + ], ]; $client = \InfluxDB\ClientFactory::create($options); @@ -135,6 +159,31 @@ array(1) { } ``` +By default data is returned as is. You can add filters in order to +change a response as you prefer, by default this library carries a +common filter that simplifies the response. + +``` +$client->setFilter(new ColumnsPointsFilter()); + +$data = $client->query("select * from hd_used"); +``` + +With the "ColumnsPointsFilter" you get a list of dictionaries, +something like: + +``` +[ + "serie_name" => [ + [ + "time" => 410545635590, + "sequence_number" => 390001, + "mark" => "element", + ], + ] +] +``` + ## Database operations You can create, list or destroy databases using dedicated methods @@ -147,51 +196,3 @@ $client->deleteDatabase("my.name"); // delete an existing database with name "my Actually only queryable adapters can handle databases (implements the `QueryableInterface`) -## Install it - -Just use composer - -```shell -php composer.phar require corley/influxdb-sdk:dev-master -``` - -Or place it in your require section - -```json -{ - "require": { - // ... - "corley/influxdb-sdk": "dev-master" - } -} -``` - - -## Prepare lib dependencies - -Use your DiC or Service Locator in order to provide a configured client - -```php -setHost("analytics.mine.domain.tld"); -$options->setPort(8086); -$options->setUsername("root"); -$options->setPassword("root"); -$options->setDatabase("mine"); - -$guzzleHttp = new GuzzleHttpClient(); -$adapter = new InfluxHttpAdapter($guzzleHttp, $options); - -$influx = new Client(); -$influx->setAdapter($adapter); - -$influx->mark("tcp.test", ["mark" => "element"]); -``` - diff --git a/VERSION b/VERSION index d917d3e26a..0ea3a944b3 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -0.1.2 +0.2.0 diff --git a/spec/InfluxDB/ClientSpec.php b/spec/InfluxDB/ClientSpec.php index b1ff81cb6d..126ac4f05c 100644 --- a/spec/InfluxDB/ClientSpec.php +++ b/spec/InfluxDB/ClientSpec.php @@ -6,7 +6,8 @@ use Prophecy\Argument; use InfluxDB\Adapter\GuzzleAdapter; use InfluxDB\Adapter\UdpAdapter; use InfluxDB\Adapter\AdapterInterface; -use InfluxDB\Adapter\ConnectableInterface; +use InfluxDB\Filter\FilterInterface; +use InfluxDb\Adapter\QueryableInterface; class ClientSpec extends ObjectBehavior { @@ -83,4 +84,15 @@ class ClientSpec extends ObjectBehavior $this->shouldThrow("\\BadMethodCallException")->duringQuery("select * from tcp.test"); } + + function it_should_filter_returned_data(FilterInterface $filter, QueryableInterface $adapter) + { + $adapter->query(Argument::Any(), Argument::Any())->willReturn(null); + $filter->filter(Argument::Any())->shouldBeCalledTimes(1)->willReturn([]); + + $this->setFilter($filter); + $this->setAdapter($adapter); + + $this->query("select * from tcp.test")->shouldReturn([]); + } } diff --git a/spec/InfluxDB/Filter/ColumnsPointsFilterSpec.php b/spec/InfluxDB/Filter/ColumnsPointsFilterSpec.php new file mode 100644 index 0000000000..4e85f88fc2 --- /dev/null +++ b/spec/InfluxDB/Filter/ColumnsPointsFilterSpec.php @@ -0,0 +1,58 @@ +shouldHaveType('InfluxDB\Filter\ColumnsPointsFilter'); + } + + function it_is_a_valid_filter() + { + $this->shouldImplement("InfluxDb\\Filter\\FilterInterface"); + } + + function it_should_map_columns_with_points() + { + $response = json_decode('[{"name":"hd_used","columns":["time","sequence_number","value","host","mount","time_precision"],"points":[[1410591684,11820001,23.2,"serverA","/mnt","s"]]}]'); + + $this->filter($response)->shouldBeEqualTo([ + "hd_used" => [ + [ + "time" => 1410591684, + "sequence_number" => 11820001, + "value" => 23.2, + "host" => "serverA", + "mount" => "/mnt", + "time_precision" => "s", + ], + ], + ]); + } + + function it_should_map_also_a_series_list() + { + $response = json_decode('[{"name":"list_series_result","columns":["time","name"],"points":[[0,"hd_used"]]}]'); + + $this->filter($response)->shouldBeEqualTo([ + "list_series_result" => [ + [ + "time" => 0, + "name" => "hd_used", + ], + ], + ]); + } + + function it_should_reply_to_an_empty_set() + { + $response = json_decode('[]'); + + $this->filter($response)->shouldBeEqualTo([]); + } +} diff --git a/src/InfluxDB/Client.php b/src/InfluxDB/Client.php index 3b4c7e95c0..94e879f8f8 100644 --- a/src/InfluxDB/Client.php +++ b/src/InfluxDB/Client.php @@ -3,11 +3,23 @@ namespace InfluxDB; use InfluxDb\Adapter\QueryableInterface; -use InfluxDb\Adapter\ConnectableInterface; +use InfluxDB\Filter\FilterInterface; class Client { private $adapter; + private $filter; + + public function setFilter(Filter\FilterInterface $filter) + { + $this->filter = $filter; + return $this; + } + + public function getFilter() + { + return $this->filter; + } public function setAdapter(Adapter\AdapterInterface $adapter) { @@ -41,7 +53,13 @@ class Client $timePrecision = $this->clearTimePrecision($timePrecision); - return $this->getAdapter()->query($query, $timePrecision); + $return = $this->getAdapter()->query($query, $timePrecision); + + if ($this->getFilter() instanceOf FilterInterface) { + $return = $this->getFilter()->filter($return); + } + + return $return; } public function getDatabases() diff --git a/src/InfluxDB/ClientFactory.php b/src/InfluxDB/ClientFactory.php index 1fe7846d13..035b7f53d5 100644 --- a/src/InfluxDB/ClientFactory.php +++ b/src/InfluxDB/ClientFactory.php @@ -12,6 +12,9 @@ abstract class ClientFactory "options" => [], ], "options" => [], + "filters" => [ + "query" => false + ], ]; public static function create(array $options) @@ -42,6 +45,10 @@ abstract class ClientFactory $client = new Client(); $client->setAdapter($adapter); + if ($options["filters"]["query"]) { + $client->setFilter(new $options["filters"]["query"]["name"]); + } + return $client; } } diff --git a/src/InfluxDB/Filter/ColumnsPointsFilter.php b/src/InfluxDB/Filter/ColumnsPointsFilter.php new file mode 100644 index 0000000000..b6e94dc07b --- /dev/null +++ b/src/InfluxDB/Filter/ColumnsPointsFilter.php @@ -0,0 +1,22 @@ +columns; + $response[$metric->name] = []; + + foreach ($metric->points as $point) { + $response[$metric->name][] = array_combine($columns, $point); + } + } + + return $response; + } +} diff --git a/src/InfluxDB/Filter/FilterInterface.php b/src/InfluxDB/Filter/FilterInterface.php new file mode 100644 index 0000000000..01bb59fd80 --- /dev/null +++ b/src/InfluxDB/Filter/FilterInterface.php @@ -0,0 +1,7 @@ +assertEquals("user", $client->getAdapter()->getOptions()->getUsername()); $this->assertEquals("pass", $client->getAdapter()->getOptions()->getPassword()); } + + /** + * @group factory + * @group filters + */ + public function testCreateTcpClientWithFilter() + { + $options = [ + "adapter" => [ + "name" => "InfluxDB\\Adapter\\GuzzleAdapter", + ], + "options" => [ + "host" => "127.0.0.1", + "username" => "user", + "password" => "pass", + ], + "filters" => [ + "query" => [ + "name" => "InfluxDB\\Filter\\ColumnsPointsFilter", + ], + ], + ]; + + $client = ClientFactory::create($options); + $this->assertInstanceOf("InfluxDB\\Client", $client); + + $this->assertInstanceOf("InfluxDB\\Adapter\\GuzzleAdapter", $client->getAdapter()); + $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->assertInstanceOf("InfluxDB\\Filter\\ColumnsPointsFilter", $client->getFilter()); + } }