This commit is contained in:
laf
2015-08-19 21:54:44 +00:00
parent 28d452cda4
commit be61f522f8
186 changed files with 0 additions and 21314 deletions

View File

@@ -1,324 +0,0 @@
<?php
namespace InfluxDB;
use InfluxDB\Client\Admin;
use InfluxDB\Client\Exception as ClientException;
use InfluxDB\Driver\DriverInterface;
use InfluxDB\Driver\Exception as DriverException;
use InfluxDB\Driver\Guzzle;
use InfluxDB\Driver\QueryDriverInterface;
use InfluxDB\Driver\UDP;
/**
* Class Client
*
* @package InfluxDB
* @author Stephen "TheCodeAssassin" Hoogendijk
*/
class Client
{
/**
* @var Admin
*/
public $admin;
/**
* @var string
*/
protected $host = '';
/**
* @var int
*/
protected $port = 8086;
/**
* @var string
*/
protected $username = '';
/**
* @var string
*/
protected $password = '';
/**
* @var int
*/
protected $timeout = 0;
/**
* @var bool
*/
protected $scheme = 'http';
/**
* @var bool
*/
protected $verifySSL = false;
/**
* @var bool
*/
protected $useUdp = false;
/**
* @var int
*/
protected $udpPort = 4444;
/**
* @var
*/
protected $baseURI;
/**
* @var \Guzzle\Http\Client
*/
protected $httpClient;
/**
* @var array
*/
protected $options = array();
/**
* @var DriverInterface
*/
protected $driver;
/**
* @param string $host
* @param int $port
* @param string $username
* @param string $password
* @param bool $ssl
* @param bool $verifySSL
* @param int $timeout
*/
public function __construct(
$host,
$port = 8086,
$username = '',
$password = '',
$ssl = false,
$verifySSL = true,
$timeout = 0
) {
$this->host = (string) $host;
$this->port = (int) $port;
$this->username = (string) $username;
$this->password = (string) $password;
$this->timeout = (int) $timeout;
$this->verifySSL = (bool) $verifySSL;
if ($ssl) {
$this->scheme = 'https';
$this->options['verify'] = $verifySSL;
}
// the the base URI
$this->baseURI = sprintf('%s://%s:%d', $this->scheme, $this->host, $this->port);
// set the default driver to guzzle
$this->driver = new Guzzle(
new \GuzzleHttp\Client(
[
'timeout' => $this->timeout,
'base_uri' => $this->baseURI,
'verify' => $this->verifySSL
]
)
);
$this->admin = new Admin($this);
}
/**
* Use the given database
*
* @param string $name
* @return Database
*/
public function selectDB($name)
{
return new Database($name, $this);
}
/**
* Query influxDB
*
* @param string $database
* @param string $query
* @param array $parameters
*
* @return ResultSet
* @throws Exception
*/
public function query($database, $query, $parameters = [])
{
if (!$this->driver instanceof QueryDriverInterface) {
throw new Exception('The currently configured driver does not support query operations');
}
if ($database) {
$parameters['db'] = $database;
}
$driver = $this->getDriver();
$parameters = [
'url' => 'query?' . http_build_query(array_merge(['q' => $query], $parameters)),
'database' => $database,
'method' => 'get'
];
// add authentication to the driver if needed
if (!empty($this->username) && !empty($this->password)) {
$parameters += ['auth' => [$this->username, $this->password]];
}
$driver->setParameters($parameters);
try {
// perform the query and return the resultset
return $driver->query();
} catch (DriverException $e) {
throw new Exception('Query has failed', $e->getCode(), $e);
}
}
/**
* List all the databases
*/
public function listDatabases()
{
$result = $this->query(null, 'SHOW DATABASES')->getPoints();
return $this->pointsToArray($result);
}
/**
* List all the users
*
* @return array
* @throws Exception
*/
public function listUsers()
{
$result = $this->query(null, 'SHOW USERS')->getPoints();
return $this->pointsToArray($result);
}
/**
* Build the client from a dsn
* Examples:
*
* https+influxdb://username:pass@localhost:8086/databasename
* udp+influxdb://username:pass@localhost:4444/databasename
*
* @param string $dsn
* @param int $timeout
* @param bool $verifySSL
*
*@return Client|Database
* @throws ClientException
*/
public static function fromDSN($dsn, $timeout = 0, $verifySSL = false)
{
$connParams = parse_url($dsn);
$schemeInfo = explode('+', $connParams['scheme']);
$dbName = null;
$modifier = null;
$scheme = $schemeInfo[0];
if (isset($schemeInfo[1])) {
$modifier = strtolower($schemeInfo[0]);
$scheme = $schemeInfo[1];
}
if ($scheme != 'influxdb') {
throw new ClientException($scheme . ' is not a valid scheme');
}
$ssl = $modifier === 'https' ? true : false;
$dbName = $connParams['path'] ? substr($connParams['path'], 1) : null;
$client = new self(
$connParams['host'],
$connParams['port'],
$connParams['user'],
$connParams['pass'],
$ssl,
$verifySSL,
$timeout
);
// set the UDP driver when the DSN specifies UDP
if ($modifier == 'udp') {
$client->setDriver(new UDP($connParams['host'], $connParams['port']));
}
return ($dbName ? $client->selectDB($dbName) : $client);
}
/**
* @return mixed
*/
public function getBaseURI()
{
return $this->baseURI;
}
/**
* @return int
*/
public function getTimeout()
{
return $this->timeout;
}
/**
* @param Driver\DriverInterface $driver
*/
public function setDriver(DriverInterface $driver)
{
$this->driver = $driver;
}
/**
* @return DriverInterface|QueryDriverInterface
*/
public function getDriver()
{
return $this->driver;
}
/**
* @return string
*/
public function getHost()
{
return $this->host;
}
/**
* @param Point[] $points
* @return array
*/
protected function pointsToArray(array $points)
{
$names = [];
foreach ($points as $item) {
$names[] = $item['name'];
}
return $names;
}
}

View File

@@ -1,158 +0,0 @@
<?php
/**
* @author Stephen "TheCodeAssassin" Hoogendijk
*/
namespace InfluxDB\Client;
use InfluxDB\Client;
use InfluxDB\Database;
/**
* Class Admin
*
* @package InfluxDB\Client
*/
class Admin
{
/**
* @var Client
*/
private $client;
const PRIVILEGE_READ = 'READ';
const PRIVILEGE_WRITE = 'WRITE';
const PRIVILEGE_ALL= 'ALL';
public function __construct(Client $client)
{
$this->client = $client;
}
/**
* Create a user
*
* @param string $username
* @param string $password
*
* @param string $privilege
*
* @throws \InfluxDB\Exception
* @return \InfluxDB\ResultSet
*/
public function createUser($username, $password, $privilege = null)
{
$query = sprintf('CREATE USER %s WITH PASSWORD \'%s\'', $username, $password);
if ($privilege) {
$query .= " WITH $privilege PRIVILEGES";
}
return $this->client->query(null, $query);
}
/**
* @param string $username
*
* @return \InfluxDB\ResultSet
* @throws \InfluxDB\Exception
*/
public function dropUser($username)
{
return $this->client->query(null, 'DROP USER ' . $username);
}
/**
* Change a users password
*
* @param string $username
* @param string $newPassword
*
* @return \InfluxDB\ResultSet
* @throws \InfluxDB\Exception
*/
public function changeUserPassword($username, $newPassword)
{
return $this->client->query(null, "SET PASSWORD FOR $username = '$newPassword'");
}
/**
* Shows a list of all the users
*
* @return \InfluxDB\ResultSet
* @throws \InfluxDB\Exception
*/
public function showUsers()
{
return $this->client->query(null, "SHOW USERS");
}
/**
* Grants permissions
*
* @param string $privilege
* @param string $username
* @param Database|string $database
*
* @return \InfluxDB\ResultSet
*/
public function grant($privilege, $username, $database = null)
{
return $this->executePrivilege('GRANT', $privilege, $username, $database);
}
/**
* Revokes permissions
*
* @param string $privilege
* @param string $username
* @param Database|string $database
*
* @throws \InfluxDB\Exception
* @return \InfluxDB\ResultSet
*/
public function revoke($privilege, $username, $database = null)
{
return $this->executePrivilege('REVOKE', $privilege, $username, $database);
}
/**
* @param string $type
* @param string $privilege
* @param string $username
* @param Database|string $database
*
* @throws \InfluxDB\Exception
* @return \InfluxDB\ResultSet
*/
private function executePrivilege($type, $privilege, $username, $database = null)
{
if (!in_array($privilege, [self::PRIVILEGE_READ, self::PRIVILEGE_WRITE, self::PRIVILEGE_ALL])) {
throw new Exception($privilege . ' is not a valid privileges, allowed privileges: READ, WRITE, ALL');
}
if ($privilege != self::PRIVILEGE_ALL && !$database) {
throw new Exception('Only grant ALL cluster-wide privileges are allowed');
}
$database = ($database instanceof Database ? $database->getName() : (string) $database);
$query = "$type $privilege";
if ($database) {
$query .= sprintf(' ON %s ', $database);
} else {
$query .= " PRIVILEGES ";
}
if ($username && $type == 'GRANT') {
$query .= "TO $username";
} elseif ($username && $type == 'REVOKE') {
$query .= "FROM $username";
}
return $this->client->query(null, $query);
}
}

View File

@@ -1,12 +0,0 @@
<?php
namespace InfluxDB\Client;
/**
* Class Exception
*
* @package InfluxDB\Client
*/
class Exception extends \InfluxDB\Exception
{
}

View File

@@ -1,232 +0,0 @@
<?php
namespace InfluxDB;
use InfluxDB\Database\Exception as DatabaseException;
use InfluxDB\Database\RetentionPolicy;
use InfluxDB\Query\Builder as QueryBuilder;
/**
* Class Database
*
* @package InfluxDB
* @author Stephen "TheCodeAssassin" Hoogendijk
*/
class Database
{
/**
* The name of the Database
*
* @var string
*/
protected $name = '';
/**
* @var Client
*/
protected $client;
/**
* Precision constants
*/
const PRECISION_NANOSECONDS = 'n';
const PRECISION_MICROSECONDS = 'u';
const PRECISION_MILLISECONDS = 'ms';
const PRECISION_SECONDS = 's';
const PRECISION_MINUTES = 'm';
const PRECISION_HOURS = 'h';
/**
* Construct a database object
*
* @param string $name
* @param Client $client
*/
public function __construct($name, Client $client)
{
if (empty($name)) {
throw new \InvalidArgumentException('No database name provided');
}
$this->name = (string) $name;
$this->client = $client;
}
/**
* @return string
*/
public function getName()
{
return $this->name;
}
/**
* Query influxDB
*
* @param string $query
* @param array $params
* @return ResultSet
* @throws Exception
*/
public function query($query, $params = [])
{
return $this->client->query($this->name, $query, $params);
}
/**
* Create this database
*
* @param RetentionPolicy $retentionPolicy
* @return ResultSet
* @throws DatabaseException
* @throws Exception
*/
public function create(RetentionPolicy $retentionPolicy = null)
{
try {
$this->query(sprintf('CREATE DATABASE %s', $this->name));
if ($retentionPolicy) {
$this->createRetentionPolicy($retentionPolicy);
}
} catch (\Exception $e) {
throw new DatabaseException(
sprintf('Failed to created database %s', $this->name),
$e->getCode(),
$e
);
}
}
/**
* @param RetentionPolicy $retentionPolicy
* @return ResultSet
*/
public function createRetentionPolicy(RetentionPolicy $retentionPolicy)
{
return $this->query($this->getRetentionPolicyQuery('CREATE', $retentionPolicy));
}
/**
* Writes points into InfluxDB
*
* @param Point[] $points Array of points
* @param string $precision The timestamp precision (defaults to nanoseconds)
* @return bool
* @throws Exception
*/
public function writePoints(array $points, $precision = self::PRECISION_NANOSECONDS)
{
$payload = array_map(
function (Point $point) {
return (string) $point;
},
$points
);
try {
$driver = $this->client->getDriver();
$parameters = [
'url' => sprintf('write?db=%s&precision=%s', $this->name, $precision),
'database' => $this->name,
'method' => 'post'
];
// add authentication to the driver if needed
if (!empty($this->username) && !empty($this->password)) {
$parameters += ['auth' => [$this->username, $this->password]];
}
$driver->setParameters($parameters);
// send the points to influxDB
$driver->write(implode(PHP_EOL, $payload));
return $driver->isSuccess();
} catch (\Exception $e) {
throw new Exception($e->getMessage(), $e->getCode());
}
}
/**
* @return bool
*/
public function exists()
{
$databases = $this->client->listDatabases();
return in_array($this->name, $databases);
}
/**
* @param RetentionPolicy $retentionPolicy
*/
public function alterRetentionPolicy(RetentionPolicy $retentionPolicy)
{
$this->query($this->getRetentionPolicyQuery('ALTER', $retentionPolicy));
}
/**
* @return array
* @throws Exception
*/
public function listRetentionPolicies()
{
return $this->query(sprintf('SHOW RETENTION POLICIES %s', $this->name))->getPoints();
}
/**
* Drop this database
*/
public function drop()
{
$this->query(sprintf('DROP DATABASE %s', $this->name));
}
/**
* Retrieve the query builder
*
* @return QueryBuilder
*/
public function getQueryBuilder()
{
return new QueryBuilder($this);
}
/**
* @return Client
*/
public function getClient()
{
return $this->client;
}
/**
* @param string $method
* @param RetentionPolicy $retentionPolicy
* @return string
*/
protected function getRetentionPolicyQuery($method, RetentionPolicy $retentionPolicy)
{
if (!in_array($method, ['CREATE', 'ALTER'])) {
throw new \InvalidArgumentException(sprintf('%s is not a valid method'));
}
$query = sprintf(
'%s RETENTION POLICY %s ON %s DURATION %s REPLICATION %s',
$method,
$retentionPolicy->name,
$this->name,
$retentionPolicy->duration,
$retentionPolicy->replication
);
if ($retentionPolicy->default) {
$query .= " DEFAULT";
}
return $query;
}
}

View File

@@ -1,10 +0,0 @@
<?php
namespace InfluxDB\Database;
/**
* @author Stephen "TheCodeAssassin" Hoogendijk
*/
class Exception extends \InfluxDB\Exception
{
}

View File

@@ -1,48 +0,0 @@
<?php
namespace InfluxDB\Database;
/**
* Class RetentionPolicy
*
* @package InfluxDB\Database
* @author Stephen "TheCodeAssassin" Hoogendijk
*/
class RetentionPolicy
{
/**
* @var string
*/
public $name;
/**
* @var string
*/
public $duration;
/**
* @var int
*/
public $replication;
/**
* @var bool
*/
public $default;
/**
* @param string $name
* @param string $duration
* @param int $replication
* @param bool $default
*
* @todo validate duration, replication
*/
public function __construct($name, $duration = '1d', $replication = 1, $default = false)
{
$this->name = (string) $name;
$this->duration = $duration;
$this->replication = (int) $replication;
$this->default = (bool) $default;
}
}

View File

@@ -1,49 +0,0 @@
<?php
/**
* @author Stephen "TheCodeAssassin" Hoogendijk
*/
namespace InfluxDB\Driver;
/**
* Interface DriverInterface
*
* @package InfluxDB\Driver
*/
interface DriverInterface
{
/**
* Called by the client write() method, will pass an array of required parameters such as db name
*
* will contain the following parameters:
*
* [
* 'database' => 'name of the database',
* 'url' => 'URL to the resource',
* 'method' => 'HTTP method used'
* ]
*
* @param array $parameters
*
* @return mixed
*/
public function setParameters(array $parameters);
/**
* Send the data
*
* @param $data
*
* @return mixed
*/
public function write($data = null);
/**
* Should return if sending the data was successful
*
* @return bool
*/
public function isSuccess();
}

View File

@@ -1,16 +0,0 @@
<?php
/**
* @author Stephen "TheCodeAssassin" Hoogendijk
*/
namespace InfluxDB\Driver;
/**
* Class Exception
*
* @package InfluxDB\Driver
*/
class Exception extends \InfluxDB\Client\Exception
{
}

View File

@@ -1,134 +0,0 @@
<?php
/**
* @author Stephen "TheCodeAssassin" Hoogendijk
*/
namespace InfluxDB\Driver;
use GuzzleHttp\Client;
use Guzzle\Http\Message\Response;
use GuzzleHttp\Exception\ClientException;
use GuzzleHttp\Psr7\Request;
use InfluxDB\ResultSet;
/**
* Class Guzzle
*
* @package InfluxDB\Driver
*/
class Guzzle implements DriverInterface, QueryDriverInterface
{
/**
* Array of options
*
* @var array
*/
private $parameters;
/**
* @var Client
*/
private $httpClient;
/**
* @var Response
*/
private $response;
/**
* Set the config for this driver
*
* @param Client $client
*
* @return mixed
*/
public function __construct(Client $client)
{
$this->httpClient = $client;
}
/**
* Called by the client write() method, will pass an array of required parameters such as db name
*
* will contain the following parameters:
*
* [
* 'database' => 'name of the database',
* 'url' => 'URL to the resource',
* 'method' => 'HTTP method used'
* ]
*
* @param array $parameters
*
* @return mixed
*/
public function setParameters(array $parameters)
{
$this->parameters = $parameters;
}
/**
* Send the data
*
* @param $data
*
* @throws Exception
* @return mixed
*/
public function write($data = null)
{
$this->response = $this->httpClient->post($this->parameters['url'], $this->getRequestParameters($data));
}
/**
* @throws Exception
* @return ResultSet
*/
public function query()
{
$response = $this->httpClient->get($this->parameters['url'], $this->getRequestParameters());
$raw = (string) $response->getBody();
$responseJson = json_encode($raw);
if (isset($responseJson->error)) {
throw new Exception($responseJson->error);
}
return new ResultSet($raw);
}
/**
* Should return if sending the data was successful
*
* @return bool
*/
public function isSuccess()
{
return in_array($this->response->getStatusCode(), ['200', '204']);
}
/**
* @param null $data
*
* @return array
*/
protected function getRequestParameters($data = null)
{
$requestParameters = ['http_errors' => false];
if ($data) {
$requestParameters += ['body' => $data];
}
if (isset($this->parameters['auth'])) {
$requestParameters += ['auth' => $this->parameters['auth']];
}
return $requestParameters;
}
}

View File

@@ -1,22 +0,0 @@
<?php
/**
* @author Stephen "TheCodeAssassin" Hoogendijk
*/
namespace InfluxDB\Driver;
use InfluxDB\ResultSet;
/**
* Interface QueryDriverInterface
*
* @package InfluxDB\Driver
*/
interface QueryDriverInterface
{
/**
* @return ResultSet
*/
public function query();
}

View File

@@ -1,90 +0,0 @@
<?php
/**
* @author Stephen "TheCodeAssassin" Hoogendijk
*/
namespace InfluxDB\Driver;
use Symfony\Component\Config\Definition\Exception\Exception;
/**
* Class UDP
*
* @package InfluxDB\Driver
*/
class UDP implements DriverInterface
{
/**
* Parameters
*
* @var array
*/
private $parameters;
/**
* @var array
*/
private $config;
/**
* @param string $host IP/hostname of the InfluxDB host
* @param int $port Port of the InfluxDB process
*/
public function __construct($host, $port)
{
$this->config['host'] = $host;
$this->config['port'] = $port;
}
/**
* Called by the client write() method, will pass an array of required parameters such as db name
*
* will contain the following parameters:
*
* [
* 'database' => 'name of the database',
* 'url' => 'URL to the resource',
* 'method' => 'HTTP method used'
* ]
*
* @param array $parameters
*
* @return mixed
*/
public function setParameters(array $parameters)
{
$this->parameters = $parameters;
}
/**
* Send the data
*
* @param $data
*
* @return mixed
*/
public function write($data = null)
{
$host = sprintf('udp://%s:%d', $this->config['host'], $this->config['port']);
// stream the data using UDP and suppress any errors
$stream = @stream_socket_client($host);
@stream_socket_sendto($stream, $data);
@fclose($stream);
return true;
}
/**
* Should return if sending the data was successful
*
* @return bool
*/
public function isSuccess()
{
return true;
}
}

View File

@@ -1,10 +0,0 @@
<?php
namespace InfluxDB;
/**
* @author Stephen "TheCodeAssassin" Hoogendijk
*/
class Exception extends \Exception
{
}

View File

@@ -1,126 +0,0 @@
<?php
namespace InfluxDB;
use InfluxDB\Database\Exception as DatabaseException;
/**
* Class Point
*
* @package InfluxDB
*/
class Point
{
/**
* @var string
*/
private $measurement;
/**
* @var array
*/
private $tags = [];
/**
* @var array
*/
private $fields = [];
/**
* @var string
*/
private $timestamp;
/**
* The timestamp is optional. If you do not specify a timestamp the servers
* local timestamp will be used
*
* @param string $measurement
* @param float $value
* @param array $tags
* @param array $additionalFields
* @param null $timestamp
* @throws DatabaseException
*/
public function __construct(
$measurement,
$value = null,
array $tags = array(),
array $additionalFields = array(),
$timestamp = null
) {
if (empty($measurement)) {
throw new DatabaseException('Invalid measurement name provided');
}
$this->measurement = (string) $measurement;
$this->tags = $tags;
$this->fields = $additionalFields;
if ($value) {
$this->fields['value'] = $value;
}
if ($timestamp && !$this->isValidTimeStamp($timestamp)) {
throw new DatabaseException(sprintf('%s is not a valid timestamp', $timestamp));
}
$this->timestamp = $timestamp;
}
/**
* @see: https://influxdb.com/docs/v0.9/concepts/reading_and_writing_data.html
*
* Should return this format
* 'cpu_load_short,host=server01,region=us-west value=0.64 1434055562000000000'
*/
public function __toString()
{
$string = $this->measurement;
if (count($this->tags) > 0) {
$string .= ',' . $this->arrayToString($this->tags);
}
$string .= ' ' . $this->arrayToString($this->fields);
if ($this->timestamp) {
$string .= ' '.$this->timestamp;
}
return $string;
}
/**
* @param array $arr
* @return string
*/
private function arrayToString(array $arr)
{
$strParts = [];
foreach ($arr as $key => $value) {
$strParts[] = sprintf('%s=%s', $key, $value);
}
return implode(',', $strParts);
}
/**
* @param int $timestamp
* @return bool
*/
private function isValidTimeStamp($timestamp)
{
if ((int) $timestamp === $timestamp) {
return true;
}
if ($timestamp <= PHP_INT_MAX && $timestamp >= ~PHP_INT_MAX) {
return true;
}
return false;
}
}

View File

@@ -1,271 +0,0 @@
<?php
namespace InfluxDB\Query;
use InfluxDB\Database;
use InfluxDB\ResultSet;
/**
* Class Builder
*
* Abstraction class for getting time series out of InfluxDB
*
* Sample usage:
*
* $series = new QueryBuilder($db);
* $series->percentile(95)->setTimeRange($timeFrom, $timeTo)->getResult();
*
* $series->select('*')->from('*')->getResult();
*
* @todo add inner join
* @todo add merge
*
* @package InfluxDB\Query
* @author Stephen "TheCodeAssassin" Hoogendijk <s.hoogendijk@tech.leaseweb.com>
*/
class Builder
{
/**
* @var Database
*/
protected $db;
/**
* @var string
*/
protected $selection = '*';
/**
* @var string[]
*/
protected $where = array();
/**
* @var string
*/
protected $startTime;
/**
* @var string
*/
protected $endTime;
/**
* @var string
*/
protected $metric;
/**
* @var string
*/
protected $limitClause = '';
/**
* @param Database $db
*/
public function __construct(Database $db)
{
$this->db = $db;
}
/**
* @param string $metric The metric to select (required)
* @return $this
*/
public function from($metric)
{
$this->metric = $metric;
return $this;
}
/**
* Custom select method
*
* example:
*
* $series->select('sum(value)',
*
* @param string $customSelect
* @return $this
*/
public function select($customSelect)
{
$this->selection = $customSelect;
return $this;
}
/**
* @param array $conditions
*
* Example: array('time > now()', 'time < now() -1d');
*
* @return $this
*/
public function where(array $conditions)
{
foreach ($conditions as $condition) {
$this->where[] = $condition;
}
return $this;
}
/**
* @param string $field
* @return $this
*/
public function count($field = 'type')
{
$this->selection = sprintf('count(%s)', $field);
return $this;
}
/**
* @param string $field
* @return $this
*/
public function median($field = 'type')
{
$this->selection = sprintf('median(%s)', $field);
return $this;
}
/**
* @param string $field
* @return $this
*/
public function mean($field = 'type')
{
$this->selection = sprintf('mean(%s)', $field);
return $this;
}
/**
* @param string $field
* @return $this
*/
public function sum($field = 'type')
{
$this->selection = sprintf('sum(%s)', $field);
return $this;
}
/**
* @param string $field
* @return $this
*/
public function first($field = 'type')
{
$this->selection = sprintf('first(%s)', $field);
return $this;
}
/**
* @param string $field
* @return $this
*/
public function last($field = 'type')
{
$this->selection = sprintf('last(%s)', $field);
return $this;
}
/**
* Set's the time range to select data from
*
* @param int $from
* @param int $to
* @return $this
*/
public function setTimeRange($from, $to)
{
$fromDate = date('Y-m-d H:i:s', (int) $from);
$toDate = date('Y-m-d H:i:s', (int) $to);
$this->where(array("time > '$fromDate'", "time < '$toDate'"));
return $this;
}
/**
* @param int $percentile Percentage to select (for example 95 for 95th percentile billing)
*
* @return $this
*/
public function percentile($percentile = 95)
{
$this->selection = sprintf('percentile(value, %d)', (int) $percentile);
return $this;
}
/**
* Limit the ResultSet to n records
*
* @param int $count
*
* @return $this
*/
public function limit($count)
{
$this->limitClause = sprintf(' LIMIT %s', (int) $count);
return $this;
}
/**
* @return string
*/
public function getQuery()
{
return $this->parseQuery();
}
/**
* Gets the result from the database (builds the query)
*
* @return ResultSet
*/
public function getResultSet()
{
return $this->db->query($this->parseQuery());
}
/**
* @return string
*/
protected function parseQuery()
{
$query = sprintf("SELECT %s FROM %s", $this->selection, $this->metric);
if (! $this->metric) {
throw new \InvalidArgumentException('No metric provided to from()');
}
for ($i = 0; $i < count($this->where); $i++) {
$selection = 'WHERE';
if ($i > 0) {
$selection = 'AND';
}
$clause = $this->where[$i];
$query .= ' ' . $selection . ' ' . $clause;
}
if ($this->limitClause) {
$query .= $this->limitClause;
}
return $query;
}
}

View File

@@ -1,10 +0,0 @@
<?php
namespace InfluxDB\Query;
/**
* @author Stephen "TheCodeAssassin" Hoogendijk
*/
class Exception extends \InfluxDB\Exception
{
}

View File

@@ -1,106 +0,0 @@
<?php
namespace InfluxDB;
use InfluxDB\Client\Exception as ClientException;
/**
* Class ResultSet
*
* @package InfluxDB
* @author Stephen "TheCodeAssassin" Hoogendijk
*/
class ResultSet
{
/**
* @var array|mixed
*/
protected $parsedResults = [];
/**
* @param string $raw
* @throws \InvalidArgumentException
* @throws Exception
*/
public function __construct($raw)
{
$this->parsedResults = json_decode((string) $raw, true);
if (json_last_error() !== JSON_ERROR_NONE) {
throw new \InvalidArgumentException('Invalid JSON');
}
// There was an error in the query thrown by influxdb
if (isset($this->parsedResults['error'])) {
throw new ClientException($this->parsedResults['error']);
}
// Check if there are errors in the first serie
if (isset($this->parsedResults['results'][0]['error'])) {
throw new ClientException($this->parsedResults['results'][0]['error']);
}
}
/**
* @param $metricName
* @param array $tags
* @return array $points
*/
public function getPoints($metricName = '', array $tags = array())
{
$points = [];
$series = $this->getSeries();
foreach ($series as $serie) {
if ((empty($metricName) && empty($tags)
|| $serie['name'] == $metricName
|| (isset($serie['tags']) && array_intersect($tags, $serie['tags'])))
&& isset($serie['values'])
) {
$points = array_merge($points, $this->getPointsFromSerie($serie));
}
}
return $points;
}
/**
* @see: https://influxdb.com/docs/v0.9/concepts/reading_and_writing_data.html
*
* results is an array of objects, one for each query,
* each containing the keys for a series
*
* @throws Exception
* @return array $series
*/
public function getSeries()
{
$series = array_map(
function ($object) {
if (isset($object['error'])) {
throw new ClientException($object['error']);
}
return isset($object['series']) ? $object['series'] : [];
},
$this->parsedResults['results']
);
return array_shift($series);
}
/**
* @param array $serie
* @return array
*/
private function getPointsFromSerie(array $serie)
{
$points = [];
foreach ($serie['values'] as $point) {
$points[] = array_combine($serie['columns'], $point);
}
return $points;
}
}