DevOps

/laravel-agent:health:setup

Setup application health monitoring using spatie/laravel-health

Overview

The /health:setup command configures comprehensive health monitoring for your Laravel application using the spatie/laravel-health package. It automates the installation, configuration, and setup of various health checks to monitor database connectivity, cache availability, Redis, queues, disk space, scheduler status, and more.

Usage

/laravel-agent:health:setup [--checks=<db,cache,redis,queue,storage,schedule>]

Examples

# Interactive setup with all checks
/laravel-agent:health:setup

# Setup specific checks
/laravel-agent:health:setup --checks=db,cache,redis

# Setup with queue and storage monitoring
/laravel-agent:health:setup --checks=db,queue,storage,schedule

Installation Process

The command automates the following steps:

  1. Install Package - Adds spatie/laravel-health via Composer
  2. Publish Configuration - Publishes config file and migrations
  3. Run Migrations - Creates result storage tables
  4. Configure Health Checks - Registers selected health checks in AppServiceProvider
  5. Setup Routes - Adds dashboard and API endpoints
  6. Schedule Checks - Configures automated health check execution

Available Health Checks

The command can configure the following health checks:

Check Description Thresholds
DatabaseCheck Verifies database connectivity Connection test
CacheCheck Tests cache read/write operations Read/write test
RedisCheck Checks Redis server connection Ping test
QueueCheck Monitors queue job processing Job processing
UsedDiskSpaceCheck Monitors disk space usage Warn >70%, Fail >90%
ScheduleCheck Verifies scheduler is running Max age 2 minutes
DebugModeCheck Ensures debug mode is off in production Production only
EnvironmentCheck Validates environment configuration Expected environment
DatabaseSizeCheck Monitors database size Fail when >5GB
DatabaseConnectionCountCheck Tracks database connection count Warn >50, Fail >100
HorizonCheck Monitors Laravel Horizon status Service running
BackupsCheck Verifies backup recency and count <1 day old, >1 backup
OptimizedAppCheck Ensures app is optimized for production Config/routes cached

Interactive Prompts

When run without arguments, the command presents interactive prompts:

1. Which health checks to enable?

  • [x] Database connection
  • [x] Cache availability
  • [x] Redis connection
  • [x] Queue processing
  • [x] Disk space
  • [x] Schedule running
  • [ ] Debug mode (production only)
  • [ ] Environment check
  • [ ] Database size
  • [ ] Horizon status
  • [ ] Backup status

2. How often to run checks?

  • Every minute (recommended)
  • Every 5 minutes
  • Every 15 minutes

3. Notification on failure?

  • Email
  • Slack
  • Discord
  • None

4. Enable health dashboard?

  • Yes (with auth protection)
  • JSON API only
  • No dashboard

Generated Configuration

Health Checks Registration

The command registers health checks in your AppServiceProvider:

<?php

// app/Providers/AppServiceProvider.php
use Spatie\Health\Facades\Health;
use Spatie\Health\Checks\Checks\BackupsCheck;
use Spatie\Health\Checks\Checks\CacheCheck;
use Spatie\Health\Checks\Checks\DatabaseCheck;
use Spatie\Health\Checks\Checks\DatabaseConnectionCountCheck;
use Spatie\Health\Checks\Checks\DatabaseSizeCheck;
use Spatie\Health\Checks\Checks\DebugModeCheck;
use Spatie\Health\Checks\Checks\EnvironmentCheck;
use Spatie\Health\Checks\Checks\HorizonCheck;
use Spatie\Health\Checks\Checks\OptimizedAppCheck;
use Spatie\Health\Checks\Checks\QueueCheck;
use Spatie\Health\Checks\Checks\RedisCheck;
use Spatie\Health\Checks\Checks\ScheduleCheck;
use Spatie\Health\Checks\Checks\UsedDiskSpaceCheck;

public function boot(): void
{
    Health::checks([
        // Environment checks
        EnvironmentCheck::new()->expectEnvironment('production'),
        DebugModeCheck::new(),
        OptimizedAppCheck::new(),

        // Database checks
        DatabaseCheck::new(),
        DatabaseConnectionCountCheck::new()
            ->warnWhenMoreConnectionsThan(50)
            ->failWhenMoreConnectionsThan(100),
        DatabaseSizeCheck::new()
            ->failWhenSizeAboveGb(errorThresholdGb: 5.0),

        // Cache & Redis
        CacheCheck::new(),
        RedisCheck::new(),

        // Queue & Jobs
        QueueCheck::new(),
        HorizonCheck::new(), // If using Horizon

        // Scheduler
        ScheduleCheck::new()
            ->heartbeatMaxAgeInMinutes(2),

        // Storage
        UsedDiskSpaceCheck::new()
            ->warnWhenUsedSpaceIsAbovePercentage(70)
            ->failWhenUsedSpaceIsAbovePercentage(90),

        // Backups (if using spatie/laravel-backup)
        BackupsCheck::new()
            ->locatedAt(storage_path('app/backups'))
            ->youngestBackShouldHaveBeenMadeInDays(1)
            ->numberOfBackupsGreaterThan(1),
    ]);
}

Health Check Routes

Routes are added to your web.php file:

<?php

// routes/web.php
use Spatie\Health\Http\Controllers\HealthCheckResultsController;
use Spatie\Health\Http\Controllers\HealthCheckJsonResultsController;

// HTML dashboard (protect with auth in production)
Route::middleware(['auth', 'can:viewHealth'])->group(function () {
    Route::get('/health', HealthCheckResultsController::class);
});

// JSON API endpoint (for monitoring services)
Route::get('/api/health', HealthCheckJsonResultsController::class);

// Simple ping endpoint
Route::get('/api/ping', fn () => response()->json(['status' => 'ok']));

Scheduled Health Checks

The command adds scheduled execution to your Kernel:

<?php

// app/Console/Kernel.php
$schedule->command('health:check')->everyMinute();

// Or run specific checks less frequently
$schedule->command('health:check --only=DatabaseSizeCheck,UsedDiskSpaceCheck')
    ->hourly();

Custom Health Check Example

You can create custom health checks for your specific needs:

<?php

declare(strict_types=1);

namespace App\Health\Checks;

use Spatie\Health\Checks\Check;
use Spatie\Health\Checks\Result;

final class ApiConnectionCheck extends Check
{
    protected string $apiUrl;

    public function apiUrl(string $url): self
    {
        $this->apiUrl = $url;
        return $this;
    }

    public function run(): Result
    {
        $result = Result::make();

        try {
            $response = Http::timeout(5)->get($this->apiUrl . '/health');

            if ($response->successful()) {
                return $result->ok('API is reachable');
            }

            return $result->failed("API returned status {$response->status()}");
        } catch (\Exception $e) {
            return $result->failed("API unreachable: {$e->getMessage()}");
        }
    }
}

// Register in AppServiceProvider
Health::checks([
    ApiConnectionCheck::new()
        ->name('External API')
        ->apiUrl('https://api.example.com'),
]);

Configuration File

The command publishes and configures config/health.php:

<?php

use Spatie\Health\Checks\Checks\BackupsCheck;
use Spatie\Health\Checks\Checks\CacheCheck;
use Spatie\Health\Checks\Checks\DatabaseCheck;
use Spatie\Health\Checks\Checks\DatabaseConnectionCountCheck;
use Spatie\Health\Checks\Checks\DatabaseSizeCheck;
use Spatie\Health\Checks\Checks\DebugModeCheck;
use Spatie\Health\Checks\Checks\EnvironmentCheck;
use Spatie\Health\Checks\Checks\HorizonCheck;
use Spatie\Health\Checks\Checks\OptimizedAppCheck;
use Spatie\Health\Checks\Checks\QueueCheck;
use Spatie\Health\Checks\Checks\RedisCheck;
use Spatie\Health\Checks\Checks\ScheduleCheck;
use Spatie\Health\Checks\Checks\UsedDiskSpaceCheck;

return [
    'result_stores' => [
        Spatie\Health\ResultStores\EloquentHealthResultStore::class => [
            'model' => Spatie\Health\Models\HealthCheckResultHistoryItem::class,
            'keep_history_for_days' => 7,
        ],
    ],

    'notifications' => [
        'enabled' => true,

        'notifications' => [
            Spatie\Health\Notifications\CheckFailedNotification::class => ['mail'],
        ],

        'notifiable' => Spatie\Health\Notifications\Notifiable::class,

        'throttle_notifications_for_minutes' => 60,
        'throttle_notifications_key' => 'health:notifications:throttle',
    ],

    'oh_dear_endpoint' => [
        'enabled' => false,
        'secret' => env('OH_DEAR_HEALTH_CHECK_SECRET'),
        'url' => '/oh-dear-health-check-results',
    ],

    'silence_health_queue_job' => true,
];

Available Commands

After setup, these artisan commands become available:

# Run all configured health checks
php artisan health:check

# List all configured health checks
php artisan health:list

# Clear cache and run fresh checks
php artisan health:check --fresh

# Run only specific checks
php artisan health:check --only=DatabaseCheck,CacheCheck

Accessing Health Status

Once configured, you can access health information through:

  • HTML Dashboard - Visit /health for a visual dashboard (requires authentication)
  • JSON API - Query /api/health for programmatic access
  • Simple Ping - Use /api/ping for basic uptime monitoring
  • Oh Dear Integration - Connect to Oh Dear monitoring service (optional)

Notification Setup

The command can configure notifications for failed health checks:

  • Email - Uses Laravel's mail configuration
  • Slack - Requires Slack webhook URL
  • Discord - Requires Discord webhook URL
  • Throttling - Prevents notification spam (default: 60 minutes)

Best Practices

  1. Start with core checks - Begin with database, cache, and storage checks
  2. Run checks frequently - Every minute is recommended for critical systems
  3. Protect the dashboard - Always use authentication middleware in production
  4. Configure thresholds - Adjust warning/failure levels based on your infrastructure
  5. Enable notifications - Get alerted immediately when checks fail
  6. Monitor from outside - Use external monitoring services to ping your health endpoint
  7. Keep history - Store results for trend analysis (default: 7 days)
  8. Test custom checks - Verify custom health checks work before deploying

Example Output

After successful setup, the command displays:

## Health Monitoring Setup Complete

### Package Installed
- spatie/laravel-health

### Health Checks Configured
| Check | Status | Threshold |
|-------|--------|-----------|
| Database | Enabled | Connection test |
| Cache | Enabled | Read/write test |
| Redis | Enabled | Ping test |
| Queue | Enabled | Job processing |
| Disk Space | Enabled | Warn >70%, Fail >90% |
| Schedule | Enabled | Max age 2 minutes |

### Routes Added
- GET `/health` - HTML dashboard (auth protected)
- GET `/api/health` - JSON endpoint

### Schedule
- `health:check` runs every minute

### Commands Available
```bash
php artisan health:check         # Run all checks
php artisan health:list          # List configured checks
php artisan health:check --fresh # Clear cache and run
```

### Next Steps
1. Run `php artisan migrate` for result storage
2. Visit `/health` to view dashboard
3. Configure monitoring service to ping `/api/health`
4. Test alert notifications

Monitoring Integration

Popular monitoring services that work with the health endpoint:

  • Oh Dear - Native integration with dedicated endpoint
  • UptimeRobot - Monitor the /api/health JSON endpoint
  • Pingdom - HTTP check on /api/ping
  • New Relic - Synthetic monitoring of health endpoints
  • Datadog - Custom integration with JSON endpoint

See Also