Skip to content
This repository has been archived by the owner on Oct 22, 2019. It is now read-only.

Add Predis support #55

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 4 additions & 2 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,13 @@
"guzzlehttp/guzzle": "^6.2"
},
"require-dev": {
"phpunit/phpunit": "4.1.0"
"phpunit/phpunit": "4.1.0",
"predis/predis": "^1.1"
},
"suggest": {
"ext-redis": "Required if using Redis.",
"ext-apc": "Required if using APCu."
"predis/predis": "Required if using Predis",
"ext-apcu": "Required if using APCu."
},
"autoload": {
"psr-0": {
Expand Down
19 changes: 7 additions & 12 deletions examples/flush_adapter.php
Original file line number Diff line number Diff line change
@@ -1,17 +1,12 @@
<?php
require __DIR__ . '/../vendor/autoload.php';

$adapter = $_GET['adapter'];
$adapter = require __DIR__ . '/initialize.php';

if ($adapter === 'redis') {
define('REDIS_HOST', isset($_SERVER['REDIS_HOST']) ? $_SERVER['REDIS_HOST'] : '127.0.0.1');

$redisAdapter = new Prometheus\Storage\Redis(array('host' => REDIS_HOST));
$redisAdapter->flushRedis();
} elseif ($adapter === 'apc') {
$apcAdapter = new Prometheus\Storage\APC();
$apcAdapter->flushAPC();
} elseif ($adapter === 'in-memory') {
$inMemoryAdapter = new Prometheus\Storage\InMemory();
$inMemoryAdapter->flushMemory();
if ($adapter instanceof \Prometheus\Storage\Redis) {
$adapter->flushRedis();
} elseif ($adapter instanceof \Prometheus\Storage\APC) {
$adapter->flushAPC();
} elseif ($adapter instanceof \Prometheus\Storage\InMemory) {
$adapter->flushMemory();
}
21 changes: 21 additions & 0 deletions examples/initialize.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
<?php

$adapterName = $_GET['adapter'];

switch($adapterName) {
case "redis":
return \Prometheus\Storage\Redis::usingRedis(
new \Redis(),
array('host' => isset($_SERVER['REDIS_HOST']) ? $_SERVER['REDIS_HOST'] : '127.0.0.1')
);
case "predis":
return Prometheus\Storage\Redis::usingPredis(
new \Predis\Client(['host' => isset($_SERVER['REDIS_HOST']) ? $_SERVER['REDIS_HOST'] : '127.0.0.1'])
);
case "apc":
return new Prometheus\Storage\APC();
case "in-memory":
return new Prometheus\Storage\InMemory();
default:
throw new \RuntimeException(sprintf('Adapter "" is not supported', $adapterName));
}
10 changes: 1 addition & 9 deletions examples/metrics.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,16 +6,8 @@
use Prometheus\RenderTextFormat;
use Prometheus\Storage\Redis;

$adapter = $_GET['adapter'];
$adapter = require __DIR__ . '/initialize.php';

if ($adapter === 'redis') {
Redis::setDefaultOptions(array('host' => isset($_SERVER['REDIS_HOST']) ? $_SERVER['REDIS_HOST'] : '127.0.0.1'));
$adapter = new Prometheus\Storage\Redis();
} elseif ($adapter === 'apc') {
$adapter = new Prometheus\Storage\APC();
} elseif ($adapter === 'in-memory') {
$adapter = new Prometheus\Storage\InMemory();
}
$registry = new CollectorRegistry($adapter);
$renderer = new RenderTextFormat();
$result = $renderer->render($registry->getMetricFamilySamples());
Expand Down
11 changes: 1 addition & 10 deletions examples/pushgateway.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,7 @@
use Prometheus\Storage\Redis;
use Prometheus\CollectorRegistry;

$adapter = $_GET['adapter'];

if ($adapter === 'redis') {
Redis::setDefaultOptions(array('host' => isset($_SERVER['REDIS_HOST']) ? $_SERVER['REDIS_HOST'] : '127.0.0.1'));
$adapter = new Prometheus\Storage\Redis();
} elseif ($adapter === 'apc') {
$adapter = new Prometheus\Storage\APC();
} elseif ($adapter === 'in-memory') {
$adapter = new Prometheus\Storage\InMemory();
}
$adapter = require __DIR__ . '/initialize.php';

$registry = new CollectorRegistry($adapter);

Expand Down
11 changes: 1 addition & 10 deletions examples/some_counter.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,7 @@
use Prometheus\CollectorRegistry;
use Prometheus\Storage\Redis;

$adapter = $_GET['adapter'];

if ($adapter === 'redis') {
Redis::setDefaultOptions(array('host' => isset($_SERVER['REDIS_HOST']) ? $_SERVER['REDIS_HOST'] : '127.0.0.1'));
$adapter = new Prometheus\Storage\Redis();
} elseif ($adapter === 'apc') {
$adapter = new Prometheus\Storage\APC();
} elseif ($adapter === 'in-memory') {
$adapter = new Prometheus\Storage\InMemory();
}
$adapter = require __DIR__ . '/initialize.php';
$registry = new CollectorRegistry($adapter);

$counter = $registry->registerCounter('test', 'some_counter', 'it increases', ['type']);
Expand Down
11 changes: 1 addition & 10 deletions examples/some_gauge.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,16 +8,7 @@

error_log('c='. $_GET['c']);

$adapter = $_GET['adapter'];

if ($adapter === 'redis') {
Redis::setDefaultOptions(array('host' => isset($_SERVER['REDIS_HOST']) ? $_SERVER['REDIS_HOST'] : '127.0.0.1'));
$adapter = new Prometheus\Storage\Redis();
} elseif ($adapter === 'apc') {
$adapter = new Prometheus\Storage\APC();
} elseif ($adapter === 'in-memory') {
$adapter = new Prometheus\Storage\InMemory();
}
$adapter = require __DIR__ . '/initialize.php';
$registry = new CollectorRegistry($adapter);

$gauge = $registry->registerGauge('test', 'some_gauge', 'it sets', ['type']);
Expand Down
11 changes: 1 addition & 10 deletions examples/some_histogram.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,16 +7,7 @@

error_log('c='. $_GET['c']);

$adapter = $_GET['adapter'];

if ($adapter === 'redis') {
Redis::setDefaultOptions(array('host' => isset($_SERVER['REDIS_HOST']) ? $_SERVER['REDIS_HOST'] : '127.0.0.1'));
$adapter = new Prometheus\Storage\Redis();
} elseif ($adapter === 'apc') {
$adapter = new Prometheus\Storage\APC();
} elseif ($adapter === 'in-memory') {
$adapter = new Prometheus\Storage\InMemory();
}
$adapter = require __DIR__ . '/initialize.php';
$registry = new CollectorRegistry($adapter);

$histogram = $registry->registerHistogram('test', 'some_histogram', 'it observes', ['type'], [0.1, 1, 2, 3.5, 4, 5, 6, 7, 8, 9]);
Expand Down
4 changes: 2 additions & 2 deletions src/Prometheus/PushGateway.php
Original file line number Diff line number Diff line change
Expand Up @@ -49,9 +49,9 @@ public function pushAdd(CollectorRegistry $collectorRegistry, $job, $groupingKey
* @param $job
* @param $groupingKey
*/
public function delete($job, $groupingKey = null)
public function delete(CollectorRegistry $collectorRegistry, $job, $groupingKey = null)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

$collectorRegistry is left out on purpose here. It's not being used anyways. Modeled after the Python implementation which also leaves out the registry when doing a delete.

{
$this->doRequest(null, $job, $groupingKey, 'delete');
$this->doRequest($collectorRegistry, $job, $groupingKey, 'delete');
}

/**
Expand Down
98 changes: 30 additions & 68 deletions src/Prometheus/Storage/Redis.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
namespace Prometheus\Storage;


use Predis\Client;
use Prometheus\Counter;
use Prometheus\Exception\StorageException;
use Prometheus\Gauge;
Expand All @@ -13,55 +14,40 @@ class Redis implements Adapter
{
const PROMETHEUS_METRIC_KEYS_SUFFIX = '_METRIC_KEYS';

private static $defaultOptions = array();
private static $prefix = 'PROMETHEUS_';
private $prefix = 'PROMETHEUS_';

private $options;
private $redis;

public function __construct(array $options = array())
/**
* Redis constructor.
* @param RedisAdapter $redis
* @param string $prefix
*/
public function __construct(RedisAdapter $redis, $prefix = 'PROMETHEUS_')
{
// with php 5.3 we cannot initialize the options directly on the field definition
// so we initialize them here for now
if (!isset(self::$defaultOptions['host'])) {
self::$defaultOptions['host'] = '127.0.0.1';
}
if (!isset(self::$defaultOptions['port'])) {
self::$defaultOptions['port'] = 6379;
}
if (!isset(self::$defaultOptions['timeout'])) {
self::$defaultOptions['timeout'] = 0.1; // in seconds
}
if (!isset(self::$defaultOptions['read_timeout'])) {
self::$defaultOptions['read_timeout'] = 10; // in seconds
}
if (!isset(self::$defaultOptions['persistent_connections'])) {
self::$defaultOptions['persistent_connections'] = false;
}
if (!isset(self::$defaultOptions['password'])) {
self::$defaultOptions['password'] = null;
}

$this->options = array_merge(self::$defaultOptions, $options);
$this->redis = new \Redis();
$this->redis = $redis;
}

/**
* @param array $options
* @param string $prefix
*/
public static function setDefaultOptions(array $options)
public function setPrefix($prefix)
{
$this->prefix = $prefix;
}

public static function usingRedis(\Redis $redis, array $options)
{
self::$defaultOptions = array_merge(self::$defaultOptions, $options);
return new self(RedisAdapter::forRedis($redis, $options));
}

public static function setPrefix($prefix)
public static function usingPredis(Client $redis)
{
self::$prefix = $prefix;
return new self(RedisAdapter::forPredis($redis));
}

public function flushRedis()
{
$this->openConnection();
$this->redis->flushAll();
}

Expand All @@ -71,7 +57,6 @@ public function flushRedis()
*/
public function collect()
{
$this->openConnection();
$metrics = $this->collectHistograms();
$metrics = array_merge($metrics, $this->collectGauges());
$metrics = array_merge($metrics, $this->collectCounters());
Expand All @@ -83,29 +68,8 @@ function (array $metric) {
);
}

/**
* @throws StorageException
*/
private function openConnection()
{
try {
if ($this->options['persistent_connections']) {
@$this->redis->pconnect($this->options['host'], $this->options['port'], $this->options['timeout']);
} else {
@$this->redis->connect($this->options['host'], $this->options['port'], $this->options['timeout']);
}
if ($this->options['password']) {
$this->redis->auth($this->options['password']);
}
$this->redis->setOption(\Redis::OPT_READ_TIMEOUT, $this->options['read_timeout']);
} catch (\RedisException $e) {
throw new StorageException("Can't connect to Redis server", 0, $e);
}
}

public function updateHistogram(array $data)
{
$this->openConnection();
$bucketToIncrease = '+Inf';
foreach ($data['buckets'] as $bucket) {
if ($data['value'] <= $bucket) {
Expand All @@ -116,7 +80,7 @@ public function updateHistogram(array $data)
$metaData = $data;
unset($metaData['value']);
unset($metaData['labelValues']);
$this->redis->eval(<<<LUA
$this->redis->evaluate(<<<LUA
local increment = redis.call('hIncrByFloat', KEYS[1], KEYS[2], ARGV[1])
redis.call('hIncrBy', KEYS[1], KEYS[3], 1)
if increment == ARGV[1] then
Expand All @@ -129,7 +93,7 @@ public function updateHistogram(array $data)
$this->toMetricKey($data),
json_encode(array('b' => 'sum', 'labelValues' => $data['labelValues'])),
json_encode(array('b' => $bucketToIncrease, 'labelValues' => $data['labelValues'])),
self::$prefix . Histogram::TYPE . self::PROMETHEUS_METRIC_KEYS_SUFFIX,
$this->prefix . Histogram::TYPE . self::PROMETHEUS_METRIC_KEYS_SUFFIX,
$data['value'],
json_encode($metaData),
),
Expand All @@ -139,12 +103,12 @@ public function updateHistogram(array $data)

public function updateGauge(array $data)
{
$this->openConnection();

$metaData = $data;
unset($metaData['value']);
unset($metaData['labelValues']);
unset($metaData['command']);
$this->redis->eval(<<<LUA
$this->redis->evaluate(<<<LUA
local result = redis.call(KEYS[2], KEYS[1], KEYS[4], ARGV[1])

if KEYS[2] == 'hSet' then
Expand All @@ -163,7 +127,7 @@ public function updateGauge(array $data)
array(
$this->toMetricKey($data),
$this->getRedisCommand($data['command']),
self::$prefix . Gauge::TYPE . self::PROMETHEUS_METRIC_KEYS_SUFFIX,
$this->prefix . Gauge::TYPE . self::PROMETHEUS_METRIC_KEYS_SUFFIX,
json_encode($data['labelValues']),
$data['value'],
json_encode($metaData),
Expand All @@ -174,12 +138,11 @@ public function updateGauge(array $data)

public function updateCounter(array $data)
{
$this->openConnection();
$metaData = $data;
unset($metaData['value']);
unset($metaData['labelValues']);
unset($metaData['command']);
$result = $this->redis->eval(<<<LUA
$result = $this->redis->evaluate(<<<LUA
local result = redis.call(KEYS[2], KEYS[1], KEYS[4], ARGV[1])
if result == tonumber(ARGV[1]) then
redis.call('hMSet', KEYS[1], '__meta', ARGV[2])
Expand All @@ -191,7 +154,7 @@ public function updateCounter(array $data)
array(
$this->toMetricKey($data),
$this->getRedisCommand($data['command']),
self::$prefix . Counter::TYPE . self::PROMETHEUS_METRIC_KEYS_SUFFIX,
$this->prefix . Counter::TYPE . self::PROMETHEUS_METRIC_KEYS_SUFFIX,
json_encode($data['labelValues']),
$data['value'],
json_encode($metaData),
Expand All @@ -203,7 +166,7 @@ public function updateCounter(array $data)

private function collectHistograms()
{
$keys = $this->redis->sMembers(self::$prefix . Histogram::TYPE . self::PROMETHEUS_METRIC_KEYS_SUFFIX);
$keys = $this->redis->sMembers($this->prefix . Histogram::TYPE . self::PROMETHEUS_METRIC_KEYS_SUFFIX);
sort($keys);
$histograms = array();
foreach ($keys as $key) {
Expand Down Expand Up @@ -277,7 +240,7 @@ private function collectHistograms()

private function collectGauges()
{
$keys = $this->redis->sMembers(self::$prefix . Gauge::TYPE . self::PROMETHEUS_METRIC_KEYS_SUFFIX);
$keys = $this->redis->sMembers($this->prefix . Gauge::TYPE . self::PROMETHEUS_METRIC_KEYS_SUFFIX);
sort($keys);
$gauges = array();
foreach ($keys as $key) {
Expand All @@ -303,7 +266,7 @@ private function collectGauges()

private function collectCounters()
{
$keys = $this->redis->sMembers(self::$prefix . Counter::TYPE . self::PROMETHEUS_METRIC_KEYS_SUFFIX);
$keys = $this->redis->sMembers($this->prefix . Counter::TYPE . self::PROMETHEUS_METRIC_KEYS_SUFFIX);
sort($keys);
$counters = array();
foreach ($keys as $key) {
Expand Down Expand Up @@ -347,7 +310,6 @@ private function getRedisCommand($cmd)
*/
private function toMetricKey(array $data)
{
return implode(':', array(self::$prefix, $data['type'], $data['name']));
return implode(':', array($this->prefix, $data['type'], $data['name']));
}

}
Loading