diff --git a/composer.json b/composer.json index f2f8b90..607dec3 100644 --- a/composer.json +++ b/composer.json @@ -13,7 +13,7 @@ "jimdo/prometheus_client_php": "*" }, "require": { - "php": "^7.2", + "php": "^7.2|^8.0", "ext-json": "*", "guzzlehttp/guzzle": "^6.3", "symfony/polyfill-apcu": "^1.6" diff --git a/src/Prometheus/Counter.php b/src/Prometheus/Counter.php index 1b095e5..0c8faef 100644 --- a/src/Prometheus/Counter.php +++ b/src/Prometheus/Counter.php @@ -29,8 +29,9 @@ public function inc(array $labels = []): void /** * @param int $count e.g. 2 * @param array $labels e.g. ['status', 'opcode'] + * @param int|null $timestamp */ - public function incBy($count, array $labels = []): void + public function incBy($count, array $labels = [], int $timestamp = null): void { $this->assertLabelsAreDefinedCorrectly($labels); @@ -43,6 +44,7 @@ public function incBy($count, array $labels = []): void 'labelValues' => $labels, 'value' => $count, 'command' => Adapter::COMMAND_INCREMENT_INTEGER, + 'timestamp' => $timestamp ] ); } diff --git a/src/Prometheus/Gauge.php b/src/Prometheus/Gauge.php index 72189f7..c2937b2 100644 --- a/src/Prometheus/Gauge.php +++ b/src/Prometheus/Gauge.php @@ -13,8 +13,9 @@ class Gauge extends Collector /** * @param double $value e.g. 123 * @param array $labels e.g. ['status', 'opcode'] + * @param int|null $timestamp */ - public function set(float $value, array $labels = []): void + public function set(float $value, array $labels = [], int $timestamp = null): void { $this->assertLabelsAreDefinedCorrectly($labels); @@ -27,6 +28,7 @@ public function set(float $value, array $labels = []): void 'labelValues' => $labels, 'value' => $value, 'command' => Adapter::COMMAND_SET, + 'timestamp' => $timestamp ] ); } @@ -50,8 +52,9 @@ public function inc($labels = []): void /** * @param $value * @param array $labels + * @param int|null $timestamp */ - public function incBy($value, array $labels = []): void + public function incBy($value, array $labels = [], int $timestamp = null): void { $this->assertLabelsAreDefinedCorrectly($labels); @@ -64,6 +67,7 @@ public function incBy($value, array $labels = []): void 'labelValues' => $labels, 'value' => $value, 'command' => Adapter::COMMAND_INCREMENT_FLOAT, + 'timestamp' => $timestamp ] ); } diff --git a/src/Prometheus/RenderTextFormat.php b/src/Prometheus/RenderTextFormat.php index a5b78dc..49907b4 100644 --- a/src/Prometheus/RenderTextFormat.php +++ b/src/Prometheus/RenderTextFormat.php @@ -37,6 +37,7 @@ public function render(array $metrics): string */ private function renderSample(MetricFamilySamples $metric, Sample $sample): string { + $result = null; $escapedLabels = []; $labelNames = $metric->getLabelNames(); @@ -45,9 +46,14 @@ private function renderSample(MetricFamilySamples $metric, Sample $sample): stri foreach ($labels as $labelName => $labelValue) { $escapedLabels[] = $labelName . '="' . $this->escapeLabelValue($labelValue) . '"'; } - return $sample->getName() . '{' . implode(',', $escapedLabels) . '} ' . $sample->getValue(); + $result = $sample->getName() . '{' . implode(',', $escapedLabels) . '} ' . $sample->getValue(); + } else { + $result = $sample->getName() . ' ' . $sample->getValue(); } - return $sample->getName() . ' ' . $sample->getValue(); + if ($sample->hasTimestamp()) { + $result .= ' ' . $sample->getTimestamp() * 1000; + } + return $result; } /** @@ -56,6 +62,7 @@ private function renderSample(MetricFamilySamples $metric, Sample $sample): stri */ private function escapeLabelValue($v): string { + $v = is_array($v) ? $v : strval($v); $v = str_replace("\\", "\\\\", $v); $v = str_replace("\n", "\\n", $v); $v = str_replace("\"", "\\\"", $v); diff --git a/src/Prometheus/Sample.php b/src/Prometheus/Sample.php index c8774e8..1aec8bc 100644 --- a/src/Prometheus/Sample.php +++ b/src/Prometheus/Sample.php @@ -26,6 +26,11 @@ class Sample */ private $value; + /** + * @var ?int + */ + private $timestamp; + /** * Sample constructor. * @param array $data @@ -36,6 +41,7 @@ public function __construct(array $data) $this->labelNames = $data['labelNames']; $this->labelValues = $data['labelValues']; $this->value = $data['value']; + $this->timestamp = (int)($data['timestamp'] ?? 0) ?: null; } /** @@ -67,7 +73,7 @@ public function getLabelValues(): array */ public function getValue(): string { - return (string) $this->value; + return (string)$this->value; } /** @@ -77,4 +83,20 @@ public function hasLabelNames(): bool { return !empty($this->labelNames); } + + /** + * @return int|null + */ + public function getTimestamp(): ?int + { + return $this->timestamp; + } + + /** + * @return bool + */ + public function hasTimestamp(): bool + { + return (bool)$this->timestamp; + } } diff --git a/src/Prometheus/Storage/InMemory.php b/src/Prometheus/Storage/InMemory.php index bfd4c70..de0a38f 100644 --- a/src/Prometheus/Storage/InMemory.php +++ b/src/Prometheus/Storage/InMemory.php @@ -125,11 +125,13 @@ private function internalCollect(array $metrics): array foreach ($metric['samples'] as $key => $value) { $parts = explode(':', $key); $labelValues = $parts[2]; + $timestamp = $parts[3] ?? false; $data['samples'][] = [ 'name' => $metaData['name'], 'labelNames' => [], 'labelValues' => $this->decodeLabelValues($labelValues), 'value' => $value, + 'timestamp' => $timestamp ]; } $this->sortSamples($data['samples']); @@ -261,6 +263,7 @@ private function valueKey(array $data): string $data['type'], $data['name'], $this->encodeLabelValues($data['labelValues']), + $data['timestamp'] ?? false, 'value' ]); }