laminas/laminas-diagnostics
Run health checks for your PHP/Laminas apps and environments. laminas-diagnostics provides diagnostic tests and reporting for common issues, with an extensible API for custom checks and CI-friendly output.
Installation:
composer require laminas/laminas-diagnostics
Add the Laminas\Diagnostics\DiagnosticListener to your Laravel service container (e.g., in AppServiceProvider):
$this->app->bind('diagnosticListener', function ($app) {
return new \Laminas\Diagnostics\DiagnosticListener();
});
First Use Case:
EnvironmentDiagnostic to verify PHP settings:
use Laminas\Diagnostics\DiagnosticListener;
use Laminas\Diagnostics\Diagnostic\EnvironmentDiagnostic;
$listener = $this->app->make('diagnosticListener');
$diagnostic = new EnvironmentDiagnostic();
$listener->addDiagnostic($diagnostic);
$result = $listener->run();
dd($result); // Inspect PHP environment (memory, extensions, etc.)
Where to Look First:
src/Diagnostic/ for built-in diagnostics (e.g., EnvironmentDiagnostic, MemoryDiagnostic).src/Listener/ for event-driven diagnostics (e.g., DiagnosticListener).Pre-Request Diagnostics: Use middleware to run diagnostics before critical operations (e.g., API requests):
namespace App\Http\Middleware;
use Closure;
use Laminas\Diagnostics\DiagnosticListener;
class DiagnosticsMiddleware
{
public function handle($request, Closure $next)
{
$listener = app('diagnosticListener');
$listener->addDiagnostic(new \Laminas\Diagnostics\Diagnostic\MemoryDiagnostic());
$result = $listener->run();
// Log or store results (e.g., in a database or cache)
cache()->put('diagnostics', $result, now()->addHours(1));
return $next($request);
}
}
Custom Diagnostics:
Extend AbstractDiagnostic to create domain-specific checks:
namespace App\Diagnostics;
use Laminas\Diagnostics\Diagnostic\AbstractDiagnostic;
class DatabaseConnectionDiagnostic extends AbstractDiagnostic
{
public function diagnose()
{
try {
\DB::connection()->getPdo();
return $this->createOk('Database connection is healthy.');
} catch (\Exception $e) {
return $this->createFail('Database connection failed: ' . $e->getMessage());
}
}
}
Register it in a service provider:
$this->app->bind('databaseDiagnostic', function ($app) {
return new DatabaseConnectionDiagnostic();
});
Event-Driven Diagnostics:
Attach diagnostics to Laravel events (e.g., Illuminate\Queue\Events\JobProcessed):
use Laminas\Diagnostics\DiagnosticListener;
use Illuminate\Queue\Events\JobProcessed;
Event::listen(JobProcessed::class, function ($event) {
$listener = app('diagnosticListener');
$listener->addDiagnostic(new \App\Diagnostics\QueueDiagnostic());
$result = $listener->run();
// Handle results (e.g., alert on failures)
});
Laravel Logging: Integrate results with Laravel’s logging system:
$result = $listener->run();
foreach ($result as $diagnostic) {
if ($diagnostic->isOk()) {
\Log::info($diagnostic->getMessage());
} else {
\Log::error($diagnostic->getMessage());
}
}
Scheduling: Run diagnostics via Laravel’s scheduler (e.g., nightly checks):
// app/Console/Kernel.php
protected function schedule(Schedule $schedule)
{
$schedule->command('diagnostics:run')->daily();
}
Create a custom Artisan command:
php artisan make:command DiagnosticsRun
API Endpoints: Expose diagnostics via an API route:
Route::get('/diagnostics', function () {
$listener = app('diagnosticListener');
$listener->addDiagnostic(new \Laminas\Diagnostics\Diagnostic\EnvironmentDiagnostic());
$result = $listener->run();
return response()->json($result);
});
Performance Overhead:
Diagnostic Order:
DiagnosticListener::setDiagnostics() to enforce order.False Positives/Negatives:
Laravel-Specific Quirks:
Verbose Output: Enable debug mode for detailed diagnostic output:
$diagnostic = new EnvironmentDiagnostic();
$diagnostic->setDebug(true);
Logging Levels: Use Laravel’s log levels to filter diagnostic output:
if (!$diagnostic->isOk()) {
\Log::warning('Diagnostic failed: ' . $diagnostic->getMessage());
}
Testing: Mock diagnostics in unit tests:
$mockDiagnostic = $this->createMock(\Laminas\Diagnostics\Diagnostic\DiagnosticInterface::class);
$mockDiagnostic->method('diagnose')->willReturn($this->createOk('Test passed'));
$listener->addDiagnostic($mockDiagnostic);
Combine Diagnostics:
Use CompositeDiagnostic to group related checks:
use Laminas\Diagnostics\Diagnostic\CompositeDiagnostic;
$composite = new CompositeDiagnostic();
$composite->addDiagnostic(new EnvironmentDiagnostic());
$composite->addDiagnostic(new MemoryDiagnostic());
$listener->addDiagnostic($composite);
Configuration:
Store diagnostic thresholds in config/diagnostics.php:
return [
'memory' => [
'warning' => 512, // MB
'critical' => 1024,
],
];
Load config in diagnostics:
$memoryLimit = config('diagnostics.memory.warning');
Notifications: Integrate with Laravel Notifications for alerts:
if (!$diagnostic->isOk()) {
Notification::route('mail', 'admin@example.com')
->notify(new DiagnosticFailed($diagnostic));
}
Extension Points:
DiagnosticListener to add custom logic (e.g., filtering, formatting).AbstractDiagnostic for reusable diagnostic logic (e.g., shared setup/teardown).Documentation:
Document custom diagnostics in a README or Swagger/OpenAPI specs for API endpoints.
How can I help you explore Laravel packages today?