Skip to content

Commit 4f71eb1

Browse files
SevaWeb011VsevolodLKaemmerling
authored
Catch invalid JSON from Redis and throw an error (#174)
* Catch invalid JSON from Redis and throw an error Signed-off-by: Vsevolod <vmalygin@adsterra.com> * was added a custom json exception for metrics Signed-off-by: Vsevolod <vmalygin@adsterra.com> * refactoring Signed-off-by: Vsevolod <vmalygin@adsterra.com> * Update src/Prometheus/Exception/MetricJsonException.php --------- Signed-off-by: Vsevolod <vmalygin@adsterra.com> Co-authored-by: Vsevolod <vmalygin@adsterra.com> Co-authored-by: Lukas Kämmerling <github@lukas-kaemmerling.de> Co-authored-by: Lukas Kämmerling <lukas.kaemmerling@hetzner-cloud.de>
1 parent f191801 commit 4f71eb1

File tree

3 files changed

+76
-0
lines changed

3 files changed

+76
-0
lines changed
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
<?php
2+
3+
namespace Prometheus\Exception;
4+
5+
use Exception;
6+
7+
/**
8+
* Exception thrown if a metric can't be found in the CollectorRegistry.
9+
*/
10+
class MetricJsonException extends Exception
11+
{
12+
13+
private $metricName;
14+
public function __construct($message = "", $code = 0, Exception $previous = null, ?string $metricName = null)
15+
{
16+
parent::__construct($message, $code, $previous);
17+
$this->metricName = $metricName;
18+
}
19+
20+
public function getMetricName(): ?string
21+
{
22+
return $this->metricName;
23+
}
24+
}

src/Prometheus/Storage/Redis.php

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66

77
use InvalidArgumentException;
88
use Prometheus\Counter;
9+
use Prometheus\Exception\MetricJsonException;
910
use Prometheus\Exception\StorageException;
1011
use Prometheus\Gauge;
1112
use Prometheus\Histogram;
@@ -432,6 +433,9 @@ private function collectHistograms(): array
432433
}
433434
$allLabelValues[] = $d['labelValues'];
434435
}
436+
if (json_last_error() !== JSON_ERROR_NONE) {
437+
$this->throwMetricJsonException($key);
438+
}
435439

436440
// We need set semantics.
437441
// This is the equivalent of array_unique but for arrays of arrays.
@@ -618,6 +622,9 @@ private function collectGauges(bool $sortMetrics = true): array
618622
'labelValues' => json_decode($k, true),
619623
'value' => $value,
620624
];
625+
if (json_last_error() !== JSON_ERROR_NONE) {
626+
$this->throwMetricJsonException($key, $gauge['name']);
627+
}
621628
}
622629

623630
if ($sortMetrics) {
@@ -633,6 +640,7 @@ private function collectGauges(bool $sortMetrics = true): array
633640

634641
/**
635642
* @return mixed[]
643+
* @throws MetricJsonException
636644
*/
637645
private function collectCounters(bool $sortMetrics = true): array
638646
{
@@ -645,6 +653,7 @@ private function collectCounters(bool $sortMetrics = true): array
645653
continue;
646654
}
647655
$counter = json_decode($raw['__meta'], true);
656+
648657
unset($raw['__meta']);
649658
$counter['samples'] = [];
650659
foreach ($raw as $k => $value) {
@@ -654,6 +663,10 @@ private function collectCounters(bool $sortMetrics = true): array
654663
'labelValues' => json_decode($k, true),
655664
'value' => $value,
656665
];
666+
667+
if (json_last_error() !== JSON_ERROR_NONE) {
668+
$this->throwMetricJsonException($key, $counter['name']);
669+
}
657670
}
658671

659672
if ($sortMetrics) {
@@ -725,4 +738,17 @@ private function decodeLabelValues(string $values): array
725738
}
726739
return $decodedValues;
727740
}
741+
742+
/**
743+
* @param string $redisKey
744+
* @param string|null $metricName
745+
* @return void
746+
* @throws MetricJsonException
747+
*/
748+
private function throwMetricJsonException(string $redisKey, ?string $metricName = null): void
749+
{
750+
$metricName = $metricName ?? 'unknown';
751+
$message = 'Json error: ' . json_last_error_msg() . ' redis key : ' . $redisKey . ' metric name: ' . $metricName;
752+
throw new MetricJsonException($message, 0, null, $metricName);
753+
}
728754
}

src/Prometheus/Storage/RedisNg.php

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66

77
use InvalidArgumentException;
88
use Prometheus\Counter;
9+
use Prometheus\Exception\MetricJsonException;
910
use Prometheus\Exception\StorageException;
1011
use Prometheus\Gauge;
1112
use Prometheus\Histogram;
@@ -405,6 +406,7 @@ private function metaData(array $data): array
405406

406407
/**
407408
* @return mixed[]
409+
* @throws MetricJsonException
408410
*/
409411
private function collectHistograms(): array
410412
{
@@ -429,6 +431,10 @@ private function collectHistograms(): array
429431
$allLabelValues[] = $d['labelValues'];
430432
}
431433

434+
if (json_last_error() !== JSON_ERROR_NONE) {
435+
$this->throwMetricJsonException($key);
436+
}
437+
432438
// We need set semantics.
433439
// This is the equivalent of array_unique but for arrays of arrays.
434440
$allLabelValues = array_map("unserialize", array_unique(array_map("serialize", $allLabelValues)));
@@ -599,6 +605,9 @@ private function collectGauges(bool $sortMetrics = true): array
599605
'labelValues' => json_decode($k, true),
600606
'value' => $value,
601607
];
608+
if (json_last_error() !== JSON_ERROR_NONE) {
609+
$this->throwMetricJsonException($key, $gauge['name']);
610+
}
602611
}
603612

604613
if ($sortMetrics) {
@@ -614,6 +623,7 @@ private function collectGauges(bool $sortMetrics = true): array
614623

615624
/**
616625
* @return mixed[]
626+
* @throws MetricJsonException
617627
*/
618628
private function collectCounters(bool $sortMetrics = true): array
619629
{
@@ -632,6 +642,9 @@ private function collectCounters(bool $sortMetrics = true): array
632642
'labelValues' => json_decode($k, true),
633643
'value' => $value,
634644
];
645+
if (json_last_error() !== JSON_ERROR_NONE) {
646+
$this->throwMetricJsonException($key, $counter['name']);
647+
}
635648
}
636649

637650
if ($sortMetrics) {
@@ -703,4 +716,17 @@ private function decodeLabelValues(string $values): array
703716
}
704717
return $decodedValues;
705718
}
719+
720+
/**
721+
* @param string $redisKey
722+
* @param string|null $metricName
723+
* @return void
724+
* @throws MetricJsonException
725+
*/
726+
private function throwMetricJsonException(string $redisKey, ?string $metricName = null): void
727+
{
728+
$metricName = $metricName ?? 'unknown';
729+
$message = 'Json error: ' . json_last_error_msg() . ' redis key : ' . $redisKey . ' metric name: ' . $metricName;
730+
throw new MetricJsonException($message, 0, null, $metricName);
731+
}
706732
}

0 commit comments

Comments
 (0)