feat(api) : add /api/health endpoint for monitoring
- Returns status, version, timestamp, PHP version, DB latency and memory usage - Accessible without authentication (PUBLIC_ACCESS) - Returns 200 when healthy, 503 when degraded (DB down)
This commit is contained in:
@@ -55,6 +55,7 @@ security:
|
|||||||
- { path: ^/api/admin, roles: ROLE_ADMIN }
|
- { path: ^/api/admin, roles: ROLE_ADMIN }
|
||||||
- { path: ^/api/docs, roles: PUBLIC_ACCESS }
|
- { path: ^/api/docs, roles: PUBLIC_ACCESS }
|
||||||
- { path: ^/api/test, roles: PUBLIC_ACCESS }
|
- { path: ^/api/test, roles: PUBLIC_ACCESS }
|
||||||
|
- { path: ^/api/health$, roles: PUBLIC_ACCESS }
|
||||||
- { path: ^/docs, roles: PUBLIC_ACCESS }
|
- { path: ^/docs, roles: PUBLIC_ACCESS }
|
||||||
- { path: ^/contexts, roles: PUBLIC_ACCESS }
|
- { path: ^/contexts, roles: PUBLIC_ACCESS }
|
||||||
- { path: ^/\.well-known, roles: PUBLIC_ACCESS }
|
- { path: ^/\.well-known, roles: PUBLIC_ACCESS }
|
||||||
|
|||||||
53
src/Controller/HealthCheckController.php
Normal file
53
src/Controller/HealthCheckController.php
Normal file
@@ -0,0 +1,53 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace App\Controller;
|
||||||
|
|
||||||
|
use DateTimeImmutable;
|
||||||
|
use DateTimeInterface;
|
||||||
|
use Doctrine\DBAL\Connection;
|
||||||
|
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
|
||||||
|
use Symfony\Component\HttpFoundation\JsonResponse;
|
||||||
|
use Symfony\Component\Routing\Attribute\Route;
|
||||||
|
use Throwable;
|
||||||
|
|
||||||
|
class HealthCheckController extends AbstractController
|
||||||
|
{
|
||||||
|
#[Route('/api/health', name: 'api_health', methods: ['GET'])]
|
||||||
|
public function __invoke(Connection $connection): JsonResponse
|
||||||
|
{
|
||||||
|
$version = '0.0.0';
|
||||||
|
$versionFile = $this->getParameter('kernel.project_dir').'/VERSION';
|
||||||
|
if (file_exists($versionFile)) {
|
||||||
|
$version = trim(file_get_contents($versionFile));
|
||||||
|
}
|
||||||
|
|
||||||
|
$dbOk = false;
|
||||||
|
$dbLatency = null;
|
||||||
|
|
||||||
|
try {
|
||||||
|
$start = hrtime(true);
|
||||||
|
$connection->executeQuery('SELECT 1');
|
||||||
|
$dbLatency = round((hrtime(true) - $start) / 1e6, 1);
|
||||||
|
$dbOk = true;
|
||||||
|
} catch (Throwable) {
|
||||||
|
}
|
||||||
|
|
||||||
|
$healthy = $dbOk;
|
||||||
|
|
||||||
|
return $this->json([
|
||||||
|
'status' => $healthy ? 'ok' : 'degraded',
|
||||||
|
'version' => $version,
|
||||||
|
'timestamp' => new DateTimeImmutable()->format(DateTimeInterface::ATOM),
|
||||||
|
'php' => PHP_VERSION,
|
||||||
|
'checks' => [
|
||||||
|
'database' => [
|
||||||
|
'status' => $dbOk ? 'ok' : 'down',
|
||||||
|
'latency_ms' => $dbLatency,
|
||||||
|
],
|
||||||
|
],
|
||||||
|
'memory_mb' => round(memory_get_usage(true) / 1024 / 1024, 1),
|
||||||
|
], $healthy ? 200 : 503);
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user