Framework-agnostic PHP core for Crontinel. Provides monitor contracts, typed data objects, alert management with deduplication, and cron expression helpers.
If you use Laravel, install crontinel/laravel instead. It pulls in this package automatically and adds service providers, dashboard, Artisan commands, and event listeners.
Install crontinel/php directly when you are:
- Building an adapter for Symfony, Slim, or another framework
- Integrating Crontinel into a vanilla PHP application
- Writing a custom monitor that does not depend on Laravel
- PHP 8.2, 8.3, or 8.4
composer require crontinel/phpMonitorInterface-- implementisHealthy(): boolto create a custom monitorAlertChannelInterface-- implementsend(AlertEvent $event): voidto deliver alerts via any transport (Slack, email, webhook, etc.)
Immutable, readonly value objects used across the stack:
AlertEvent-- key, title, message, level (critical/warning/info/resolved), fired timestampCronStatus-- command, expression, status, last run metadata, next due timeHorizonStatus-- Horizon supervisor stateQueueStatus-- queue depth, failed count, oldest job age
AlertManager handles fire/resolve lifecycle with built-in deduplication. It accepts any PSR-16 cache and any AlertChannelInterface implementation:
- Deduplicates repeated alerts for the same key (default: 5 min TTL)
- Auto-sends "resolved" notifications when an issue clears
- Logs failures via PSR-3 logger (falls back to
NullLogger)
CronExpressionHelper wraps dragonmantank/cron-expression with convenience methods:
nextDue(string $expression)-- next scheduled run asDateTimeImmutablepreviousDue(string $expression)-- last scheduled runisLate(DateTimeInterface $lastRunAt, string $expression, int $graceSeconds = 120)-- whether a job has missed its window
Ready-to-use monitor implementations (all implement MonitorInterface):
CronMonitor,HorizonMonitor,QueueMonitor
Implement MonitorInterface to build a custom health check:
use Crontinel\Contracts\MonitorInterface;
final class DiskSpaceMonitor implements MonitorInterface
{
public function __construct(
private readonly string $path = '/',
private readonly float $minFreePercent = 10.0,
) {}
public function isHealthy(): bool
{
$free = disk_free_space($this->path);
$total = disk_total_space($this->path);
return ($free / $total) * 100 >= $this->minFreePercent;
}
}Wire up alert delivery by implementing AlertChannelInterface:
use Crontinel\Contracts\AlertChannelInterface;
use Crontinel\Data\AlertEvent;
final class WebhookChannel implements AlertChannelInterface
{
public function __construct(
private readonly string $url,
) {}
public function send(AlertEvent $event): void
{
file_get_contents($this->url, false, stream_context_create([
'http' => [
'method' => 'POST',
'header' => 'Content-Type: application/json',
'content' => json_encode([
'key' => $event->key,
'title' => $event->title,
'message' => $event->message,
'level' => $event->level,
'resolved' => $event->resolved,
]),
],
]));
}
}Then use AlertManager to fire and resolve alerts:
use Crontinel\Alert\AlertManager;
// Requires any PSR-16 cache implementation
$alertManager = new AlertManager(
cache: $cache,
channel: new WebhookChannel('https://example.com/webhook'),
);
$monitor = new DiskSpaceMonitor('/data');
if (! $monitor->isHealthy()) {
$alertManager->fire('disk.data', 'Low disk space', 'Disk /data is below 10% free', 'critical');
} else {
$alertManager->resolve('disk.data');
}| Package | Description |
|---|---|
| crontinel/php (this repo) | Framework-agnostic PHP core |
| crontinel/laravel | Laravel package with dashboard, Artisan commands, and event listeners |
| crontinel/mcp-server | MCP server for AI assistants (Claude, Cursor) |
| docs.crontinel.com | Full documentation |
| app.crontinel.com | Hosted SaaS dashboard |
MIT. See LICENSE.
Built by Harun R Rayhan · crontinel.com