laravel-service-health maintained by mrtolouei
Laravel Service Health
A flexible and extensible service health monitoring package for Laravel.
This package helps you monitor the health of your application's critical services such as:
- Database connections
- Cache stores
- Queue connections
- Filesystem disks
- Redis connections
- External/internal HTTP endpoints
It includes:
- A web-based dashboard
- A JSON API endpoint
- An Artisan command for CLI / CI usage
- Built-in authorization layer
- Extensible architecture for adding custom inspectors
Screenshot

Table of Contents
- Features
- Requirements
- Installation
- Publishing Assets
- Quick Start
- Routes
- Configuration
- Usage Examples
- Dashboard
- JSON API
- Artisan Command
- Authorization
- Custom Inspectors for Developers
- Status Model
- CI Ideas
- Testing
- Contributing
- License
Features
- Monitor important Laravel services in one place
- Detect:
- healthy services
- degraded services
- failed services
- Measure response duration in milliseconds
- Configure slow thresholds per monitor
- Expose health results through:
- Dashboard page
- API endpoint
- CLI command
- Protect access using authorization middleware
- Add your own custom service inspectors
- Works with Laravel auto-discovery
Requirements
- PHP
>= 8.2 - Laravel
11,12, or13
Package dependencies include:
illuminate/supportilluminate/httpilluminate/cacheilluminate/queueilluminate/filesystemilluminate/database
Installation
Install the package via Composer:
composer require mrtolouei/laravel-service-health
Laravel will automatically discover and register the package service provider.
Publishing Assets
Publish Config
Publish the package configuration file:
php artisan vendor:publish --tag=service-health-config
This creates:
config/service-health.php
Publish Authorization Provider Stub
If you want to define who can access the dashboard and API, publish the authorization provider stub:
php artisan vendor:publish --tag=service-health-provider
This creates:
app/Providers/HealthServiceServiceProvider.php
You can then register your own gate logic there.
Publish Views
If you want to customize the dashboard UI:
php artisan vendor:publish --tag=service-health-views
Quick Start
1) Install the package
composer require mrtolouei/laravel-service-health
2) Publish assets
php artisan vendor:publish --tag=service-health-config
php artisan vendor:publish --tag=service-health-provider
php artisan vendor:publish --tag=service-health-views
3) Visit the dashboard
- Dashboard:
/service-health - API:
/service-health-api
4) Run checks from CLI
php artisan service-health:check
5) Optionally secure access
Publish the authorization provider and define your gate rules.
Routes
By default, the package registers two routes:
GET /service-health
GET /service-health-api
These are configurable via:
'route' => [
'prefix' => env('SERVICE_HEALTH_ROUTE_PREFIX', ''),
'dashboard' => env('SERVICE_HEALTH_ROUTE_DASHBOARD', 'service-health'),
'api' => env('SERVICE_HEALTH_ROUTE_API', 'service-health-api'),
'middleware' => [
'web',
MrTolouei\ServiceHealth\Http\Middleware\Authorize::class,
],
],
Example
If you set:
SERVICE_HEALTH_ROUTE_PREFIX=admin/tools
SERVICE_HEALTH_ROUTE_DASHBOARD=health
SERVICE_HEALTH_ROUTE_API=health-api
Routes become:
/admin/tools/health/admin/tools/health-api
Configuration
Main config file:
config/service-health.php
Top-Level Config Options
enabled
'enabled' => env('SERVICE_HEALTH_ENABLED', true),
Globally enables or disables the package routes.
If set to false, routes will not be registered.
route
'route' => [
'prefix' => env('SERVICE_HEALTH_ROUTE_PREFIX', ''),
'dashboard' => env('SERVICE_HEALTH_ROUTE_DASHBOARD', 'service-health'),
'api' => env('SERVICE_HEALTH_ROUTE_API', 'service-health-api'),
'middleware' => [
'web',
MrTolouei\ServiceHealth\Http\Middleware\Authorize::class,
],
],
Controls route URLs and middleware.
history_limit
'history_limit' => env('SERVICE_HEALTH_LIMIT_HISTORY', 20),
Used by the dashboard for limiting displayed history items.
refresh_interval
'refresh_interval' => env('SERVICE_HEALTH_REFRESH_INTERVAL', 3000),
Dashboard refresh interval in milliseconds.
Example:
- 3000 = every 3 seconds
- 10000 = every 10 seconds
expose_exception_messages
'expose_exception_messages' => env('SERVICE_HEALTH_EXPOSE_EXCEPTION_MESSAGES', true),
Controls whether raw exception messages should be shown in results.
true: actual exception messages are exposedfalse: generic safe messages are returned
For production environments, you may prefer setting this to false.
Monitor Configuration
Each monitor has a structure similar to this:
'monitor_name' => [
'enabled' => true,
'inspector' => SomeInspector::class,
'slow_threshold' => 20,
'connections' => [
...
],
],
Common fields
enabled
Whether this monitor is active.
inspector
The class responsible for performing the health check.
slow_threshold
If the check completes successfully but takes longer than this threshold (ms), the result becomes degraded instead of healthy.
connections
The list of things to inspect.
For some inspectors, each item is a string connection name.
For HttpInspector, each item is a full config array.
Usage Examples
Monitoring Multiple Database Connections
'database' => [
'enabled' => true,
'inspector' => MrTolouei\ServiceHealth\Inspectors\DatabaseInspector::class,
'slow_threshold' => 50,
'connections' => [
'mysql',
'analytics',
'tenant',
],
],
This will create separate health results for each configured database connection.
Monitoring External APIs
'http' => [
'enabled' => true,
'inspector' => MrTolouei\ServiceHealth\Inspectors\HttpInspector::class,
'connections' => [
[
'name' => 'GitHub API',
'endpoint' => 'https://api.github.com',
'method' => 'GET',
'expected_status' => 200,
'headers' => [
'Accept' => 'application/json',
'User-Agent' => 'LaravelServiceHealth',
],
'timeout' => 5,
'slow_threshold' => 2000,
],
[
'name' => 'Payment Gateway Health',
'endpoint' => 'https://payments.example.com/health',
'method' => 'GET',
'expected_status' => 200,
'auth' => [
'type' => 'bearer',
'token' => env('PAYMENT_GATEWAY_TOKEN'),
],
'timeout' => 5,
'slow_threshold' => 1000,
],
],
],
Monitoring Internal Services with Auth
'http' => [
'enabled' => true,
'inspector' => MrTolouei\ServiceHealth\Inspectors\HttpInspector::class,
'connections' => [
[
'name' => 'Internal Admin API',
'endpoint' => 'https://internal.example.com/api/health',
'method' => 'GET',
'expected_status' => 200,
'headers' => [
'Accept' => 'application/json',
],
'auth' => [
'type' => 'basic',
'username' => env('INTERNAL_API_USER'),
'password' => env('INTERNAL_API_PASSWORD'),
],
'timeout' => 3,
'slow_threshold' => 800,
],
],
],
Dashboard
The dashboard route renders a Blade view:
return view('service-health::dashboard');
By default, it is available at:
/service-health
This dashboard is intended to give a quick visual overview of:
- service statuses
- degraded/failed services
- timings
- refresh-based updates
You may publish and customize the view if needed.
JSON API
The API endpoint returns a structured JSON response including:
- checked_at
- summary
- services
Default route:
/service-health-api
Summary keys
- total
- healthy
- degraded
- failed
- average_duration
- slowest_service
- slowest_duration
- overall_status
Service item keys
- name
- status
- is_healthy
- is_degraded
- is_failed
- is_up
- message
- duration
- metadata
- type
- connection
Artisan Command
Run checks via CLI:
php artisan service-health:check
JSON output
php artisan service-health:check --json
Behavior
- Prints a table of all services
- Returns failure exit code if any service has failed
- Returns success if all services are either healthy or degraded
This makes it useful for:
- deployment pipelines
- cron jobs
- uptime scripts
- container health checks
- infrastructure monitoring
Authorization
The package uses this middleware by default:
MrTolouei\ServiceHealth\Http\Middleware\Authorize::class
That middleware delegates authorization to:
ServiceHealth::check($request)
By default, if no custom auth callback is defined, access is only allowed in the local environment.
To customize this, publish the provider stub:
php artisan vendor:publish --tag=service-health-provider
Then define your gate in the generated provider.
Example:
<?php
namespace App\Providers;
use Illuminate\Support\Facades\Gate;
use MrTolouei\ServiceHealth\HealthServiceApplicationServiceProvider;
class HealthServiceServiceProvider extends HealthServiceApplicationServiceProvider
{
protected function gate(): void
{
Gate::define('viewHealthService', function ($user = null) {
return $user && $user->is_admin;
});
}
}
You can also make access conditional by email, role, permission, environment, IP, or any custom logic.
Custom Inspectors for Developers
One of the main strengths of this package is that you can create your own inspectors.
Inspector Contract
Every custom inspector must implement:
MrTolouei\ServiceHealth\Inspectors\InspectorInterface
Which requires:
public function monitor(): InspectorResult;
Creating a Custom Inspector
Example: checking a third-party SDK, external service state, or internal app condition.
<?php
namespace App\Health;
use MrTolouei\ServiceHealth\DTOs\InspectorResult;
use MrTolouei\ServiceHealth\Inspectors\InspectorInterface;
use Throwable;
class MailProviderInspector implements InspectorInterface
{
public function __construct(protected string $connection)
{
}
public function monitor(): InspectorResult
{
$startedAt = microtime(true);
try {
// Example custom logic
$healthy = true;
$duration = round((microtime(true) - $startedAt) * 1000, 2);
return new InspectorResult(
name: "mail-provider:{$this->connection}",
status: $healthy
? InspectorResult::STATUS_HEALTHY
: InspectorResult::STATUS_FAILED,
message: $healthy
? 'Mail provider is healthy.'
: 'Mail provider is unavailable.',
duration: $duration,
metadata: [
'provider' => $this->connection,
],
type: 'mail',
connection: $this->connection,
);
} catch (Throwable $e) {
$duration = round((microtime(true) - $startedAt) * 1000, 2);
return new InspectorResult(
name: "mail-provider:{$this->connection}",
status: InspectorResult::STATUS_FAILED,
message: config('service-health.expose_exception_messages', true)
? $e->getMessage()
: 'Mail provider health check failed.',
duration: $duration,
metadata: [],
type: 'mail',
connection: $this->connection,
);
}
}
}
Registering a Custom Inspector
Add it to your config:
'mail_provider' => [
'enabled' => true,
'inspector' => App\Health\MailProviderInspector::class,
'connections' => [
'postmark',
'ses',
],
],
The package manager will automatically instantiate the inspector for each connection and include its results in:
- dashboard
- API
- Artisan command
Returning Rich Metadata
You can include extra details in metadata:
metadata: [
'region' => 'eu-central-1',
'quota_remaining' => 1240,
'response_code' => 200,
],
This is useful if you want the API consumers to understand more about the service state.
Status Model
The package supports three statuses:
healthy
The service is available and responding within the acceptable threshold.
degraded
The service is working, but slower than expected.
failed
The service is unavailable, returned unexpected results, or threw an exception.
CI Ideas
You can use this package in CI/CD pipelines like this:
php artisan service-health:check --json
Possible use cases:
- fail deployment if a critical dependency is down
- verify environment readiness after deployment
- expose health checks to orchestration systems
- monitor external API dependencies
You can also wrap the command inside cron or supervisor-based scripts.
Testing
Run tests using PHPUnit:
vendor/bin/phpunit
Contributing
- Fork the repository
- Create a feature branch (
feature/awesome-feature) - Commit your changes (
git commit -m 'Add new feature') - Push to the branch (
git push origin feature/awesome-feature) - Open a Pull Request
License
This package is open-sourced software licensed under the MIT license.