plusforta/health-bundle

Symfony health check bundle inspired by Spatie's laravel-health

Maintainers

Package info

gitlab.com/plusforta/public/healthbundle

Issues

Type:symfony-bundle

pkg:composer/plusforta/health-bundle

Statistics

Installs: 1

Dependents: 0

Suggesters: 0

Stars: 0

1.0.0 2026-03-24 16:46 UTC

This package is not auto-updated.

Last update: 2026-03-25 14:02:15 UTC


README

A Symfony bundle for monitoring the health of your application. It provides a set of built-in health checks, an HTTP endpoint compatible with Oh Dear application health monitoring, and a simple API for creating your own custom checks.

This package was entirely inspired by the excellent spatie/laravel-health package.

Installation

composer require plusforta/health-bundle

Requirements: PHP 8.2+, Symfony 6.4 or 7.0

Configuration

Create config/packages/health.yaml:

health:
    endpoint:
        enabled: true
        path: /health-check-results
        secret: '%env(HEALTH_CHECK_SECRET)%'
        always_send_fresh_results: true
        failure_status_code: 200

    result_stores:
        json_file:
            enabled: true
            path: '%kernel.project_dir%/var/health-check-results.json'
        cache:
            enabled: true
            pool: cache.app
        doctrine:
            enabled: true
            connection: ~
            keep_history_for_days: 5

    notifications:
        enabled: false
        throttle_minutes: 60
        only_on_failure: true
        email:
            to: admin@example.com
            from: health@example.com
        slack:
            dsn: 'slack://token@default/channel'

    checks:
        database:
            class: Plusforta\Health\Check\Checks\DatabaseCheck
            label: Database Connection
        disk_space:
            class: Plusforta\Health\Check\Checks\UsedDiskSpaceCheck
            options:
                warning_threshold: 70
                error_threshold: 90

Oh Dear Integration

This bundle is designed to work with Oh Dear's application health monitoring out of the box. The JSON endpoint uses the ohdearapp/health-check-results package to produce output in the exact format Oh Dear expects:

{
    "finishedAt": 1234567890,
    "checkResults": [
        {
            "name": "Database",
            "label": "Database Connection",
            "notificationMessage": "",
            "shortSummary": "Ok",
            "status": "ok",
            "meta": {
                "connection_name": "default"
            }
        }
    ]
}

Simply point Oh Dear at your /health-check-results endpoint (with the secret token if configured) and it will start monitoring your checks.

You can also protect the endpoint with a secret token, passed via the X-Secret-Token header or ?secret= query parameter.

While built for Oh Dear, the JSON output is straightforward and can be consumed by any monitoring system.

Built-in Checks

CheckDescriptionRequires
DatabaseCheckVerifies database connectivity via SELECT 1doctrine/dbal
DatabaseConnectionCountCheckMonitors active database connectionsdoctrine/dbal
DatabaseSizeCheckChecks total database size in GBdoctrine/dbal
DatabaseTableSizeCheckChecks individual table sizedoctrine/dbal
CacheCheckTests cache read/write/delete operationssymfony/cache
RedisCheckVerifies Redis connectivity via PINGRedis extension or Predis
RedisMemoryUsageCheckMonitors Redis memory consumptionRedis extension or Predis
PingCheckMakes HTTP requests to verify external servicessymfony/http-client
MeilisearchCheckVerifies Meilisearch health endpointsymfony/http-client
UsedDiskSpaceCheckMonitors disk usage with configurable thresholdssymfony/process
EnvironmentCheckAsserts the application environment (prod, dev, etc.)-
DebugModeCheckAsserts the kernel debug mode state-
ProfilerCheckDetects if the WebProfilerBundle is active-
MessengerCheckHeartbeat mechanism to detect stuck message consumerssymfony/messenger

Creating Custom Checks

Creating a custom health check is straightforward. Extend the abstract Check class and implement the run() method:

<?php

declare(strict_types=1);

namespace App\Health\Checks;

use Plusforta\Health\Check\Check;
use Plusforta\Health\Result\Result;

class QueueDepthCheck extends Check
{
    public function __construct(
        private readonly int $warningThreshold = 100,
        private readonly int $errorThreshold = 500,
    ) {
    }

    public function run(): Result
    {
        $depth = $this->getQueueDepth();

        if ($depth >= $this->errorThreshold) {
            return Result::make("Queue depth is {$depth}")
                ->failed()
                ->shortSummary("{$depth} jobs")
                ->meta(['depth' => $depth]);
        }

        if ($depth >= $this->warningThreshold) {
            return Result::make("Queue depth is {$depth}")
                ->warning()
                ->shortSummary("{$depth} jobs")
                ->meta(['depth' => $depth]);
        }

        return Result::make()
            ->ok()
            ->shortSummary("{$depth} jobs")
            ->meta(['depth' => $depth]);
    }

    private function getQueueDepth(): int
    {
        // Your logic here
    }
}

The Result Object

The Result class uses a fluent builder pattern. Available methods:

  • Result::make(string $message = '') - Create a new result
  • ->ok(), ->warning(), ->failed(), ->crashed(), ->skipped() - Set the status
  • ->shortSummary(string) - A brief status string (shown in Oh Dear dashboard)
  • ->notificationMessage(string) - Message used in notifications
  • ->meta(array) - Arbitrary metadata (included in JSON output)

Registering Custom Checks

Register your check in your bundle configuration:

health:
    checks:
        queue_depth:
            class: App\Health\Checks\QueueDepthCheck
            label: Message Queue
            options:
                warning_threshold: 100
                error_threshold: 500

Or tag it as a service directly:

services:
    App\Health\Checks\QueueDepthCheck:
        tags: ['health.check']

Naming and Labels

Check names and labels are derived automatically from the class name. QueueDepthCheck becomes:

  • Name: QueueDepth
  • Label: Queue Depth

You can override both:

QueueDepthCheck::new()
    ->name('queue')
    ->label('RabbitMQ Queue Depth');

CLI Commands

# Run all health checks and display results
php bin/console health:check

# Run checks but don't store results or send notifications
php bin/console health:check --no-store --no-notification

# Exit with non-zero code if any check fails
php bin/console health:check --fail-on-error

# List all registered checks
php bin/console health:list

# Pause health checks (e.g. during deployments)
php bin/console health:pause

# Resume health checks
php bin/console health:resume

Events

The bundle dispatches events before and after each check runs:

  • CheckStartingEvent - Dispatched before a check runs
  • CheckEndedEvent - Dispatched after a check completes, includes the result

Use these to add logging, metrics, or custom side effects.

Result Stores

Results can be persisted to multiple stores simultaneously:

StoreDescription
InMemoryResultStoreStatic in-memory storage (useful for testing)
JsonFileResultStorePersists results to a JSON file
CacheResultStoreUses Symfony's cache component
DoctrineResultStoreDatabase storage with automatic history tracking and pruning

License

MIT