Cron Monitoring
Monitor scheduled jobs and cron tasks with HTTP check-ins. Get notified through Email, webhooks or your other integrations when a job misses its check-in, and see failed runs in the Console. No SDK required.
Monitor your scheduled jobs and cron tasks. Abrova Trace notifies you through your configured integrations when a check-in is missed, and records failed runs. No SDK required — any HTTP client can send check-ins.
3 cron monitors are free every month. Each extra monitor costs 2,000 Toman a month from your wallet — see Pricing. Check-ins themselves cost nothing.
ab_srv_…) in the X-API-Key header. Run them from your server or CI, from an environment variable — never from an app.Cron Monitoring#
Monitor scheduled jobs and cron tasks with HTTP check-ins. Missed check-ins notify you through Email, webhooks or your other integrations; failed runs are recorded and shown on the monitor. No SDK required — any HTTP client can send check-ins.
How It Works
- Create a Monitor — Define a cron monitor in Abrova Console with a unique slug, a schedule (cron expression or interval), and a grace period.
- Send Check-Ins — Your cron job sends an HTTP POST to the check-in API when it runs. No SDK needed — just a simple HTTP call.
- Detect Missed Jobs — AbrovaTrace evaluates all monitors every 5 minutes. If a check-in is overdue (past expected interval + grace period), the monitor status changes to "missed".
- Get Notified — When a job is missed, notifications are sent to the integrations you selected on the monitor (Email, Webhook, etc.).
Create a Monitor (Dashboard)
- In Abrova Console, open your project → Trace → Crons
- Click "New monitor"
- Fill in the monitor details (see configuration below)
- Optionally select notification channels from your active integrations
- Click "Create monitor" to save
Managing monitors (create, edit, pause, delete) needs the admin or owner role; every role can see monitors and their check-in history. See Roles & Permissions.
Monitor Configuration
| Option | Type | Required | Description |
|---|---|---|---|
| Name | string | Yes | Descriptive name (e.g., "Daily Database Backup") |
| Slug | string | Yes | Unique identifier used in check-in API (e.g., "daily-backup"). Auto-generated from name. |
| Schedule | string | No | Cron expression (e.g., "0 2 * * *"). When set, it decides the expected interval. |
| Expected Interval | number | Yes | How often the job should run, in minutes (default: 60). Used when no cron expression is set. |
| Grace Period | number | Yes | Extra minutes to wait before marking as missed (default: 5) |
| Environment | string | No | Filter by environment (e.g., production) |
| Notification Channels | multi-select | No | Select from your active integrations |
Send Check-Ins from Your Jobs
When your cron job runs, send an HTTP POST to the check-in endpoint. Authenticate with your project's server secret (ab_srv_...) in the X-API-Key header. The monitor will be auto-created if the slug doesn't exist yet.
Cron jobs run on your servers, so use the server secret. The app key (ab_live_...) is also accepted while the project setting Server routes require the server secret is off — but it ships inside your apps, so anyone who extracts it could send a fake "ok" check-in. Switch the setting on once your jobs use the server secret. See Server Secret & Server Routes.
If you send a check-in with a slug that doesn't exist, AbrovaTrace will automatically create a monitor with default settings (60-minute interval, 5-minute grace period). You can then customize it in the dashboard.
Check-In API
| Field | Type | Required | Description |
|---|---|---|---|
monitor_slug | string | Yes | The unique slug of the monitor |
status | string | Yes | "ok", "error", or "in_progress" |
check_in_id | string | No | UUID to track multi-step jobs (returned as `id` from in_progress) |
duration_ms | number | No | How long the job took in milliseconds |
environment | string | No | Environment name (e.g., "production") |
message | string | No | Optional message or error details |
Examples
Simple Check-In (curl)
Send a single "ok" check-in when your job completes successfully:
curl -X POST https://trace.abrova.ir/api/cron-monitors/check-in \
-H "X-API-Key: ab_srv_your_server_secret" \
-H "Content-Type: application/json" \
-d '{
"monitor_slug": "daily-backup",
"status": "ok",
"duration_ms": 4500
}'Report an Error (curl)
If the job fails, report it with "error" status:
curl -X POST https://trace.abrova.ir/api/cron-monitors/check-in \
-H "X-API-Key: ab_srv_your_server_secret" \
-H "Content-Type: application/json" \
-d '{
"monitor_slug": "daily-backup",
"status": "error",
"message": "Connection to database timed out"
}'Multi-Step Job (curl)
For long-running jobs, start with "in_progress" and complete with "ok" or "error":
# Step 1: Mark job as in_progress (returns a check_in_id)
CHECK_IN_ID=$(curl -s -X POST https://trace.abrova.ir/api/cron-monitors/check-in \
-H "X-API-Key: ab_srv_your_server_secret" \
-H "Content-Type: application/json" \
-d '{"monitor_slug": "nightly-report", "status": "in_progress"}' \
| jq -r '.id')
# ... run your job ...
# Step 2: Mark job as complete
curl -X POST https://trace.abrova.ir/api/cron-monitors/check-in \
-H "X-API-Key: ab_srv_your_server_secret" \
-H "Content-Type: application/json" \
-d "{
\"monitor_slug\": \"nightly-report\",
\"status\": \"ok\",
\"check_in_id\": \"$CHECK_IN_ID\",
\"duration_ms\": 120000
}"Node.js
const axios = require('axios');
const API_KEY = process.env.ABROVA_SERVER_SECRET; // ab_srv_...
const BASE_URL = 'https://trace.abrova.ir/api/cron-monitors/check-in';
async function runDailyBackup() {
const start = Date.now();
try {
// ... your backup logic here ...
await performBackup();
// Report success
await axios.post(BASE_URL, {
monitor_slug: 'daily-backup',
status: 'ok',
duration_ms: Date.now() - start,
}, { headers: { 'X-API-Key': API_KEY } });
} catch (error) {
// Report failure
await axios.post(BASE_URL, {
monitor_slug: 'daily-backup',
status: 'error',
duration_ms: Date.now() - start,
message: error.message,
}, { headers: { 'X-API-Key': API_KEY } });
}
}Python
import os
import requests
import time
API_KEY = os.environ["ABROVA_SERVER_SECRET"] # ab_srv_...
BASE_URL = "https://trace.abrova.ir/api/cron-monitors/check-in"
def run_daily_backup():
start = time.time()
headers = {"X-API-Key": API_KEY, "Content-Type": "application/json"}
try:
# ... your backup logic here ...
perform_backup()
# Report success
requests.post(BASE_URL, json={
"monitor_slug": "daily-backup",
"status": "ok",
"duration_ms": int((time.time() - start) * 1000),
}, headers=headers)
except Exception as e:
# Report failure
requests.post(BASE_URL, json={
"monitor_slug": "daily-backup",
"status": "error",
"duration_ms": int((time.time() - start) * 1000),
"message": str(e),
}, headers=headers)Laravel (Artisan Command)
<?php
// In your scheduled command or Kernel.php
use Illuminate\Support\Facades\Http;
$start = microtime(true);
try {
// ... your job logic ...
$this->performCleanup();
Http::withHeaders([
'X-API-Key' => env('ABROVATRACE_SERVER_SECRET'),
])->post('https://trace.abrova.ir/api/cron-monitors/check-in', [
'monitor_slug' => 'daily-cleanup',
'status' => 'ok',
'duration_ms' => (int)((microtime(true) - $start) * 1000),
]);
} catch (\Exception $e) {
Http::withHeaders([
'X-API-Key' => env('ABROVATRACE_SERVER_SECRET'),
])->post('https://trace.abrova.ir/api/cron-monitors/check-in', [
'monitor_slug' => 'daily-cleanup',
'status' => 'error',
'message' => $e->getMessage(),
]);
}Bash Script
Wrap any cron job with a simple check-in call at the end:
#!/bin/bash
# Add this to the end of your cron job script
API_KEY="$ABROVA_SERVER_SECRET" # ab_srv_...
# Run your job
/usr/local/bin/my-backup-script.sh
# Report based on exit code
if [ $? -eq 0 ]; then
curl -s -X POST https://trace.abrova.ir/api/cron-monitors/check-in \
-H "X-API-Key: $API_KEY" \
-H "Content-Type: application/json" \
-d '{"monitor_slug": "my-backup", "status": "ok"}'
else
curl -s -X POST https://trace.abrova.ir/api/cron-monitors/check-in \
-H "X-API-Key: $API_KEY" \
-H "Content-Type: application/json" \
-d '{"monitor_slug": "my-backup", "status": "error"}'
fiMonitor Statuses
Last check-in was successful
Last check-in reported an error
No check-in received within expected time
Monitor is paused
API Reference
Your cron job sends check-ins to one public endpoint:
POST /api/cron-monitors/check-in
It takes a project credential in the X-API-Key header: the server secret (recommended), or the app key while the "Server routes require the server secret" setting is off.
Manage monitors in Abrova Console. What a signed-in user may do there depends on their role — see Roles & Permissions.
Best Practices
Choose slugs like "daily-backup", "hourly-sync", or "weekly-report" that clearly identify the job.
Give enough buffer for natural job duration variation. A 5-minute grace period works for most jobs; use longer for jobs with variable runtimes.
Always send a check-in with status "error" when a job fails. This gives you visibility into both missed and failed jobs.
Include duration_ms in your check-ins to spot performance degradation over time.
For jobs that take minutes or hours, use in_progress + ok/error pattern. This lets you distinguish between "still running" and "missed".
Connect at least one integration (Email or a Webhook work without a connection outside Iran) to get alerted when jobs are missed.
Troubleshooting
Monitor shows as missed but job ran?
- Verify the key is correct and active — check the HTTP status of the check-in; a 401 means it was refused
- Check that the
monitor_slugmatches exactly - Ensure the check-in request is reaching the server (check network/firewall)
- Review the expected interval — if your job runs every 24 hours, set the interval to 1440 minutes
- Check the grace period — increase it if your job has variable start times
Not receiving missed notifications?
- Verify notification channels are selected on the monitor
- Check that the selected integrations are active (test them in Trace → Integrations)
- Missed detection runs every 5 minutes — there may be a short delay
- Ensure the monitor is enabled (not disabled/toggled off)
Check-in API returns 401?
- Verify the key starts with
ab_srv_(orab_live_) - If the response says
server_credential_required, the project setting Server routes require the server secret is on and the job sent the app key — use the server secret - Check that the key is being sent in the
X-API-Keyheader - Ensure the API key belongs to an active project with Trace enabled
Cannot create another monitor?
- 3 monitors are free; more monitors are paid from your organisation's wallet (2,000 Toman per extra monitor a month)
- Top up the wallet in Abrova Console, or delete a monitor you no longer need
Auto-created monitor has wrong settings?
- Auto-created monitors use defaults (60 min interval, 5 min grace)
- Go to Trace → Crons in Abrova Console and edit the monitor
- Alternatively, create the monitor in the dashboard first with your desired settings