mirror of
https://github.com/librenms/librenms.git
synced 2024-10-07 16:52:45 +00:00
More
This commit is contained in:
@@ -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;
|
||||
}
|
||||
|
||||
}
|
@@ -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);
|
||||
}
|
||||
}
|
@@ -1,12 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace InfluxDB\Client;
|
||||
|
||||
/**
|
||||
* Class Exception
|
||||
*
|
||||
* @package InfluxDB\Client
|
||||
*/
|
||||
class Exception extends \InfluxDB\Exception
|
||||
{
|
||||
}
|
@@ -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;
|
||||
}
|
||||
}
|
@@ -1,10 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace InfluxDB\Database;
|
||||
|
||||
/**
|
||||
* @author Stephen "TheCodeAssassin" Hoogendijk
|
||||
*/
|
||||
class Exception extends \InfluxDB\Exception
|
||||
{
|
||||
}
|
@@ -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;
|
||||
}
|
||||
}
|
@@ -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();
|
||||
|
||||
}
|
@@ -1,16 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* @author Stephen "TheCodeAssassin" Hoogendijk
|
||||
*/
|
||||
|
||||
namespace InfluxDB\Driver;
|
||||
|
||||
/**
|
||||
* Class Exception
|
||||
*
|
||||
* @package InfluxDB\Driver
|
||||
*/
|
||||
class Exception extends \InfluxDB\Client\Exception
|
||||
{
|
||||
|
||||
}
|
@@ -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;
|
||||
}
|
||||
}
|
@@ -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();
|
||||
}
|
@@ -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;
|
||||
}
|
||||
}
|
@@ -1,10 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace InfluxDB;
|
||||
|
||||
/**
|
||||
* @author Stephen "TheCodeAssassin" Hoogendijk
|
||||
*/
|
||||
class Exception extends \Exception
|
||||
{
|
||||
}
|
@@ -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 server’s
|
||||
* 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;
|
||||
}
|
||||
}
|
@@ -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;
|
||||
}
|
||||
}
|
@@ -1,10 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace InfluxDB\Query;
|
||||
|
||||
/**
|
||||
* @author Stephen "TheCodeAssassin" Hoogendijk
|
||||
*/
|
||||
class Exception extends \InfluxDB\Exception
|
||||
{
|
||||
}
|
@@ -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;
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user