Extending Laravel 11's Health Endpoint for Reliable Monitoring
Keeping your web applications running smoothly means staying ahead of potential issues before they impact users. That’s where Laravel 11’s health endpoint comes in. Out of the box, it provides a quick way to check your app’s status via the /up endpoint.
But why stop there? By extending this functionality, you can gain deeper insights into your system’s health and catch problems early—before they turn into downtime. In this post, we’ll explore how to customize the health endpoint to monitor your application more comprehensively.
We've been lugging around a simple code snippet between projects to ensure all aspects of our projects are up and running properly. Some of the services we like to make sure are up and running include:
- Database
- Queue/Horizon
- Cache/Redis
- Broadcasting
By listening for the Illuminate\Foundation\Events\DiagnosingHealth
event, we can do it a bit more than simply render a view to test if our application is up and running:
namespace App\Listeners;
use Exception;
use Carbon\Carbon;
use App\Events\HealthEvent;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Redis;
use Illuminate\Foundation\Events\DiagnosingHealth;
use Laravel\Horizon\Contracts\MasterSupervisorRepository;
class DiagnosingHealthListener
{
/**
* Create the event listener.
*/
public function __construct()
{
//
}
/**
* Handle the event.
*/
public function handle(DiagnosingHealth $event)
{
$status = 200;
$response = [
'status' => true,
'time' => (string) Carbon::now(),
'queue' => false,
'cache' => false,
'db' => false,
'reverb' => false,
];
try {
DB::connection()->getPdo();
$response['db'] = true;
} catch (\Exception $e) {
$status = 400;
}
try {
Redis::connection()->client()->ping();
$response['cache'] = true;
} catch (\Exception $e) {
$status = 400;
}
try {
if (!app()->environment('testing', 'local') && $this->horizonStatus() !== 'running') {
throw new Exception('Horizon is not active');
}
$response['queue'] = true;
} catch (\Exception $e) {
$status = 400;
}
try {
HealthEvent::dispatch();
$response['reverb'] = true;
} catch (\Exception $e) {
$status = 400;
}
if ($status !== 200) {
http_response_code($status);
header('Content-Type: application/json');
echo json_encode($response);
exit;
}
}
/**
* Get the current status of Horizon.
*
* @return string
*/
private function horizonStatus()
{
if (!$masters = app(MasterSupervisorRepository::class)->all()) {
return 'inactive';
}
return collect($masters)->every(function ($master) {
return $master->status === 'paused';
}) ? 'paused' : 'running';
}
}
Here's the HealthEvent
class:
namespace App\Events;
use Illuminate\Broadcasting\Channel;
use Illuminate\Queue\SerializesModels;
use Illuminate\Foundation\Events\Dispatchable;
use Illuminate\Broadcasting\InteractsWithSockets;
use Illuminate\Contracts\Broadcasting\ShouldBroadcastNow;
class HealthEvent implements ShouldBroadcastNow
{
use Dispatchable, InteractsWithSockets, SerializesModels;
/**
* Create a new event instance.
*/
public function __construct() {}
/**
* Get the channels the event should broadcast on.
*
* @return array<int, \Illuminate\Broadcasting\Channel>
*/
public function broadcastOn(): array
{
return [
new Channel('uptime'),
];
}
}
After you have set up the listener, you can point your favorite uptime monitoring service at https://your.site/up and be notified whenever a critical part of your application stops behaving properly.
For reliable and easy-to-use monitoring, consider services like PingPing.io, Pingdom, or UptimeRobot. These tools provide real-time alerts and detailed insights into your application’s availability, helping you stay proactive about performance and uptime.
Extending Laravel’s health endpoint is a simple but powerful way to stay on top of your application’s performance. When combined with external uptime monitoring, you can keep your finger on the pulse of your system and respond faster when something goes wrong.
If you’d like help implementing these features or optimizing your Laravel setup, reach out to our team today to get the support you need.