rasuvaeff / yii3-health-check
Health check endpoints for Yii3 applications
Requires
- php: ^8.3
- psr/clock: ^1.0
- psr/http-factory: ^1.0
- psr/http-message: ^2.0
- psr/http-server-handler: ^1.0
Requires (Dev)
- ergebnis/composer-normalize: ^2.51
- friendsofphp/php-cs-fixer: ^3.95
- infection/infection: ^0.29
- maglnet/composer-require-checker: ^4.17
- phpunit/phpunit: ^11.5
- psalm/plugin-phpunit: ^0.19
- rector/rector: ^2.4
- vimeo/psalm: ^6.16
This package is auto-updated.
Last update: 2026-06-02 16:59:59 UTC
README
Health check endpoints for Yii3: /live, /ready, /health. PSR-15 request handlers with composite checks, elapsed time tracking and Kubernetes probe support.
Using an AI coding assistant? llms.txt has a compact API reference ready to paste into context.
Requirements
- PHP 8.3+
psr/clock^1.0psr/http-factory^1.0psr/http-message^2.0psr/http-server-handler^1.0
Installation
composer require rasuvaeff/yii3-health-check
Usage
1. Register routes
// config/routes.php use Rasuvaeff\Yii3HealthCheck\HealthEndpoint; use Rasuvaeff\Yii3HealthCheck\LivenessEndpoint; use Rasuvaeff\Yii3HealthCheck\ReadinessEndpoint; use Yiisoft\Router\Route; return [ Route::get('/live')->action(LivenessEndpoint::class)->name('health.live'), Route::get('/ready')->action(ReadinessEndpoint::class)->name('health.ready'), Route::get('/health')->action(HealthEndpoint::class)->name('health.full'), ];
2. Register your checks in DI
The package ships config/di.php and config/params.php via config-plugin. Extend HealthChecker with your own checks:
// config/di.php use App\Infrastructure\Health\DatabaseHealthCheck; use App\Infrastructure\Health\RedisHealthCheck; use Rasuvaeff\Yii3HealthCheck\HealthChecker; use Yiisoft\Definitions\Reference; return [ HealthChecker::class => [ '__construct()' => [ 'checks' => [ Reference::to(DatabaseHealthCheck::class), Reference::to(RedisHealthCheck::class), ], 'warnThresholdMs' => $params['rasuvaeff/yii3-health-check']['warnThresholdMs'], ], ], ];
3. Implement your checks
// src/Infrastructure/Health/DatabaseHealthCheck.php use Rasuvaeff\Yii3HealthCheck\HealthCheck; use Rasuvaeff\Yii3HealthCheck\HealthResult; use Yiisoft\Db\Connection\ConnectionInterface; final readonly class DatabaseHealthCheck implements HealthCheck { public function __construct(private ConnectionInterface $db) {} public function name(): string { return 'database'; } public function check(): HealthResult { try { $this->db->createCommand('SELECT 1')->queryScalar(); return HealthResult::pass(name: 'database'); } catch (\Throwable $e) { return HealthResult::fail(name: 'database', message: $e->getMessage()); } } }
For inline checks without a dedicated class use CallbackHealthCheck:
use Rasuvaeff\Yii3HealthCheck\CallbackHealthCheck; use Rasuvaeff\Yii3HealthCheck\HealthResult; new CallbackHealthCheck( name: 'disk', check: static function (): HealthResult { $free = disk_free_space('/'); if ($free === false) { return HealthResult::fail(name: 'disk', message: 'Cannot read disk stats'); } if ($free < 100 * 1024 * 1024) { return HealthResult::warn(name: 'disk', message: 'Less than 100MB free', data: ['freeBytes' => $free]); } return HealthResult::pass(name: 'disk'); }, )
Liveness vs Readiness
| Endpoint | Handler | Checks | k8s probe | On failure |
|---|---|---|---|---|
/live |
LivenessEndpoint |
None (always pass) | livenessProbe |
Container restart |
/ready |
ReadinessEndpoint |
All registered checks | readinessProbe |
Removed from load balancer |
/health |
HealthEndpoint |
All registered checks | Monitoring/dashboard | — |
Rule: never put external service checks (DB, Redis) in liveness — a slow DB would restart your container. Put them only in readiness.
API reference
HealthResult
HealthResult::pass(name: 'db') HealthResult::pass(name: 'db', message: 'Connected') HealthResult::warn(name: 'db', message: 'Slow', data: ['latencyMs' => 950]) HealthResult::fail(name: 'db', message: 'Connection refused') $result->name // string $result->status // HealthStatus $result->message // string $result->data // array<string, mixed> $result->elapsedMs // float (set by HealthChecker) $result->withData(['rows' => 42]) // returns new instance $result->withElapsedMs(12.5) // returns new instance $result->toArray() // array, omits elapsedMs:0 and data:[], always includes message
HealthStatus
HealthStatus::Pass // 'pass' → HTTP 200 HealthStatus::Warn // 'warn' → HTTP 200 HealthStatus::Fail // 'fail' → HTTP 503
HealthChecker
$checker = new HealthChecker( checks: [$dbCheck, $redisCheck], clock: $psrClock, // optional PSR-20, default microtime() warnThresholdMs: 500.0, // default 1000.0 ); $checker->add($check); // add a check at runtime $checker->has('database'); // bool $results = $checker->run(); // array<string, HealthResult> $results = $checker->runByName('database'); // array<string, HealthResult> HealthChecker::aggregateStatus($results); // HealthStatus
Aggregation rules:
| Condition | Result |
|---|---|
Any fail |
fail |
Any warn, no fail |
warn |
All pass |
pass |
HealthCheck interface
interface HealthCheck { public function name(): string; // /^[a-z][a-z0-9_.-]*$/ public function check(): HealthResult; }
Exception thrown from check() is caught and converted to HealthResult::fail.
LivenessEndpoint
new LivenessEndpoint( responseFactory: $factory, statusMessage: 'alive', // optional, default 'alive' )
Always returns HTTP 200. Never depends on external services.
{"status":"pass","message":"alive"}
ReadinessEndpoint / HealthEndpoint
new ReadinessEndpoint(checker: $checker, responseFactory: $factory) new HealthEndpoint(checker: $checker, responseFactory: $factory)
Both run all registered checks and return the same JSON format.
{
"status": "warn",
"checks": {
"database": {"name":"database","status":"pass","message":"","elapsedMs":2.1},
"redis": {"name":"redis","status":"warn","message":"Check took 1243.0ms (threshold: 1000.0ms)","elapsedMs":1243.0}
}
}
Warn threshold
warnThresholdMs (default: 1000ms) automatically upgrades pass → warn when a check takes too long. Existing warn and fail statuses are never downgraded:
// warnThresholdMs: 500 // database check took 750ms → upgraded to warn automatically {"name":"database","status":"warn","message":"Check took 750.0ms (threshold: 500.0ms)","elapsedMs":750.0}
Configure via params.php:
'rasuvaeff/yii3-health-check' => [ 'warnThresholdMs' => 500.0, 'livenessMessage' => 'alive', ],
Kubernetes probes
livenessProbe: httpGet: path: /live port: 8080 initialDelaySeconds: 5 periodSeconds: 10 failureThreshold: 3 readinessProbe: httpGet: path: /ready port: 8080 initialDelaySeconds: 5 periodSeconds: 10 failureThreshold: 3
Security
- Check names validated:
/^[a-z][a-z0-9_.-]*$/ - Callbacks are developer-controlled, no user input executed
- Liveness never exposes internal service state
Examples
See examples/ for runnable scripts and a full Yii3 wiring guide.
Development
make install make build make cs:fix make mutation
License
BSD-3-Clause. See LICENSE.md.