LiipMonitorBundle
LiipMonitorBundle copied to clipboard
OhDear Reporter & Health Check controller
Not sure if we should include here or a separate bundle?
Ref: https://twitter.com/zenstruck/status/1471115679986335747 Ref: https://ohdear.app/docs/general/application-health-monitoring
Here is how I wired it up in my app:
use Laminas\Diagnostics\Check\CheckInterface;
use Laminas\Diagnostics\Result\Collection as ResultsCollection;
use Laminas\Diagnostics\Result\ResultInterface;
use Laminas\Diagnostics\Result\Skip;
use Laminas\Diagnostics\Result\Success;
use Laminas\Diagnostics\Result\Warning;
use Laminas\Diagnostics\Runner\Reporter\ReporterInterface;
/**
* @author Kevin Bond <[email protected]>
*/
final class OhDearReporter implements ReporterInterface
{
private array $results = [];
public function results(): array
{
return $this->results;
}
public function onAfterRun(CheckInterface $check, ResultInterface $result, $checkAlias = null): void
{
$this->results[] = [
'name' => $checkAlias ?? $check->getLabel(),
'label' => $check->getLabel(),
'status' => self::statusFor($result),
'notificationMessage' => $result->getMessage(),
'shortSummary' => $result->getMessage(),
'meta' => [],
];
}
public function onStart(\ArrayObject $checks, $runnerConfig): void
{
}
public function onBeforeRun(CheckInterface $check, $checkAlias = null): void
{
}
public function onStop(ResultsCollection $results): void
{
}
public function onFinish(ResultsCollection $results): void
{
}
private static function statusFor(ResultInterface $result): string
{
switch (true) {
case $result instanceof Success:
return 'ok';
case $result instanceof Warning:
return 'warning';
case $result instanceof Skip:
return 'skipped';
}
return 'crashed';
}
}
use ...\OhDearReporter;
use Liip\MonitorBundle\Runner;
use Symfony\Component\Cache\CacheItem;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
use Symfony\Contracts\Cache\CacheInterface;
/**
* @author Kevin Bond <[email protected]>
*/
final class HealthCheckController
{
private Runner $runner;
private string $secret;
public function __construct(Runner $runner, string $secret)
{
$this->runner = $runner;
$this->secret = $secret;
}
public function __invoke(Request $request, CacheInterface $cache): JsonResponse
{
if ($this->secret !== $request->headers->get('oh-dear-health-check-secret')) {
throw new NotFoundHttpException();
}
$results = $cache->get('ohdear-health-check', function(CacheItem $item) {
$this->runner->addReporter($reporter = new OhDearReporter());
$this->runner->run();
$item->expiresAfter(300);
return $reporter->results();
});
return new JsonResponse([
'finishedAt' => \time(),
'checkResults' => $results,
]);
}
}