marin-solutions / checkybot-laravel
Laravel package for CheckyBot monitoring integration
Package info
github.com/Marin-Solutions/checkybot-laravel
pkg:composer/marin-solutions/checkybot-laravel
Fund package maintenance!
Requires
- php: ^8.2
- guzzlehttp/guzzle: ^7.8
- illuminate/contracts: ^12.30|^13.0
- spatie/laravel-package-tools: ^1.16
Requires (Dev)
- larastan/larastan: ^3.0
- laravel/pint: ^1.14
- nunomaduro/collision: ^8.8
- orchestra/testbench: ^10.7|^11.0
- pestphp/pest: ^4.1
- pestphp/pest-plugin-arch: ^4.0
- pestphp/pest-plugin-laravel: ^4.0
- phpstan/extension-installer: ^1.4
- phpstan/phpstan-deprecation-rules: ^2.0
- phpstan/phpstan-phpunit: ^2.0
This package is not auto-updated.
Last update: 2026-08-01 23:40:38 UTC
README
A Laravel package for defining and syncing monitoring checks to your Checkybot instance. Define uptime, SSL certificate, and API endpoint monitors using a beautiful fluent API inspired by Pest, and sync them with a single command.
Quick Start
Get up and running in under 2 minutes:
# 1. Install the package composer require marin-solutions/checkybot-laravel # 2. Publish the routes file php artisan vendor:publish --tag="checkybot-routes" # 3. Publish the config (for API credentials) php artisan vendor:publish --tag="checkybot-laravel-config" # 4. Add credentials to .env echo "CHECKYBOT_API_KEY=your-api-key" >> .env echo "CHECKYBOT_PROJECT_ID=1" >> .env # 5. Define your checks in routes/checkybot.php (see examples below) # 6. Preview your checks php artisan checkybot:sync --dry-run # 7. Sync to Checkybot php artisan checkybot:sync
Installation
Step 1: Install via Composer
composer require marin-solutions/checkybot-laravel
Step 2: Publish Routes File
php artisan vendor:publish --tag="checkybot-routes"
This creates routes/checkybot.php where you'll define your monitoring checks using the fluent API.
Step 3: Publish Configuration
php artisan vendor:publish --tag="checkybot-laravel-config"
Step 4: Set Environment Variables
Add to your .env file:
CHECKYBOT_API_KEY=your-api-key CHECKYBOT_PROJECT_ID=1 CHECKYBOT_URL=https://checkybot.com
| Variable | Description |
|---|---|
CHECKYBOT_API_KEY |
Your Checkybot API key (found in account settings) |
CHECKYBOT_PROJECT_ID |
The project ID to sync checks to |
CHECKYBOT_URL |
Checkybot instance URL (default: https://checkybot.com) |
Step 5: Verify Installation
php artisan checkybot:sync --dry-run
Runtime Component Status Reporting (v0.2.1)
Install the supported client with:
composer require marin-solutions/checkybot-laravel:^0.2.1
After a component has been declared and synced, report its runtime status through the configured CheckybotClient:
use DateTimeImmutable; use DateTimeZone; use MarinSolutions\CheckybotLaravel\Http\CheckybotClient; /** @var CheckybotClient $checkybot */ $checkybot = app(CheckybotClient::class); $checkybot->reportComponentStatus( componentKey: 'serp-data-lake', status: 'warning', // healthy, warning, or failure observedAt: new DateTimeImmutable('now', new DateTimeZone('UTC')), message: 'Refresh backlog is above the warning threshold.', metrics: [ 'due' => 12, 'coverage_percent' => 98.5, ], );
This method calls POST /api/v1/projects/{projectId}/components/{componentKey}/status with the configured base URL, project ID, timeout, Bearer API key, and retry settings. The Checkybot application must support this endpoint before consumers upgrade.
Each call sends an Idempotency-Key header. The package generates a stable key for the call and reuses it across configured retries; pass an optional 64-character hexadecimal key as the sixth argument when a caller must safely retry the same operation after an unknown network outcome.
The authenticated JSON body contains only:
{
"status": "healthy|warning|failure",
"observed_at": "2026-07-31T12:34:56+00:00",
"message": "A short safe status message.",
"metrics": {"due": 12}
}
observed_at is normalized to RFC3339 UTC. Component keys must be 1–64 characters matching [A-Za-z0-9][A-Za-z0-9._-]*. Messages are limited to 500 bytes and cannot contain control characters. Metrics are limited to 20 values, must use the allowlisted keys active, configured_pairs, count, coverage_percent, due, duration_ms, error_count, failed, failure_count, failure_streak, healthy, latency_ms, missing_pairs, oldest_overdue_age_minutes, overdue, stale_claims, success_count, total, unique_keywords, or warning, and each value must be a non-negative integer, finite number, or boolean no greater than 1,000,000,000.
The server maps failure to Checkybot's danger state and persists the observation against the already-declared component. Declaration sync remains separate and continues to reject runtime status, message, timestamp, and metric fields.
The server allows observed timestamps up to 120 seconds ahead of its clock to tolerate normal clock skew; larger future timestamps are rejected. Deploy the compatible Checkybot application endpoint and migration first (server hardening commit 1e43daf3334cef0e49dd409b317a650bb74d9984), then change the consumer requirement to ^0.2.1. Do not add status fields to php artisan checkybot:sync; call reportComponentStatus separately from application runtime code.
Defining Checks (Fluent API)
Define your checks in routes/checkybot.php using the expressive fluent API:
<?php use MarinSolutions\CheckybotLaravel\Facades\Checkybot; // Uptime Checks Checkybot::uptime('homepage') ->url(config('app.url')) ->everyFiveMinutes(); Checkybot::uptime('api-server') ->url(config('app.url') . '/api') ->everyMinute() ->maxRedirects(5); // SSL Certificate Checks Checkybot::ssl('main-certificate') ->url(config('app.url')) ->daily(); // API Checks with Assertions (Pest-style!) Checkybot::api('health-check') ->url(config('app.url') . '/api/health') ->everyFiveMinutes() ->withToken(config('services.monitoring.token')) ->expect('status')->toEqual('healthy') ->expect('database.connected')->toBeTrue() ->expect('queue.size')->toBeLessThan(1000);
Uptime Checks
Monitor website availability and response times:
use MarinSolutions\CheckybotLaravel\Facades\Checkybot; // Simple uptime check Checkybot::uptime('homepage') ->url('https://example.com') ->everyFiveMinutes(); // With max redirects Checkybot::uptime('blog') ->url('https://blog.example.com') ->every('10m') ->maxRedirects(5); // Using interval helpers Checkybot::uptime('critical-api') ->url('https://api.example.com') ->everyMinute(); Checkybot::uptime('dashboard') ->url('https://app.example.com/dashboard') ->everyFifteenMinutes();
Interval Helpers
All Laravel scheduler interval helpers are available:
Seconds
| Method | Interval |
|---|---|
->everySecond() |
1 second |
->everyTwoSeconds() |
2 seconds |
->everyFiveSeconds() |
5 seconds |
->everyTenSeconds() |
10 seconds |
->everyFifteenSeconds() |
15 seconds |
->everyTwentySeconds() |
20 seconds |
->everyThirtySeconds() |
30 seconds |
Minutes
| Method | Interval |
|---|---|
->everyMinute() |
1 minute |
->everyTwoMinutes() |
2 minutes |
->everyThreeMinutes() |
3 minutes |
->everyFourMinutes() |
4 minutes |
->everyFiveMinutes() |
5 minutes |
->everyTenMinutes() |
10 minutes |
->everyFifteenMinutes() |
15 minutes |
->everyThirtyMinutes() |
30 minutes |
Hours
| Method | Interval |
|---|---|
->hourly() |
1 hour |
->everyTwoHours() |
2 hours |
->everyThreeHours() |
3 hours |
->everyFourHours() |
4 hours |
->everySixHours() |
6 hours |
->twiceDaily() |
12 hours |
Days
| Method | Interval |
|---|---|
->daily() |
1 day |
->weekly() |
7 days |
Custom
| Method | Interval |
|---|---|
->every('5m') |
Custom interval |
SSL Certificate Checks
Monitor SSL certificate expiration dates:
use MarinSolutions\CheckybotLaravel\Facades\Checkybot; Checkybot::ssl('main-ssl') ->url('https://example.com') ->daily(); Checkybot::ssl('api-ssl') ->url('https://api.example.com') ->daily(); Checkybot::ssl('cdn-ssl') ->url('https://cdn.example.com') ->every('12h');
API Endpoint Checks
Monitor API endpoints with optional response validation using Pest-style assertions:
use MarinSolutions\CheckybotLaravel\Facades\Checkybot; // Simple API check Checkybot::api('health') ->url('https://example.com/api/health') ->everyFiveMinutes(); // With authentication Checkybot::api('authenticated-endpoint') ->url('https://example.com/api/status') ->everyFiveMinutes() ->withToken(config('services.monitoring.token')); // With custom headers Checkybot::api('custom-headers') ->url('https://example.com/api/data') ->everyFiveMinutes() ->headers([ 'Accept' => 'application/json', 'X-Custom-Header' => 'value', ]); // Or add headers one at a time Checkybot::api('endpoint') ->url('https://example.com/api') ->withHeader('Authorization', 'Bearer token') ->withHeader('Accept', 'application/json') ->everyFiveMinutes(); // Expected non-2xx contract without repeated requests Checkybot::api('deprecated-contract') ->url('https://example.com/api/deprecated') ->expectStatus(503) ->retries(0) ->everyFiveMinutes();
Response Assertions (Pest-style)
Chain assertions to validate JSON responses:
Checkybot::api('health-check') ->url('https://example.com/api/health') ->everyFiveMinutes() ->expect('status')->toExist() ->expect('status')->toEqual('healthy') ->expect('database.connected')->toBeTrue() ->expect('cache.connected')->toBeTrue() ->expect('queue.size')->toBeLessThan(1000) ->expect('workers')->toBeGreaterThanOrEqual(1);
Available Assertions
Existence
->expect('path')->toExist() ->expect('path')->exists() // alias
Equality
->expect('status')->toEqual('healthy') ->expect('status')->toBe('healthy') // alias ->expect('status')->equals('healthy') // alias ->expect('status')->notToEqual('error') ->expect('status')->notToBe('error') // alias
Comparisons
->expect('count')->toBeGreaterThan(10) ->expect('count')->toBeGreaterThanOrEqual(10) ->expect('size')->toBeLessThan(1000) ->expect('size')->toBeLessThanOrEqual(1000)
Boolean
->expect('active')->toBeTrue() ->expect('maintenance')->toBeFalse()
Type Checking
->expect('id')->toBeType('integer') ->expect('id')->toBeInteger() // alias ->expect('id')->toBeInt() // alias ->expect('name')->toBeString() ->expect('active')->toBeBoolean() ->expect('active')->toBeBool() // alias ->expect('items')->toBeArray() ->expect('data')->toBeObject()
Regex Matching
->expect('version')->toMatch('/^v\d+\.\d+\.\d+$/') ->expect('email')->toMatchRegex('/^[a-z]+@example\.com$/') // alias
Real-World Examples
E-commerce Application
use MarinSolutions\CheckybotLaravel\Facades\Checkybot; // Critical pages - check every minute Checkybot::uptime('storefront') ->url(config('app.url')) ->everyMinute(); Checkybot::uptime('checkout') ->url(config('app.url') . '/checkout') ->everyMinute(); Checkybot::uptime('cart') ->url(config('app.url') . '/cart') ->everyFiveMinutes(); // SSL Checkybot::ssl('store-ssl') ->url(config('app.url')) ->daily(); // Payment gateway health Checkybot::api('payment-gateway') ->url(config('app.url') . '/api/health/payments') ->everyFiveMinutes() ->expect('stripe_connected')->toBeTrue() ->expect('paypal_connected')->toBeTrue(); // Inventory service Checkybot::api('inventory') ->url(config('app.url') . '/api/health/inventory') ->everyFiveMinutes() ->expect('status')->toEqual('operational');
SaaS Application
use MarinSolutions\CheckybotLaravel\Facades\Checkybot; // Core services Checkybot::uptime('app')->url(config('app.url'))->everyMinute(); Checkybot::uptime('api')->url(config('app.url') . '/api')->everyMinute(); Checkybot::uptime('dashboard')->url(config('app.url') . '/dashboard')->everyFiveMinutes(); // SSL certificates Checkybot::ssl('app-ssl')->url(config('app.url'))->daily(); Checkybot::ssl('api-ssl')->url(config('api.url', config('app.url')))->daily(); // Database health Checkybot::api('database') ->url(config('app.url') . '/api/health/database') ->everyFiveMinutes() ->expect('status')->toEqual('connected') ->expect('latency_ms')->toBeLessThan(100); // Redis health Checkybot::api('redis') ->url(config('app.url') . '/api/health/redis') ->everyFiveMinutes() ->expect('status')->toEqual('connected'); // Queue health Checkybot::api('queue') ->url(config('app.url') . '/api/health/queue') ->everyTenMinutes() ->expect('workers')->toBeGreaterThanOrEqual(1) ->expect('failed_jobs')->toBeLessThan(10) ->expect('queue_size')->toBeLessThan(1000);
Multi-tenant Application
use MarinSolutions\CheckybotLaravel\Facades\Checkybot; Checkybot::uptime('main-app') ->url(config('app.url')) ->everyMinute(); Checkybot::uptime('tenant-portal') ->url(config('tenant.url', config('app.url') . '/tenant')) ->everyFiveMinutes(); Checkybot::uptime('admin-panel') ->url(config('admin.url', config('app.url') . '/admin')) ->everyFiveMinutes(); Checkybot::ssl('wildcard-ssl') ->url(config('app.url')) ->daily(); Checkybot::api('tenant-resolution') ->url(config('app.url') . '/api/health/tenants') ->everyFiveMinutes() ->expect('resolver_status')->toEqual('operational') ->expect('active_tenants')->toBeGreaterThan(0);
CI/CD Integration
GitHub Actions
name: Deploy on: push: branches: [main] jobs: deploy: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - name: Deploy Application run: # your deployment steps - name: Sync Checkybot Monitors run: php artisan checkybot:sync env: CHECKYBOT_API_KEY: ${{ secrets.CHECKYBOT_API_KEY }} CHECKYBOT_PROJECT_ID: ${{ secrets.CHECKYBOT_PROJECT_ID }}
GitLab CI
deploy: stage: deploy script: - # your deployment steps - php artisan checkybot:sync variables: CHECKYBOT_API_KEY: $CHECKYBOT_API_KEY CHECKYBOT_PROJECT_ID: $CHECKYBOT_PROJECT_ID
Laravel Forge (Post-Deployment Script)
cd /home/forge/example.com
php artisan checkybot:sync
Laravel Envoyer (Deployment Hook)
Add as an "After" hook on the "Activate New Release" step:
cd {{ release }}
php artisan checkybot:sync
Commands
# Sync all checks to Checkybot php artisan checkybot:sync # Preview changes without syncing php artisan checkybot:sync --dry-run
Troubleshooting
"CHECKYBOT_API_KEY is not configured"
Make sure your .env file has the API key set:
CHECKYBOT_API_KEY=your-api-key-here
Then clear the config cache:
php artisan config:clear
"Duplicate check names found"
Each check name must be unique within its type:
// Wrong - duplicate names Checkybot::uptime('homepage')->url('https://example.com')->everyFiveMinutes(); Checkybot::uptime('homepage')->url('https://example.com/blog')->everyFiveMinutes(); // Correct - unique names Checkybot::uptime('homepage')->url('https://example.com')->everyFiveMinutes(); Checkybot::uptime('blog')->url('https://example.com/blog')->everyFiveMinutes();
"Connection timed out"
Check your CHECKYBOT_URL is correct and accessible. You can also increase the timeout in config/checkybot-laravel.php:
'timeout' => 60, // seconds
Testing
composer test
Changelog
Please see CHANGELOG for more information on what has changed recently.
License
The MIT License (MIT). Please see License File for more information.