Skip to content
This repository was archived by the owner on Oct 22, 2019. It is now read-only.
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
100 changes: 27 additions & 73 deletions src/Prometheus/Storage/APC.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@


use Prometheus\MetricFamilySamples;
use RuntimeException;

class APC implements Adapter
{
Expand All @@ -26,19 +25,19 @@ public function updateHistogram(array $data)
{
// Initialize the sum
$sumKey = $this->histogramBucketValueKey($data, 'sum');
$new = apcu_add($sumKey, $this->toInteger(0));
$new = apc_add($sumKey, $this->toInteger(0));

// If sum does not exist, assume a new histogram and store the metadata
if ($new) {
apcu_store($this->metaKey($data), json_encode($this->metaData($data)));
apc_store($this->metaKey($data), json_encode($this->metaData($data)));
}

// Atomically increment the sum
// Taken from https://github.com/prometheus/client_golang/blob/66058aac3a83021948e5fb12f1f408ff556b9037/prometheus/value.go#L91
$done = false;
while (!$done) {
$old = apcu_fetch($sumKey);
$done = apcu_cas($sumKey, $old, $this->toInteger($this->fromInteger($old) + $data['value']));
$old = apc_fetch($sumKey);
$done = apc_cas($sumKey, $old, $this->toInteger($this->fromInteger($old) + $data['value']));
}

// Figure out in which bucket the observation belongs
Expand All @@ -51,42 +50,42 @@ public function updateHistogram(array $data)
}

// Initialize and increment the bucket
apcu_add($this->histogramBucketValueKey($data, $bucketToIncrease), 0);
apcu_inc($this->histogramBucketValueKey($data, $bucketToIncrease));
apc_add($this->histogramBucketValueKey($data, $bucketToIncrease), 0);
apc_inc($this->histogramBucketValueKey($data, $bucketToIncrease));
}

public function updateGauge(array $data)
{
$valueKey = $this->valueKey($data);
if ($data['command'] == Adapter::COMMAND_SET) {
apcu_store($valueKey, $this->toInteger($data['value']));
apcu_store($this->metaKey($data), json_encode($this->metaData($data)));
apc_store($valueKey, $this->toInteger($data['value']));
apc_store($this->metaKey($data), json_encode($this->metaData($data)));
} else {
$new = apcu_add($valueKey, $this->toInteger(0));
$new = apc_add($valueKey, $this->toInteger(0));
if ($new) {
apcu_store($this->metaKey($data), json_encode($this->metaData($data)));
apc_store($this->metaKey($data), json_encode($this->metaData($data)));
}
// Taken from https://github.com/prometheus/client_golang/blob/66058aac3a83021948e5fb12f1f408ff556b9037/prometheus/value.go#L91
$done = false;
while (!$done) {
$old = apcu_fetch($valueKey);
$done = apcu_cas($valueKey, $old, $this->toInteger($this->fromInteger($old) + $data['value']));
$old = apc_fetch($valueKey);
$done = apc_cas($valueKey, $old, $this->toInteger($this->fromInteger($old) + $data['value']));
}
}
}

public function updateCounter(array $data)
{
$new = apcu_add($this->valueKey($data), 0);
$new = apc_add($this->valueKey($data), 0);
if ($new) {
apcu_store($this->metaKey($data), json_encode($this->metaData($data)));
apc_store($this->metaKey($data), json_encode($this->metaData($data)));
}
apcu_inc($this->valueKey($data), $data['value']);
apc_inc($this->valueKey($data), $data['value']);
}

public function flushAPC()
{
apcu_clear_cache();
apc_clear_cache('user');
}

/**
Expand All @@ -104,13 +103,7 @@ private function metaKey(array $data)
*/
private function valueKey(array $data)
{
return implode(':', array(
self::PROMETHEUS_PREFIX,
$data['type'],
$data['name'],
$this->encodeLabelValues($data['labelValues']),
'value'
));
return implode(':', array(self::PROMETHEUS_PREFIX, $data['type'], $data['name'], json_encode($data['labelValues']), 'value'));
}

/**
Expand All @@ -119,14 +112,7 @@ private function valueKey(array $data)
*/
private function histogramBucketValueKey(array $data, $bucket)
{
return implode(':', array(
self::PROMETHEUS_PREFIX,
$data['type'],
$data['name'],
$this->encodeLabelValues($data['labelValues']),
$bucket,
'value'
));
return implode(':', array(self::PROMETHEUS_PREFIX, $data['type'], $data['name'], json_encode($data['labelValues']), $bucket, 'value'));
}

/**
Expand All @@ -148,21 +134,21 @@ private function metaData(array $data)
private function collectCounters()
{
$counters = array();
foreach (new \APCUIterator('/^prom:counter:.*:meta/') as $counter) {
foreach (new \APCIterator('user', '/^prom:counter:.*:meta/') as $counter) {
$metaData = json_decode($counter['value'], true);
$data = array(
'name' => $metaData['name'],
'help' => $metaData['help'],
'type' => $metaData['type'],
'labelNames' => $metaData['labelNames'],
);
foreach (new \APCUIterator('/^prom:counter:' . $metaData['name'] . ':.*:value/') as $value) {
foreach (new \APCIterator('user', '/^prom:counter:' . $metaData['name'] . ':.*:value/') as $value) {
$parts = explode(':', $value['key']);
$labelValues = $parts[3];
$data['samples'][] = array(
'name' => $metaData['name'],
'labelNames' => array(),
'labelValues' => $this->decodeLabelValues($labelValues),
'labelValues' => json_decode($labelValues),
'value' => $value['value']
);
}
Expand All @@ -178,21 +164,21 @@ private function collectCounters()
private function collectGauges()
{
$gauges = array();
foreach (new \APCUIterator('/^prom:gauge:.*:meta/') as $gauge) {
foreach (new \APCIterator('user', '/^prom:gauge:.*:meta/') as $gauge) {
$metaData = json_decode($gauge['value'], true);
$data = array(
'name' => $metaData['name'],
'help' => $metaData['help'],
'type' => $metaData['type'],
'labelNames' => $metaData['labelNames'],
);
foreach (new \APCUIterator('/^prom:gauge:' . $metaData['name'] . ':.*:value/') as $value) {
foreach (new \APCIterator('user', '/^prom:gauge:' . $metaData['name'] . ':.*:value/') as $value) {
$parts = explode(':', $value['key']);
$labelValues = $parts[3];
$data['samples'][] = array(
'name' => $metaData['name'],
'labelNames' => array(),
'labelValues' => $this->decodeLabelValues($labelValues),
'labelValues' => json_decode($labelValues),
'value' => $this->fromInteger($value['value'])
);
}
Expand All @@ -209,7 +195,7 @@ private function collectGauges()
private function collectHistograms()
{
$histograms = array();
foreach (new \APCUIterator('/^prom:histogram:.*:meta/') as $histogram) {
foreach (new \APCIterator('user', '/^prom:histogram:.*:meta/') as $histogram) {
$metaData = json_decode($histogram['value'], true);
$data = array(
'name' => $metaData['name'],
Expand All @@ -223,7 +209,7 @@ private function collectHistograms()
$data['buckets'][] = '+Inf';

$histogramBuckets = array();
foreach (new \APCUIterator('/^prom:histogram:' . $metaData['name'] . ':.*:value/') as $value) {
foreach (new \APCIterator('user', '/^prom:histogram:' . $metaData['name'] . ':.*:value/') as $value) {
$parts = explode(':', $value['key']);
$labelValues = $parts[3];
$bucket = $parts[4];
Expand All @@ -236,7 +222,7 @@ private function collectHistograms()
sort($labels);
foreach ($labels as $labelValues) {
$acc = 0;
$decodedLabelValues = $this->decodeLabelValues($labelValues);
$decodedLabelValues = json_decode($labelValues);
foreach ($data['buckets'] as $bucket) {
$bucket = (string) $bucket;
if (!isset($histogramBuckets[$labelValues][$bucket])) {
Expand Down Expand Up @@ -303,36 +289,4 @@ private function sortSamples(array &$samples)
return strcmp(implode("", $a['labelValues']), implode("", $b['labelValues']));
});
}

/**
* @param array $values
* @return string
* @throws RuntimeException
*/
private function encodeLabelValues(array $values)
{
$json = json_encode($values);
if (false === $json) {
throw new RuntimeException(json_last_error_msg());
}
return base64_encode($json);
}

/**
* @param string $values
* @return array
* @throws RuntimeException
*/
private function decodeLabelValues($values)
{
$json = base64_decode($values, true);
if (false === $json) {
throw new RuntimeException('Cannot base64 decode label values');
}
$decodedValues = json_decode($json, true);
if (false === $decodedValues) {
throw new RuntimeException(json_last_error_msg());
}
return $decodedValues;
}
}
Loading