mirror of
https://github.com/librenms/librenms.git
synced 2024-10-07 16:52:45 +00:00
Merge branch 'release/0.3.0'
This commit is contained in:
@@ -77,21 +77,28 @@ $client = new Client();
|
||||
$client->setAdapter($adapter);
|
||||
```
|
||||
|
||||
### Using HTTP Adapter
|
||||
### Using HTTP Adapters
|
||||
|
||||
Actually Guzzle is used as HTTP client library
|
||||
|
||||
```php
|
||||
<?php
|
||||
$guzzle = new \GuzzleHttp\Client();
|
||||
|
||||
$options = new Options();
|
||||
$adapter = new GuzzleAdapter($guzzle, $options);
|
||||
$adapter = new HttpAdapter($options);
|
||||
|
||||
$client = new Client();
|
||||
$client->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
|
||||
|
||||
Effectively the client creation is not so simple, for that
|
||||
@@ -100,7 +107,7 @@ reason you can you the factory method provided with the library.
|
||||
```php
|
||||
$options = [
|
||||
"adapter" => [
|
||||
"name" => "InfluxDB\\Adapter\\GuzzleAdapter",
|
||||
"name" => "InfluxDB\\Adapter\\HttpAdapter",
|
||||
"options" => [
|
||||
// guzzle options
|
||||
],
|
||||
@@ -144,7 +151,7 @@ $influx->query("select * from mine", "s"); // with time_precision
|
||||
```
|
||||
|
||||
You can query the database only if the adapter is queryable (implements
|
||||
`QueryableInterface`), actually `GuzzleAdapter`.
|
||||
`QueryableInterface`), actually `HttpAdapter`.
|
||||
|
||||
The adapter returns the json decoded body of the InfluxDB response, something
|
||||
like:
|
||||
|
||||
Executable
+194
@@ -0,0 +1,194 @@
|
||||
<?php
|
||||
|
||||
namespace spec\InfluxDB\Adapter;
|
||||
|
||||
use GuzzleHttp\Client;
|
||||
use GuzzleHttp\Message\Response;
|
||||
use GuzzleHttp\Stream\Stream;
|
||||
use InfluxDB\Adapter\HttpAdapter;
|
||||
use InfluxDB\Exception\InfluxAuthorizationException;
|
||||
use InfluxDB\Exception\InfluxBadResponseException;
|
||||
use InfluxDB\Exception\InfluxGeneralException;
|
||||
use InfluxDB\Exception\InfluxNoSeriesException;
|
||||
use InfluxDB\Exception\InfluxUnexpectedResponseException;
|
||||
use InfluxDB\Options;
|
||||
use PhpSpec\ObjectBehavior;
|
||||
use Prophecy\Argument;
|
||||
|
||||
class HttpAdapterSpec extends ObjectBehavior
|
||||
{
|
||||
function it_is_initializable()
|
||||
{
|
||||
$this->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"]);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,15 @@
|
||||
<?php
|
||||
namespace InfluxDB\Adapter;
|
||||
|
||||
/**
|
||||
* Every InfluxDB adapter implements this interface
|
||||
*/
|
||||
interface AdapterInterface
|
||||
{
|
||||
/**
|
||||
* Send series into database
|
||||
* @param mixed $message
|
||||
* @param string|boolean $timePrecision
|
||||
*/
|
||||
public function send($message, $timePrecision = false);
|
||||
}
|
||||
|
||||
@@ -4,22 +4,45 @@ namespace InfluxDB\Adapter;
|
||||
use GuzzleHttp\Client;
|
||||
use InfluxDB\Options;
|
||||
|
||||
/**
|
||||
* Class GuzzleAdapter
|
||||
* @package InfluxDB\Adapter
|
||||
*
|
||||
* @deprecated
|
||||
*/
|
||||
class GuzzleAdapter implements AdapterInterface, QueryableInterface
|
||||
{
|
||||
/**
|
||||
* @var GuzzleHttp\Client
|
||||
*/
|
||||
private $httpClient;
|
||||
|
||||
/**
|
||||
* @var \InfluxDB\Options
|
||||
*/
|
||||
private $options;
|
||||
|
||||
/**
|
||||
* @param Client $httpClient
|
||||
* @param Options $options
|
||||
*/
|
||||
public function __construct(Client $httpClient, Options $options)
|
||||
{
|
||||
$this->httpClient = $httpClient;
|
||||
$this->options = $options;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Options
|
||||
*/
|
||||
public function getOptions()
|
||||
{
|
||||
return $this->options;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function send($message, $timePrecision = false)
|
||||
{
|
||||
$httpMessage = [
|
||||
@@ -35,6 +58,9 @@ class GuzzleAdapter implements AdapterInterface, QueryableInterface
|
||||
return $this->httpClient->post($endpoint, $httpMessage);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function query($query, $timePrecision = false)
|
||||
{
|
||||
$options = [
|
||||
@@ -53,6 +79,9 @@ class GuzzleAdapter implements AdapterInterface, QueryableInterface
|
||||
return $this->httpClient->get($endpoint, $options)->json();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function getDatabases()
|
||||
{
|
||||
$options = [
|
||||
@@ -64,6 +93,9 @@ class GuzzleAdapter implements AdapterInterface, QueryableInterface
|
||||
return $this->httpClient->get($endpoint, $options)->json();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function createDatabase($name)
|
||||
{
|
||||
$httpMessage = [
|
||||
@@ -75,6 +107,9 @@ class GuzzleAdapter implements AdapterInterface, QueryableInterface
|
||||
return $this->httpClient->post($endpoint, $httpMessage)->json();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function deleteDatabase($name)
|
||||
{
|
||||
$httpMessage = [
|
||||
|
||||
@@ -0,0 +1,198 @@
|
||||
<?php
|
||||
|
||||
namespace InfluxDB\Adapter;
|
||||
|
||||
use GuzzleHttp\Client;
|
||||
use GuzzleHttp\Exception\ParseException;
|
||||
use GuzzleHttp\Message\ResponseInterface;
|
||||
use InfluxDB\Exception\InfluxAuthorizationException;
|
||||
use InfluxDB\Exception\InfluxBadResponseException;
|
||||
use InfluxDB\Exception\InfluxGeneralException;
|
||||
use InfluxDB\Exception\InfluxNoSeriesException;
|
||||
use InfluxDB\Exception\InfluxUnexpectedResponseException;
|
||||
use InfluxDB\Options;
|
||||
|
||||
class HttpAdapter implements AdapterInterface, QueryableInterface
|
||||
{
|
||||
const STATUS_CODE_OK = 200;
|
||||
const STATUS_CODE_UNAUTHORIZED = 401;
|
||||
const STATUS_CODE_FORBIDDEN = 403;
|
||||
const STATUS_CODE_BAD_REQUEST = 400;
|
||||
|
||||
/**
|
||||
* @var \InfluxDB\Options
|
||||
*/
|
||||
private $options;
|
||||
|
||||
/**
|
||||
* @var Client
|
||||
*/
|
||||
private $client;
|
||||
|
||||
/**
|
||||
* @param Options $options
|
||||
*/
|
||||
public function __construct(Options $options, Client $client = null)
|
||||
{
|
||||
$this->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);
|
||||
}
|
||||
}
|
||||
@@ -1,10 +1,34 @@
|
||||
<?php
|
||||
namespace InfluxDB\Adapter;
|
||||
|
||||
/**
|
||||
* The Adapter implement this interface if it supports database query
|
||||
*/
|
||||
interface QueryableInterface
|
||||
{
|
||||
/**
|
||||
* Make query into database
|
||||
* @param string $query
|
||||
* @param string|bool $timePrecision
|
||||
*/
|
||||
public function query($query, $timePrecision = false);
|
||||
|
||||
/**
|
||||
* Return database
|
||||
*/
|
||||
public function getDatabases();
|
||||
|
||||
/**
|
||||
* Create database
|
||||
* @param string $name
|
||||
* @return array
|
||||
*/
|
||||
public function createDatabase($name);
|
||||
|
||||
/**
|
||||
* Delete database by database
|
||||
* @param string $name
|
||||
* @return array
|
||||
*/
|
||||
public function deleteDatabase($name);
|
||||
}
|
||||
|
||||
@@ -3,20 +3,33 @@ namespace InfluxDB\Adapter;
|
||||
|
||||
use InfluxDB\Options;
|
||||
|
||||
/**
|
||||
* Clent adapter to call InfluxDb by UDP protocol
|
||||
* @link http://influxdb.com/docs/v0.6/api/reading_and_writing_data.html#writing-data-through-json-+-udp
|
||||
*/
|
||||
class UdpAdapter implements AdapterInterface
|
||||
{
|
||||
private $options;
|
||||
|
||||
/**
|
||||
* @param Options $options
|
||||
*/
|
||||
public function __construct(Options $options)
|
||||
{
|
||||
$this->options = $options;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Options
|
||||
*/
|
||||
public function getOptions()
|
||||
{
|
||||
return $this->options;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function send($message, $timePrecision = false)
|
||||
{
|
||||
$message = json_encode($message);
|
||||
|
||||
@@ -5,33 +5,68 @@ namespace InfluxDB;
|
||||
use InfluxDb\Adapter\QueryableInterface;
|
||||
use InfluxDB\Filter\FilterInterface;
|
||||
|
||||
/**
|
||||
* Client to manage request at InfluxDB
|
||||
*/
|
||||
class Client
|
||||
{
|
||||
/**
|
||||
* @var \InfluxDB\Adapter\AdapterInterface
|
||||
*/
|
||||
private $adapter;
|
||||
|
||||
/**
|
||||
* @var \InfluxDB\Filter\FilterInterface
|
||||
*/
|
||||
private $filter;
|
||||
|
||||
/**
|
||||
* Set filter
|
||||
* @param Filter\FilterInterface $filter
|
||||
* @return Client
|
||||
*/
|
||||
public function setFilter(Filter\FilterInterface $filter)
|
||||
{
|
||||
$this->filter = $filter;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get filter
|
||||
* @return Filter\FilterInterface
|
||||
*/
|
||||
public function getFilter()
|
||||
{
|
||||
return $this->filter;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set InfluxDB adapter
|
||||
* @param Adapter\AdapterInterface
|
||||
* @return Client
|
||||
*/
|
||||
public function setAdapter(Adapter\AdapterInterface $adapter)
|
||||
{
|
||||
$this->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 =[];
|
||||
@@ -45,6 +80,12 @@ class Client
|
||||
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)) {
|
||||
@@ -62,6 +103,10 @@ class Client
|
||||
return $return;
|
||||
}
|
||||
|
||||
/**
|
||||
* List of databases
|
||||
* @return array
|
||||
*/
|
||||
public function getDatabases()
|
||||
{
|
||||
if (!($this->getAdapter() instanceOf QueryableInterface)) {
|
||||
@@ -70,6 +115,10 @@ class Client
|
||||
return $this->getAdapter()->getDatabases();
|
||||
}
|
||||
|
||||
/**
|
||||
* Create database by name
|
||||
* @param string $name
|
||||
*/
|
||||
public function createDatabase($name)
|
||||
{
|
||||
if (!($this->getAdapter() instanceOf QueryableInterface)) {
|
||||
@@ -78,6 +127,10 @@ class Client
|
||||
return $this->getAdapter()->createDatabase($name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete database by name
|
||||
* @param string $name
|
||||
*/
|
||||
public function deleteDatabase($name)
|
||||
{
|
||||
if (!($this->getAdapter() instanceOf QueryableInterface)) {
|
||||
@@ -86,6 +139,11 @@ class Client
|
||||
return $this->getAdapter()->deleteDatabase($name);
|
||||
}
|
||||
|
||||
/**
|
||||
* List of time precision choose
|
||||
* @param string $timePrecision
|
||||
* @return bool|string
|
||||
*/
|
||||
private function clearTimePrecision($timePrecision)
|
||||
{
|
||||
switch ($timePrecision) {
|
||||
|
||||
@@ -4,8 +4,18 @@ namespace InfluxDB;
|
||||
use Zend\Stdlib\Hydrator\ClassMethods;
|
||||
use GuzzleHttp\Client as GuzzleClient;
|
||||
|
||||
/**
|
||||
* Create your static client
|
||||
*/
|
||||
abstract class ClientFactory
|
||||
{
|
||||
/**
|
||||
* Create new client
|
||||
* @param array $options
|
||||
* @return Client
|
||||
* @throws InvalidArgumentException If not exist adapter name
|
||||
* or not find adapter
|
||||
*/
|
||||
public static function create(array $options)
|
||||
{
|
||||
$defaultOptions = [
|
||||
@@ -38,6 +48,9 @@ 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}");
|
||||
}
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
<?php
|
||||
|
||||
namespace InfluxDB\Exception;
|
||||
|
||||
class InfluxAuthorizationException extends InfluxGeneralException
|
||||
{
|
||||
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
<?php
|
||||
|
||||
namespace InfluxDB\Exception;
|
||||
|
||||
class InfluxBadResponseException extends InfluxGeneralException
|
||||
{
|
||||
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
<?php
|
||||
|
||||
namespace InfluxDB\Exception;
|
||||
|
||||
class InfluxGeneralException extends \RuntimeException
|
||||
{
|
||||
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
<?php
|
||||
|
||||
namespace InfluxDB\Exception;
|
||||
|
||||
class InfluxNoSeriesException extends InfluxGeneralException
|
||||
{
|
||||
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
<?php
|
||||
|
||||
namespace InfluxDB\Exception;
|
||||
|
||||
class InfluxUnexpectedResponseException extends InfluxGeneralException
|
||||
{
|
||||
|
||||
}
|
||||
@@ -2,8 +2,14 @@
|
||||
|
||||
namespace InfluxDB\Filter;
|
||||
|
||||
/**
|
||||
* This filter manipulates response
|
||||
*/
|
||||
class ColumnsPointsFilter implements FilterInterface
|
||||
{
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function filter($metrics)
|
||||
{
|
||||
$response = [];
|
||||
|
||||
@@ -1,7 +1,14 @@
|
||||
<?php
|
||||
namespace InfluxDB\Filter;
|
||||
|
||||
/**
|
||||
* Every filter implement this interface
|
||||
*/
|
||||
interface FilterInterface
|
||||
{
|
||||
/**
|
||||
* Filter metrics
|
||||
* @param mixed $anything
|
||||
*/
|
||||
public function filter($anything);
|
||||
}
|
||||
|
||||
@@ -2,16 +2,44 @@
|
||||
|
||||
namespace InfluxDB;
|
||||
|
||||
/**
|
||||
* Manage in the best way InfluxDB Client Configuration
|
||||
*/
|
||||
class Options
|
||||
{
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
private $host;
|
||||
|
||||
/**
|
||||
* @var string|int
|
||||
*/
|
||||
private $port;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
private $username;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
private $password;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
private $protocol;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
private $database;
|
||||
|
||||
/**
|
||||
* Set default options
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
$this->host = "localhost";
|
||||
@@ -21,17 +49,27 @@ class Options
|
||||
$this->setProtocol("http");
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getProtocol()
|
||||
{
|
||||
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;
|
||||
@@ -43,50 +81,82 @@ 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(
|
||||
@@ -98,6 +168,11 @@ class Options
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Build http database endpoint by name
|
||||
* @param string $name
|
||||
* @return string
|
||||
*/
|
||||
public function getHttpDatabaseEndpoint($name = false)
|
||||
{
|
||||
$url = sprintf(
|
||||
|
||||
@@ -61,12 +61,13 @@ class ClientFactoryTest extends \PHPUnit_Framework_TestCase
|
||||
/**
|
||||
* @group factory
|
||||
* @group tcp
|
||||
* @dataProvider getTcpAdapters
|
||||
*/
|
||||
public function testCreateTcpClient()
|
||||
public function testCreateTcpClient($adapter)
|
||||
{
|
||||
$options = [
|
||||
"adapter" => [
|
||||
"name" => "InfluxDB\\Adapter\\GuzzleAdapter",
|
||||
"name" => $adapter,
|
||||
],
|
||||
"options" => [
|
||||
"host" => "127.0.0.1",
|
||||
@@ -78,21 +79,30 @@ class ClientFactoryTest extends \PHPUnit_Framework_TestCase
|
||||
$client = ClientFactory::create($options);
|
||||
$this->assertInstanceOf("InfluxDB\\Client", $client);
|
||||
|
||||
$this->assertInstanceOf("InfluxDB\\Adapter\\GuzzleAdapter", $client->getAdapter());
|
||||
$this->assertInstanceOf($adapter, $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());
|
||||
}
|
||||
|
||||
public function getTcpAdapters()
|
||||
{
|
||||
return [
|
||||
["InfluxDB\\Adapter\\GuzzleAdapter"],
|
||||
["InfluxDB\\Adapter\\HttpAdapter"],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @group factory
|
||||
* @group filters
|
||||
* @dataProvider getTcpAdapters
|
||||
*/
|
||||
public function testCreateTcpClientWithFilter()
|
||||
public function testCreateTcpClientWithFilter($adapter)
|
||||
{
|
||||
$options = [
|
||||
"adapter" => [
|
||||
"name" => "InfluxDB\\Adapter\\GuzzleAdapter",
|
||||
"name" => $adapter,
|
||||
],
|
||||
"options" => [
|
||||
"host" => "127.0.0.1",
|
||||
@@ -109,7 +119,7 @@ class ClientFactoryTest extends \PHPUnit_Framework_TestCase
|
||||
$client = ClientFactory::create($options);
|
||||
$this->assertInstanceOf("InfluxDB\\Client", $client);
|
||||
|
||||
$this->assertInstanceOf("InfluxDB\\Adapter\\GuzzleAdapter", $client->getAdapter());
|
||||
$this->assertInstanceOf($adapter, $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());
|
||||
|
||||
@@ -0,0 +1,128 @@
|
||||
<?php
|
||||
namespace InfluxDB;
|
||||
|
||||
use InfluxDB\Adapter\HttpAdapter;
|
||||
use InfluxDB\Adapter\UdpAdapter;
|
||||
|
||||
class HttpAdapterTest extends \PHPUnit_Framework_TestCase
|
||||
{
|
||||
private $rawOptions;
|
||||
private $object;
|
||||
private $options;
|
||||
|
||||
public function setUp()
|
||||
{
|
||||
$options = include __DIR__ . '/../bootstrap.php';
|
||||
$this->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");
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user