From 283c9b6be8857247bfce32a9fc1a6f72e9b55565 Mon Sep 17 00:00:00 2001 From: Marko Kruljac Date: Mon, 2 Jan 2017 13:10:15 +0100 Subject: [PATCH 1/8] implemented missing methods --- src/Prometheus/Storage/InMemory.php | 257 +++++++++++++++++++++++++--- 1 file changed, 231 insertions(+), 26 deletions(-) diff --git a/src/Prometheus/Storage/InMemory.php b/src/Prometheus/Storage/InMemory.php index 758d19c..5e7d50e 100644 --- a/src/Prometheus/Storage/InMemory.php +++ b/src/Prometheus/Storage/InMemory.php @@ -3,42 +3,132 @@ namespace Prometheus\Storage; -use Prometheus\Collector; use Prometheus\MetricFamilySamples; use Prometheus\Sample; class InMemory implements Adapter { - /** - * @var Collector[] - */ - private $metrics = array(); - /** - * @var array - */ - private $samples = array(); + + private $counters = []; + private $gauges = []; + private $histograms = []; /** * @return MetricFamilySamples[] */ public function collect() { - $responses = array(); - foreach ($this->metrics as $metric) { - $samples = $this->samples[$metric->getKey()]; - array_multisort($samples); - $responses[] = new MetricFamilySamples( - array( - 'name' => $metric->getName(), - 'type' => $metric->getType(), - 'help' => $metric->getHelp(), - 'samples' => $samples, - 'labelNames' => $metric->getLabelNames() - ) + $metrics = $this->internalCollect($this->counters); + $metrics = array_merge($metrics, $this->internalCollect($this->gauges)); + $metrics = array_merge($metrics, $this->collectHistograms()); + return $metrics; + } + + public function flushMemory() + { + $this->counters = []; + $this->gauges = []; + $this->histograms = []; + } + + private function collectHistograms() + { + $histograms = array(); + foreach ($this->histograms as $histogram) { + $metaData = $histogram['meta']; + $data = array( + 'name' => $metaData['name'], + 'help' => $metaData['help'], + 'type' => $metaData['type'], + 'labelNames' => $metaData['labelNames'], + 'buckets' => $metaData['buckets'] ); + + // Add the Inf bucket so we can compute it later on + $data['buckets'][] = '+Inf'; + + $histogramBuckets = array(); + foreach ($histogram['samples'] as $key => $value) { + $parts = explode(':', $key); + $labelValues = $parts[2]; + $bucket = $parts[3]; + // Key by labelValues + $histogramBuckets[$labelValues][$bucket] = $value; + } + + // Compute all buckets + $labels = array_keys($histogramBuckets); + sort($labels); + foreach ($labels as $labelValues) { + $acc = 0; + $decodedLabelValues = json_decode($labelValues); + foreach ($data['buckets'] as $bucket) { + $bucket = (string) $bucket; + if (!isset($histogramBuckets[$labelValues][$bucket])) { + $data['samples'][] = array( + 'name' => $metaData['name'] . '_bucket', + 'labelNames' => array('le'), + 'labelValues' => array_merge($decodedLabelValues, array($bucket)), + 'value' => $acc + ); + } else { + $acc += $histogramBuckets[$labelValues][$bucket]; + $data['samples'][] = array( + 'name' => $metaData['name'] . '_' . 'bucket', + 'labelNames' => array('le'), + 'labelValues' => array_merge($decodedLabelValues, array($bucket)), + 'value' => $acc + ); + } + } + + // Add the count + $data['samples'][] = array( + 'name' => $metaData['name'] . '_count', + 'labelNames' => array(), + 'labelValues' => $decodedLabelValues, + 'value' => $acc + ); + + // Add the sum + $data['samples'][] = array( + 'name' => $metaData['name'] . '_sum', + 'labelNames' => array(), + 'labelValues' => $decodedLabelValues, + 'value' => $histogramBuckets[$labelValues]['sum'] + ); + + } + $histograms[] = new MetricFamilySamples($data); + } + return $histograms; + } + + private function internalCollect(array $metrics) + { + $result = []; + foreach ($metrics as $metric) { + $metaData = $metric['meta']; + $data = array( + 'name' => $metaData['name'], + 'help' => $metaData['help'], + 'type' => $metaData['type'], + 'labelNames' => $metaData['labelNames'], + ); + foreach ($metric['samples'] as $key => $value) { + $parts = explode(':', $key); + $labelValues = $parts[2]; + $data['samples'][] = array( + 'name' => $metaData['name'], + 'labelNames' => array(), + 'labelValues' => json_decode($labelValues), + 'value' => $value + ); + } + $this->sortSamples($data['samples']); + $result[] = new MetricFamilySamples($data); } - array_multisort($responses); - return $responses; + return $result; } /** @@ -54,18 +144,133 @@ function ($data) { return new Sample($data); }, public function updateHistogram(array $data) { - // TODO: Implement incrementByFloat() method. + // Initialize the sum + $metaKey = $this->metaKey($data); + if (array_key_exists($metaKey, $this->histograms) === false) { + $this->histograms[$metaKey] = [ + 'meta' => $this->metaData($data), + 'samples' => [] + ]; + } + $sumKey = $this->histogramBucketValueKey($data, 'sum'); + if (array_key_exists($sumKey, $this->histograms[$metaKey]['samples']) === false) { + $this->histograms[$metaKey]['samples'][$sumKey] = 0; + } + + $this->histograms[$metaKey]['samples'][$sumKey] += $data['value']; + + + $bucketToIncrease = '+Inf'; + foreach ($data['buckets'] as $bucket) { + if ($data['value'] <= $bucket) { + $bucketToIncrease = $bucket; + break; + } + } + + $bucketKey = $this->histogramBucketValueKey($data, $bucketToIncrease); + if (array_key_exists($bucketKey, $this->histograms[$metaKey]['samples']) === false) { + $this->histograms[$metaKey]['samples'][$bucketKey] = 0; + } + $this->histograms[$metaKey]['samples'][$bucketKey] += 1; } public function updateGauge(array $data) { - // TODO: Implement updateGauge() method. + $metaKey = $this->metaKey($data); + $valueKey = $this->valueKey($data); + if (array_key_exists($metaKey, $this->gauges) === false) { + $this->gauges[$metaKey] = [ + 'meta' => $this->metaData($data), + 'samples' => [] + ]; + } + if (array_key_exists($valueKey, $this->gauges[$metaKey]['samples']) === false) { + $this->gauges[$metaKey]['samples'][$valueKey] = 0; + } + if ($data['command'] === Adapter::COMMAND_SET) { + $this->gauges[$metaKey]['samples'][$valueKey] = $data['value']; + } else { + $this->gauges[$metaKey]['samples'][$valueKey] += $data['value']; + } } public function updateCounter(array $data) { - // TODO: Implement updateCounter() method. + $metaKey = $this->metaKey($data); + $valueKey = $this->valueKey($data); + if (array_key_exists($metaKey, $this->counters) === false) { + $this->counters[$metaKey] = [ + 'meta' => $this->metaData($data), + 'samples' => [] + ]; + } + if (array_key_exists($valueKey, $this->counters[$metaKey]['samples']) === false) { + $this->counters[$metaKey]['samples'][$valueKey] = 0; + } + if ($data['command'] === Adapter::COMMAND_SET) { + $this->counters[$metaKey]['samples'][$valueKey] = 0; + } else { + $this->counters[$metaKey]['samples'][$valueKey] += $data['value']; + } + } + + /** + * @param array $data + * + * @param $bucket + * + * @return string + */ + private function histogramBucketValueKey(array $data, $bucket) + { + return implode(':', array( + $data['type'], + $data['name'], + json_encode($data['labelValues']), + $bucket + )); + } + + /** + * @param array $data + * + * @return string + */ + private function metaKey(array $data) + { + return implode(':', array($data['type'], $data['name'], 'meta')); + } + + /** + * @param array $data + * + * @return string + */ + private function valueKey(array $data) + { + return implode(':', + array($data['type'], $data['name'], json_encode($data['labelValues']), 'value')); } + /** + * @param array $data + * + * @return array + */ + private function metaData(array $data) + { + $metricsMetaData = $data; + unset($metricsMetaData['value']); + unset($metricsMetaData['command']); + unset($metricsMetaData['labelValues']); + return $metricsMetaData; + } + private function sortSamples(array &$samples) + { + usort($samples, function ($a, $b) { + return strcmp(implode("", $a['labelValues']), implode("", $b['labelValues'])); + }); + } } From b73b4534ae40302ea38fbb097ae2dd487b3f93e0 Mon Sep 17 00:00:00 2001 From: Marko Kruljac Date: Mon, 2 Jan 2017 13:11:50 +0100 Subject: [PATCH 2/8] added tests --- .../InMemory/CollectorRegistryTest.php | 16 ++++++++++++++ .../Test/Prometheus/InMemory/CounterTest.php | 20 ++++++++++++++++++ tests/Test/Prometheus/InMemory/GaugeTest.php | 20 ++++++++++++++++++ .../Prometheus/InMemory/HistogramTest.php | 21 +++++++++++++++++++ 4 files changed, 77 insertions(+) create mode 100644 tests/Test/Prometheus/InMemory/CollectorRegistryTest.php create mode 100644 tests/Test/Prometheus/InMemory/CounterTest.php create mode 100644 tests/Test/Prometheus/InMemory/GaugeTest.php create mode 100644 tests/Test/Prometheus/InMemory/HistogramTest.php diff --git a/tests/Test/Prometheus/InMemory/CollectorRegistryTest.php b/tests/Test/Prometheus/InMemory/CollectorRegistryTest.php new file mode 100644 index 0000000..7309708 --- /dev/null +++ b/tests/Test/Prometheus/InMemory/CollectorRegistryTest.php @@ -0,0 +1,16 @@ +adapter = new InMemory(); + $this->adapter->flushMemory(); + } +} diff --git a/tests/Test/Prometheus/InMemory/CounterTest.php b/tests/Test/Prometheus/InMemory/CounterTest.php new file mode 100644 index 0000000..03ed614 --- /dev/null +++ b/tests/Test/Prometheus/InMemory/CounterTest.php @@ -0,0 +1,20 @@ +adapter = new InMemory(); + $this->adapter->flushMemory(); + } +} diff --git a/tests/Test/Prometheus/InMemory/GaugeTest.php b/tests/Test/Prometheus/InMemory/GaugeTest.php new file mode 100644 index 0000000..75e0f3c --- /dev/null +++ b/tests/Test/Prometheus/InMemory/GaugeTest.php @@ -0,0 +1,20 @@ +adapter = new InMemory(); + $this->adapter->flushMemory(); + } +} diff --git a/tests/Test/Prometheus/InMemory/HistogramTest.php b/tests/Test/Prometheus/InMemory/HistogramTest.php new file mode 100644 index 0000000..283ec3e --- /dev/null +++ b/tests/Test/Prometheus/InMemory/HistogramTest.php @@ -0,0 +1,21 @@ +adapter = new InMemory(); + $this->adapter->flushMemory(); + } +} + From c2ba3278b006b978d524cf5c07e55368ab13f694 Mon Sep 17 00:00:00 2001 From: Marko Kruljac Date: Wed, 15 Mar 2017 18:49:22 +0100 Subject: [PATCH 3/8] changed array declaration to short syntax --- src/Prometheus/Storage/InMemory.php | 56 ++++++++++++++--------------- 1 file changed, 28 insertions(+), 28 deletions(-) diff --git a/src/Prometheus/Storage/InMemory.php b/src/Prometheus/Storage/InMemory.php index 5e7d50e..ecfb2d3 100644 --- a/src/Prometheus/Storage/InMemory.php +++ b/src/Prometheus/Storage/InMemory.php @@ -33,21 +33,21 @@ public function flushMemory() private function collectHistograms() { - $histograms = array(); + $histograms = []; foreach ($this->histograms as $histogram) { $metaData = $histogram['meta']; - $data = array( + $data = [ 'name' => $metaData['name'], 'help' => $metaData['help'], 'type' => $metaData['type'], 'labelNames' => $metaData['labelNames'], 'buckets' => $metaData['buckets'] - ); + ]; // Add the Inf bucket so we can compute it later on $data['buckets'][] = '+Inf'; - $histogramBuckets = array(); + $histogramBuckets = []; foreach ($histogram['samples'] as $key => $value) { $parts = explode(':', $key); $labelValues = $parts[2]; @@ -65,38 +65,38 @@ private function collectHistograms() foreach ($data['buckets'] as $bucket) { $bucket = (string) $bucket; if (!isset($histogramBuckets[$labelValues][$bucket])) { - $data['samples'][] = array( + $data['samples'][] = [ 'name' => $metaData['name'] . '_bucket', - 'labelNames' => array('le'), - 'labelValues' => array_merge($decodedLabelValues, array($bucket)), + 'labelNames' => ['le'], + 'labelValues' => array_merge($decodedLabelValues, [$bucket]), 'value' => $acc - ); + ]; } else { $acc += $histogramBuckets[$labelValues][$bucket]; - $data['samples'][] = array( + $data['samples'][] = [ 'name' => $metaData['name'] . '_' . 'bucket', - 'labelNames' => array('le'), - 'labelValues' => array_merge($decodedLabelValues, array($bucket)), + 'labelNames' => ['le'], + 'labelValues' => array_merge($decodedLabelValues, [$bucket]), 'value' => $acc - ); + ]; } } // Add the count - $data['samples'][] = array( + $data['samples'][] = [ 'name' => $metaData['name'] . '_count', - 'labelNames' => array(), + 'labelNames' => [], 'labelValues' => $decodedLabelValues, 'value' => $acc - ); + ]; // Add the sum - $data['samples'][] = array( + $data['samples'][] = [ 'name' => $metaData['name'] . '_sum', - 'labelNames' => array(), + 'labelNames' => [], 'labelValues' => $decodedLabelValues, 'value' => $histogramBuckets[$labelValues]['sum'] - ); + ]; } $histograms[] = new MetricFamilySamples($data); @@ -109,21 +109,21 @@ private function internalCollect(array $metrics) $result = []; foreach ($metrics as $metric) { $metaData = $metric['meta']; - $data = array( + $data = [ 'name' => $metaData['name'], 'help' => $metaData['help'], 'type' => $metaData['type'], 'labelNames' => $metaData['labelNames'], - ); + ]; foreach ($metric['samples'] as $key => $value) { $parts = explode(':', $key); $labelValues = $parts[2]; - $data['samples'][] = array( + $data['samples'][] = [ 'name' => $metaData['name'], - 'labelNames' => array(), + 'labelNames' => [], 'labelValues' => json_decode($labelValues), 'value' => $value - ); + ]; } $this->sortSamples($data['samples']); $result[] = new MetricFamilySamples($data); @@ -138,7 +138,7 @@ public function fetchSamples() { return array_map( function ($data) { return new Sample($data); }, - array_values(array_reduce(array_values($this->samples), 'array_merge', array())) + array_values(array_reduce(array_values($this->samples), 'array_merge', [])) ); } @@ -224,12 +224,12 @@ public function updateCounter(array $data) */ private function histogramBucketValueKey(array $data, $bucket) { - return implode(':', array( + return implode(':', [ $data['type'], $data['name'], json_encode($data['labelValues']), $bucket - )); + ]); } /** @@ -239,7 +239,7 @@ private function histogramBucketValueKey(array $data, $bucket) */ private function metaKey(array $data) { - return implode(':', array($data['type'], $data['name'], 'meta')); + return implode(':', [$data['type'], $data['name'], 'meta']); } /** @@ -250,7 +250,7 @@ private function metaKey(array $data) private function valueKey(array $data) { return implode(':', - array($data['type'], $data['name'], json_encode($data['labelValues']), 'value')); + [$data['type'], $data['name'], json_encode($data['labelValues']), 'value']); } /** From 860cadef086bb94b1ad44856af0173f1d050c871 Mon Sep 17 00:00:00 2001 From: Marko Kruljac Date: Wed, 15 Mar 2017 18:50:32 +0100 Subject: [PATCH 4/8] removed dead code --- src/Prometheus/Storage/InMemory.php | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/src/Prometheus/Storage/InMemory.php b/src/Prometheus/Storage/InMemory.php index ecfb2d3..b83b583 100644 --- a/src/Prometheus/Storage/InMemory.php +++ b/src/Prometheus/Storage/InMemory.php @@ -131,17 +131,6 @@ private function internalCollect(array $metrics) return $result; } - /** - * @return Sample[] - */ - public function fetchSamples() - { - return array_map( - function ($data) { return new Sample($data); }, - array_values(array_reduce(array_values($this->samples), 'array_merge', [])) - ); - } - public function updateHistogram(array $data) { // Initialize the sum From 1994962275a609db6c40968103ff7cc24d86ac61 Mon Sep 17 00:00:00 2001 From: Marko Kruljac Date: Wed, 15 Mar 2017 18:52:08 +0100 Subject: [PATCH 5/8] minor style correction --- src/Prometheus/Storage/InMemory.php | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/Prometheus/Storage/InMemory.php b/src/Prometheus/Storage/InMemory.php index b83b583..37c24b1 100644 --- a/src/Prometheus/Storage/InMemory.php +++ b/src/Prometheus/Storage/InMemory.php @@ -4,7 +4,6 @@ use Prometheus\MetricFamilySamples; -use Prometheus\Sample; class InMemory implements Adapter { @@ -63,7 +62,7 @@ private function collectHistograms() $acc = 0; $decodedLabelValues = json_decode($labelValues); foreach ($data['buckets'] as $bucket) { - $bucket = (string) $bucket; + $bucket = (string)$bucket; if (!isset($histogramBuckets[$labelValues][$bucket])) { $data['samples'][] = [ 'name' => $metaData['name'] . '_bucket', From 153dcac7eab98e86ab322006132470a8b1a0af2d Mon Sep 17 00:00:00 2001 From: Marko Kruljac Date: Wed, 15 Mar 2017 19:08:04 +0100 Subject: [PATCH 6/8] added an example usage for in memory storage --- README.md | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/README.md b/README.md index ecd35f5..eb3a088 100644 --- a/README.md +++ b/README.md @@ -74,6 +74,17 @@ Change the Redis options (the example shows the defaults): ); ``` +Using the InMemory storage: +```php +$registry = new CollectorRegistry(new InMemory()); + +$counter = $registry->registerCounter('test', 'some_counter', 'it increases', ['type']); +$counter->incBy(3, ['blue']); + +$renderer = new RenderTextFormat(); +$result = $renderer->render($registry->getMetricFamilySamples()); +``` + Also look at the [examples](examples). ## Development From 2f4f7c0a584f001a1975d29a0e930160210a225a Mon Sep 17 00:00:00 2001 From: Marko Kruljac Date: Wed, 15 Mar 2017 19:08:19 +0100 Subject: [PATCH 7/8] added examples for the in memory storage --- examples/flush_adapter.php | 11 ++++++----- examples/metrics.php | 7 ++++--- examples/pushgateway.php | 13 ++++++++++++- examples/some_counter.php | 9 ++++----- examples/some_gauge.php | 7 ++++--- examples/some_histogram.php | 7 ++++--- 6 files changed, 34 insertions(+), 20 deletions(-) diff --git a/examples/flush_adapter.php b/examples/flush_adapter.php index 5c58091..0c3862d 100644 --- a/examples/flush_adapter.php +++ b/examples/flush_adapter.php @@ -3,14 +3,15 @@ $adapter = $_GET['adapter']; -if ($adapter == 'redis') { +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(); -} - -if ($adapter == 'apc') { +} elseif ($adapter === 'apc') { $apcAdapter = new Prometheus\Storage\APC(); $apcAdapter->flushAPC(); -} +} elseif ($adapter === 'in-memory') { + $inMemoryAdapter = new Prometheus\Storage\InMemory(); + $inMemoryAdapter->flushMemory(); +} \ No newline at end of file diff --git a/examples/metrics.php b/examples/metrics.php index 79c0f92..fa89247 100644 --- a/examples/metrics.php +++ b/examples/metrics.php @@ -8,12 +8,13 @@ $adapter = $_GET['adapter']; -if ($adapter == 'redis') { +if ($adapter === 'redis') { Redis::setDefaultOptions(array('host' => isset($_SERVER['REDIS_HOST']) ? $_SERVER['REDIS_HOST'] : '127.0.0.1')); $adapter = new Prometheus\Storage\Redis(); -} -if ($adapter == 'apc') { +} elseif ($adapter === 'apc') { $adapter = new Prometheus\Storage\APC(); +} elseif ($adapter === 'in-memory') { + $adapter = new Prometheus\Storage\InMemory(); } $registry = new CollectorRegistry($adapter); $renderer = new RenderTextFormat(); diff --git a/examples/pushgateway.php b/examples/pushgateway.php index e92baae..984035d 100644 --- a/examples/pushgateway.php +++ b/examples/pushgateway.php @@ -1,9 +1,20 @@ 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); $counter = $registry->registerCounter('test', 'some_counter', 'it increases', ['type']); diff --git a/examples/some_counter.php b/examples/some_counter.php index 738ff22..823bfac 100644 --- a/examples/some_counter.php +++ b/examples/some_counter.php @@ -5,16 +5,15 @@ use Prometheus\CollectorRegistry; use Prometheus\Storage\Redis; -error_log('c='. $_GET['c']); - $adapter = $_GET['adapter']; -if ($adapter == 'redis') { +if ($adapter === 'redis') { Redis::setDefaultOptions(array('host' => isset($_SERVER['REDIS_HOST']) ? $_SERVER['REDIS_HOST'] : '127.0.0.1')); $adapter = new Prometheus\Storage\Redis(); -} -if ($adapter == 'apc') { +} elseif ($adapter === 'apc') { $adapter = new Prometheus\Storage\APC(); +} elseif ($adapter === 'in-memory') { + $adapter = new Prometheus\Storage\InMemory(); } $registry = new CollectorRegistry($adapter); diff --git a/examples/some_gauge.php b/examples/some_gauge.php index 65aecc6..b3e2382 100644 --- a/examples/some_gauge.php +++ b/examples/some_gauge.php @@ -10,12 +10,13 @@ $adapter = $_GET['adapter']; -if ($adapter == 'redis') { +if ($adapter === 'redis') { Redis::setDefaultOptions(array('host' => isset($_SERVER['REDIS_HOST']) ? $_SERVER['REDIS_HOST'] : '127.0.0.1')); $adapter = new Prometheus\Storage\Redis(); -} -if ($adapter == 'apc') { +} elseif ($adapter === 'apc') { $adapter = new Prometheus\Storage\APC(); +} elseif ($adapter === 'in-memory') { + $adapter = new Prometheus\Storage\InMemory(); } $registry = new CollectorRegistry($adapter); diff --git a/examples/some_histogram.php b/examples/some_histogram.php index 684f9f1..6b34809 100644 --- a/examples/some_histogram.php +++ b/examples/some_histogram.php @@ -9,12 +9,13 @@ $adapter = $_GET['adapter']; -if ($adapter == 'redis') { +if ($adapter === 'redis') { Redis::setDefaultOptions(array('host' => isset($_SERVER['REDIS_HOST']) ? $_SERVER['REDIS_HOST'] : '127.0.0.1')); $adapter = new Prometheus\Storage\Redis(); -} -if ($adapter == 'apc') { +} elseif ($adapter === 'apc') { $adapter = new Prometheus\Storage\APC(); +} elseif ($adapter === 'in-memory') { + $adapter = new Prometheus\Storage\InMemory(); } $registry = new CollectorRegistry($adapter); From 629961d9a2e0abfbcac6fcea54e9527d0361d1be Mon Sep 17 00:00:00 2001 From: Jan Brauer Date: Mon, 20 Mar 2017 08:44:51 +0100 Subject: [PATCH 8/8] Mention in memory adapter in the introduction --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index eb3a088..8257868 100644 --- a/README.md +++ b/README.md @@ -10,9 +10,9 @@ If using Redis, we recommend to run a local Redis instance next to your PHP work ## How does it work? Usually PHP worker processes don't share any state. -You can pick from two adapters. -One uses Redis the other APC. -While the former needs a separate binary running, the latter just needs the [APC](https://pecl.php.net/package/APCU) extension to be installed. +You can pick from three adapters. +Redis, APC or an in memory adapter. +While the first needs a separate binary running, the second just needs the [APC](https://pecl.php.net/package/APCU) extension to be installed. If you don't need persistent metrics between requests (e.g. a long running cron job or script) the in memory adapter might be suitable to use. ## Usage