Skip to content

Commit c652627

Browse files
Merge pull request #5 from whatwedo/fix/prevent-state-call-on-null
Introduces new interfaces for state management in sensors and metrics, and improves error handling and robustness across the monitoring system.
2 parents 82d093b + 5bd8905 commit c652627

13 files changed

Lines changed: 197 additions & 33 deletions

File tree

src/Command/CheckCommand.php

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,12 @@ private function printResult(SymfonyStyle $io, $result, $previousGroup = null, $
4343
$rows = [];
4444
$subs = [];
4545
foreach ($items as $subGroup => $row) {
46+
if (is_array($row)) {
47+
$subs[$subGroup] = $row;
48+
49+
continue;
50+
}
51+
4652
if ($row instanceof AbstractSensor) {
4753
$rows[] = [
4854
sprintf('<fg=%s;options=bold>%s</>', $row->getState()->getCliColor(), $row->getState()->getIcon()),
@@ -55,8 +61,6 @@ private function printResult(SymfonyStyle $io, $result, $previousGroup = null, $
5561
$row->getName(),
5662
$row->getValue(),
5763
];
58-
} elseif (is_array($row)) {
59-
$subs[$subGroup] = $row;
6064
}
6165
}
6266

src/Manager/MonitoringManager.php

Lines changed: 21 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,8 @@
77
use whatwedo\MonitorBundle\Enums\MetricStateEnum;
88
use whatwedo\MonitorBundle\Enums\SensorStateEnum;
99
use whatwedo\MonitorBundle\Monitoring\AttributeInterface;
10-
use whatwedo\MonitorBundle\Monitoring\Sensor\AbstractSensor;
10+
use whatwedo\MonitorBundle\Monitoring\Metric\MetricStateInterface;
11+
use whatwedo\MonitorBundle\Monitoring\Sensor\SensorStateInterface;
1112

1213
class MonitoringManager
1314
{
@@ -106,15 +107,27 @@ public function getAttribute(string $className): AttributeInterface
106107

107108
private function wasSuccessful(AttributeInterface $attribute): bool
108109
{
109-
return $attribute instanceof AbstractSensor
110-
? $attribute->getState() === SensorStateEnum::SUCCESSFUL
111-
: $attribute->getState() === MetricStateEnum::OK;
110+
if ($attribute instanceof SensorStateInterface) {
111+
return $attribute->getState() === SensorStateEnum::SUCCESSFUL;
112+
}
113+
114+
if ($attribute instanceof MetricStateInterface) {
115+
return $attribute->getState() === MetricStateEnum::OK;
116+
}
117+
118+
return false;
112119
}
113120

114-
private function wasWarning(AttributeInterface $abstract): bool
121+
private function wasWarning(AttributeInterface $attribute): bool
115122
{
116-
return $abstract instanceof AbstractSensor
117-
? $abstract->getState() === SensorStateEnum::WARNING
118-
: $abstract->getState() === MetricStateEnum::WARNING;
123+
if ($attribute instanceof SensorStateInterface) {
124+
return $attribute->getState() === SensorStateEnum::WARNING;
125+
}
126+
127+
if ($attribute instanceof MetricStateInterface) {
128+
return $attribute->getState() === MetricStateEnum::WARNING;
129+
}
130+
131+
return false;
119132
}
120133
}

src/Monitoring/Metric/AbstractMetric.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
use whatwedo\MonitorBundle\Enums\MetricStateEnum;
88
use whatwedo\MonitorBundle\Monitoring\AttributeInterface;
99

10-
abstract class AbstractMetric implements AttributeInterface
10+
abstract class AbstractMetric implements AttributeInterface, MetricStateInterface
1111
{
1212
public null|int|float $value = null;
1313

@@ -16,7 +16,7 @@ abstract class AbstractMetric implements AttributeInterface
1616
public function getState(): MetricStateEnum
1717
{
1818
if ($this->state === null) {
19-
throw new \RuntimeException(static::class.'::$state is not set.');
19+
throw new \LogicException(static::class.'::$state is not set.');
2020
}
2121

2222
return $this->state;
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace whatwedo\MonitorBundle\Monitoring\Metric;
6+
7+
use whatwedo\MonitorBundle\Enums\MetricStateEnum;
8+
9+
interface MetricStateInterface
10+
{
11+
/**
12+
* @throws \LogicException
13+
*/
14+
public function getState(): MetricStateEnum;
15+
}

src/Monitoring/Sensor/AbstractSensor.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
use whatwedo\MonitorBundle\Enums\SensorStateEnum;
88
use whatwedo\MonitorBundle\Monitoring\AttributeInterface;
99

10-
abstract class AbstractSensor implements AttributeInterface
10+
abstract class AbstractSensor implements AttributeInterface, SensorStateInterface
1111
{
1212
public ?SensorStateEnum $state = null;
1313

@@ -16,7 +16,7 @@ abstract class AbstractSensor implements AttributeInterface
1616
public function getState(): SensorStateEnum
1717
{
1818
if ($this->state === null) {
19-
throw new \RuntimeException(__CLASS__.'::$state is not set.');
19+
throw new \LogicException(static::class.'::$state is not set.');
2020
}
2121

2222
return $this->state;
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace whatwedo\MonitorBundle\Monitoring\Sensor;
6+
7+
use whatwedo\MonitorBundle\Enums\SensorStateEnum;
8+
9+
interface SensorStateInterface
10+
{
11+
/**
12+
* @throws \LogicException
13+
*/
14+
public function getState(): SensorStateEnum;
15+
}

src/Normalizer/AttributeNormalizer.php

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,19 @@
44

55
namespace whatwedo\MonitorBundle\Normalizer;
66

7+
use Symfony\Component\Serializer\Normalizer\NormalizerAwareInterface;
8+
use Symfony\Component\Serializer\Normalizer\NormalizerAwareTrait;
79
use Symfony\Component\Serializer\Normalizer\NormalizerInterface;
810
use whatwedo\MonitorBundle\Monitoring\AttributeInterface;
911
use whatwedo\MonitorBundle\Monitoring\Metric\AbstractMetric;
12+
use whatwedo\MonitorBundle\Monitoring\Metric\MetricStateInterface;
1013
use whatwedo\MonitorBundle\Monitoring\Sensor\AbstractSensor;
14+
use whatwedo\MonitorBundle\Monitoring\Sensor\SensorStateInterface;
1115

12-
class AttributeNormalizer implements NormalizerInterface
16+
class AttributeNormalizer implements NormalizerInterface, NormalizerAwareInterface
1317
{
18+
use NormalizerAwareTrait;
19+
1420
/**
1521
* @param AttributeInterface $object
1622
*/
@@ -20,13 +26,18 @@ public function normalize($object, string $format = null, array $context = []):
2026
'name' => $object->getName(),
2127
];
2228

29+
try {
30+
if ($object instanceof MetricStateInterface || $object instanceof SensorStateInterface) {
31+
$data['state'] = $this->normalizer->normalize($object->getState());
32+
}
33+
} catch (\LogicException) {
34+
}
35+
2336
if ($object instanceof AbstractSensor) {
24-
$data['state'] = $object->getState();
2537
$data['details'] = $object->getDetails();
2638
}
2739

2840
if ($object instanceof AbstractMetric) {
29-
$data['state'] = $object->getState();
3041
$data['value'] = $object->getValue();
3142
}
3243

tests/Command/CheckCommandTest.php

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -92,24 +92,24 @@ public function testCriticalCustomExitCode(): void
9292
self::assertEquals(-1, $commandTester->getStatusCode());
9393
}
9494

95-
public function testRuntimeError(): void
95+
public function testLogicError(): void
9696
{
9797
$kernel = self::bootKernel([
9898
'config' => static function (TestKernel $kernel) {
99-
$kernel->addTestConfig(__DIR__.'/../config/dummy_runtime_error.yml');
99+
$kernel->addTestConfig(__DIR__.'/../config/dummy_logic_error.yml');
100100
},
101101
]);
102102
$application = new Application($kernel);
103103
$command = $application->find('whatwedo:monitor:check');
104104

105105
$commandTester = new CommandTester($command);
106-
$runtimeException = false;
106+
$logicException = false;
107107
try {
108108
$commandTester->execute([]);
109-
} catch (\RuntimeException $e) {
110-
$runtimeException = true;
109+
} catch (\LogicException $e) {
110+
$logicException = true;
111111
} finally {
112-
self::assertTrue($runtimeException);
112+
self::assertTrue($logicException);
113113
}
114114
}
115115
}

tests/Monitoring/Metric/Dummy/RuntimeErrorDummyMetric.php renamed to tests/Monitoring/Metric/Dummy/LogicErrorDummyMetric.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,11 +31,11 @@
3131

3232
use whatwedo\MonitorBundle\Monitoring\Metric\AbstractMetric;
3333

34-
class RuntimeErrorDummyMetric extends AbstractMetric
34+
class LogicErrorDummyMetric extends AbstractMetric
3535
{
3636
public function getName(): string
3737
{
38-
return 'Runtime Error Test';
38+
return 'Logic Error Test';
3939
}
4040

4141
public function isEnabled(): bool

tests/Monitoring/Sensor/Dummy/RuntimeErrorDummySensor.php renamed to tests/Monitoring/Sensor/Dummy/LogicErrorDummySensor.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,11 +31,11 @@
3131

3232
use whatwedo\MonitorBundle\Monitoring\Sensor\AbstractSensor;
3333

34-
class RuntimeErrorDummySensor extends AbstractSensor
34+
class LogicErrorDummySensor extends AbstractSensor
3535
{
3636
public function getName(): string
3737
{
38-
return 'Runtime Error Test';
38+
return 'Logic Error Test';
3939
}
4040

4141
public function isEnabled(): bool

0 commit comments

Comments
 (0)