From c70d96c3aaf53c8be26a5e3e56dbae99b27cc0ec Mon Sep 17 00:00:00 2001 From: ArthurErlich Date: Sat, 30 May 2026 14:13:24 +0200 Subject: [PATCH] feat(health): make /health report per-provider probe status Introduce ProviderHealthChecker which probes each configured provider via AutowireIterator. Wire it into GraphController so /health returns detailed per-provider status and responds 503 when any provider is in a degraded state. Co-Authored-By: Claude Sonnet 4.6 --- src/Controller/GraphController.php | 17 +++++++++--- src/Service/ProviderHealthChecker.php | 39 +++++++++++++++++++++++++++ 2 files changed, 52 insertions(+), 4 deletions(-) create mode 100644 src/Service/ProviderHealthChecker.php diff --git a/src/Controller/GraphController.php b/src/Controller/GraphController.php index 6fbec66..d9f15f6 100644 --- a/src/Controller/GraphController.php +++ b/src/Controller/GraphController.php @@ -1,8 +1,11 @@ */ private readonly array $allowedHosts; @@ -23,6 +26,7 @@ class GraphController private readonly SvgRenderer $renderer, private readonly CacheInterface $cache, private readonly LoggerInterface $logger, + private readonly ProviderHealthChecker $healthChecker, #[Autowire(env: 'ALLOWED_HOSTS')] string $allowedHosts = '', ) { @@ -73,8 +77,13 @@ class GraphController #[Route('/health', name: 'health', methods: ['GET'])] public function health(): Response { - return new Response('{"status":"ok"}', 200, ['Content-Type' => 'application/json']); + $result = $this->healthChecker->check(); + $statusCode = $result['status'] === 'degraded' ? 503 : 200; + + return new Response( + json_encode($result, JSON_PRETTY_PRINT | JSON_THROW_ON_ERROR), + $statusCode, + ['Content-Type' => 'application/json'], + ); } - - } diff --git a/src/Service/ProviderHealthChecker.php b/src/Service/ProviderHealthChecker.php new file mode 100644 index 0000000..8ffe9a0 --- /dev/null +++ b/src/Service/ProviderHealthChecker.php @@ -0,0 +1,39 @@ +>} + */ + public function check(): array + { + $statuses = []; + $hasError = false; + + /** @var ProviderInterface $provider */ + foreach ($this->providers as $provider) { + $status = $provider->probe(); + $statuses[$status->name] = $status->toArray(); + + if ($status->status === ProviderStatusType::Error) { + $hasError = true; + } + } + + return [ + 'status' => $hasError ? 'degraded' : 'ok', + 'providers' => $statuses, + ]; + } +}