The Health facade
RoundlyConsulting\Alerts\Facades\Health is the recommended entry point, and its Health alias is auto-discovered. Its surface has four parts: the check registry, a handle scoped to one owner, the maintenance-window sub-accessor and the verbs that span every owner:
use RoundlyConsulting\Alerts\Checks\DatabaseCheck;
use RoundlyConsulting\Alerts\Facades\Health;
// The check registry
Health::check(DatabaseCheck::make('mysql'));
Health::checks([DiskUsageCheck::class, MemoryUsageCheck::class]);
Health::define('orders-flowing', fn () => Order::where('created_at', '>=', now()->subHour())->exists());
Health::all(); // Collection<string, Check>
Health::find('disk_usage_check'); // ?Check
// Everything scoped to one owner
Health::for($team)->monitor(DatabaseCheck::class)->everyFiveMinutes()->save();
Health::for($team)->schedule($data); // from a ScheduleHealthCheckData
Health::for($team)->run(DatabaseCheck::class);
Health::for($team)->run('orders-flowing'); // by key, e.g. an inline check
Health::for($team)->report(['critical']);
Health::for($team)->status();
Health::for($team)->monitors();
Health::for($team)->unmonitor(DatabaseCheck::class);
// Maintenance windows
Health::silences()->mute('db', until: now()->addHour(), for: $team, reason: 'upgrade');
Health::silences()->unmute('db', for: $team);
Health::silences()->isMuted('db');
Health::silences()->active($team);
// Across every owner
Health::report();
Health::status();
Health::runDue(); // what alerts:perform-health-checks calls
Health::prune(14); // what alerts:prune-runs calls
Health::routes(); // the opt-in JSON endpointFlat methods
| Method | Returns | What it does |
|---|---|---|
check(string|object $check) | HealthManager | Register one check class or instance. Anything that does not extend Check throws InvalidHealthCheck. |
checks(array $checks) | HealthManager | Register several checks at once. |
define(string $key, Closure $callback) | PendingCheck | Define an inline closure check (see Inline closure checks). |
all() | Collection<string, Check> | Every registered check, keyed by its key. |
find(string $key) | ?Check | One registered check, or null. |
for(Model $owner) | NotifiableHealth | The handle scoped to one owner (next table). |
report(?array $tags = null) | HealthReport | Report across every scheduled check, optionally filtered by tags. |
status(?array $tags = null) | Status | The overall() roll-up of that report. |
silences() | Silences | The maintenance-window sub-accessor (table below). |
runDue() | int | Queue the configured job for every scheduled check whose cron is due; returns how many were queued. |
prune(?int $days = null) | int | Delete run history older than $days (default history.retention_days); returns how many runs were deleted. |
routes(?string $uri = null) | Route | Register the opt-in JSON status endpoint. |
Health::for($owner)
Every health operation scoped to one owner model. The handle is a security boundary: a scheduled row that belongs to another owner is refused with InvalidHealthCheck.
| Method | Returns | What it does |
|---|---|---|
run(string|Check|HealthCheck $check) | CheckResult | Run now with the full alert, notify and history side effects. A registered key, class or instance runs through the owner’s scheduled row, else an on-demand row that is never scheduled; a row must belong to the owner, else InvalidHealthCheck. |
report(?array $tags = null) | HealthReport | This owner’s report, optionally filtered by tags. |
status(?array $tags = null) | Status | This owner’s roll-up. |
monitor(string $check) | PendingScheduledCheck | Fluent schedule for a Check class or registered key (an inline check’s key starts from its define() options); save() validates the cron and returns the HealthCheck row. |
schedule(ScheduleHealthCheckData $data) | HealthCheck | Schedule from a DTO. |
unmonitor(string|Check|HealthCheck $check) | int | Soft-delete this owner’s schedules for a check, or one own row; another owner’s row throws InvalidHealthCheck. |
monitors() | Collection<int, HealthCheck> | This owner’s schedules, oldest first — on-demand rows are not listed. |
The UsesHealthChecks trait’s monitorCheck(), monitor() and createHealthCheck() are shortcuts over Health::for($this), so they behave exactly like the facade calls — and Health::fake() records them too (see Owner models).
Health::silences()
Maintenance windows. A key is a check key, a tag or * for everything; for: scopes a silence to one owner (see Maintenance windows & muting):
| Method | Returns | What it does |
|---|---|---|
mute(string $key, ?CarbonInterface $until = null, ?Model $for = null, ?string $reason = null) | AlertSilence | Mute a check key, a tag or *, optionally until a moment and/or for one owner. |
unmute(string $key, ?Model $for = null) | int | Lift the global silences on the key, or only those scoped to $for; returns how many were lifted. |
isMuted(string $key, ?Model $for = null) | bool | Whether a silence on exactly this key is in force now. Always false when silence is off in the config. |
active(?Model $for = null) | Collection<int, AlertSilence> | Silences in force now: all of them, or the global ones plus those scoped to $for. |
Builders
- Health::for($owner)->monitor($check) returns a PendingScheduledCheck — frequency presets, throttle, thresholds, tags, routing, escalation and meta, then save() (see Scheduling checks). For an inline check’s key it starts from the options declared on define().
- Health::define($key, $closure) returns a PendingCheck for an inline check’s name, notification and options (see Inline closure checks).
In tests, Health::fake() swaps the whole surface for a recording fake (see Testing). If you prefer an explicit dependency or single-purpose classes, see DI and actions.
Show your open-source love
This package is free and MIT-licensed. If it saves you time, a one-off donation or a Patreon membership keeps it maintained, tested and documented.
More ways to support, including cryptoBy donating, you agree to our donation terms.
Want this built into your product?
We integrate our packages into custom Laravel and AI builds. Tell us what you're working on and we'll reply within 48 hours.