Heartbeat Monitoring #
Complete guide to passive heartbeat monitoring for scheduled tasks, cron jobs, and background processes.
Overview #
Heartbeat monitoring is a passive monitoring approach where your applications "ping" a unique URL at regular intervals. If a ping is missed, an alert is triggered. This is ideal for monitoring scheduled tasks, cron jobs, backup processes, and other periodic jobs.
Key Differences: Servers vs Heartbeats #
| Feature | Servers (Active) | Heartbeats (Passive) |
|---|---|---|
| Direction | We check your endpoint | Your system pings us |
| Use Case | Websites, APIs | Cron jobs, scheduled tasks |
| Detection | Response status codes | Missing pings |
| Setup | Add URL to monitor | Add ping to your task |
Creating a Heartbeat #
1. Navigate to Heartbeats #
Go to Heartbeats in the admin menu.
2. Create New Heartbeat #
Click New Heartbeat and fill in:
- Name: Descriptive name (e.g., "Daily Database Backup")
- Timeframe: Expected interval between pings (e.g., "1 hour")
- Grace Period: Additional time before alerting (optional)
3. Get Your Unique URL #
After saving, you'll receive a unique ping URL:
https://yoursite.com/heartbeat/ping/abc123-def456-ghi789
This URL is permanent and unique to this heartbeat.
4. Add Ping to Your Task #
Add the ping URL to your scheduled task (see integration examples below).
Timeframe Options #
| Timeframe | Description | Use Case |
|---|---|---|
| 10m | Every 10 minutes | Frequent checks, real-time processing |
| 30m | Every 30 minutes | Queue processors, data sync |
| 1h | Every hour | Hourly reports, cache refresh |
| 1d | Every day (24h) | Daily backups, daily reports |
| 1w | Every week | Weekly maintenance, weekly reports |
| 1m | Every month | Monthly billing, monthly cleanup |
Status Indicators #
| Status | Description |
|---|---|
| Healthy 🟢 | Ping received within expected timeframe |
| Missing 🔴 | No ping received, alert triggered |
| Recovering 🟡 | Ping received after being missing |
| Never Pinged ⚪ | New heartbeat, waiting for first ping |
Integration Examples #
Shell Script / Cron Job #
#!/bin/bash
# backup.sh - Daily backup script
# Your backup logic here
mysqldump mydb > backup.sql
gzip backup.sql
# Send heartbeat ping at the end
curl -fsS --retry 3 https://yoursite.com/heartbeat/ping/abc123-def456
Add to crontab:
0 2 * * * /path/to/backup.sh
PHP Script #
<?php
// scheduled-task.php
// Your task logic here
processQueue();
generateReports();
// Send heartbeat ping
$ch = curl_init('https://yoursite.com/heartbeat/ping/abc123-def456');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_TIMEOUT, 10);
curl_exec($ch);
curl_close($ch);
Python Script #
#!/usr/bin/env python3
import requests
def main():
# Your task logic here
process_data()
send_reports()
# Send heartbeat ping
try:
requests.get(
'https://yoursite.com/heartbeat/ping/abc123-def456',
timeout=10
)
except requests.RequestException:
pass # Don't let ping failure break the script
if __name__ == '__main__':
main()
Node.js #
const https = require('https');
async function runTask() {
// Your task logic here
await processQueue();
await generateReports();
// Send heartbeat ping
https.get('https://yoursite.com/heartbeat/ping/abc123-def456');
}
runTask().catch(console.error);
Laravel Scheduled Task #
// app/Console/Kernel.php
protected function schedule(Schedule $schedule)
{
$schedule->command('backup:run')
->daily()
->after(function () {
Http::get('https://yoursite.com/heartbeat/ping/abc123-def456');
});
}
Docker Container #
# Dockerfile
CMD ["/bin/sh", "-c", "your-task.sh && curl -fsS https://yoursite.com/heartbeat/ping/abc123-def456"]
GitHub Actions #
# .github/workflows/scheduled.yml
name: Scheduled Task
on:
schedule:
- cron: '0 * * * *' # Every hour
jobs:
run:
runs-on: ubuntu-latest
steps:
- name: Run task
run: |
# Your task here
echo "Running scheduled task..."
- name: Send heartbeat
run: curl -fsS https://yoursite.com/heartbeat/ping/abc123-def456
AWS Lambda #
import urllib.request
def lambda_handler(event, context):
# Your task logic here
result = process_event(event)
# Send heartbeat ping
try:
urllib.request.urlopen(
'https://yoursite.com/heartbeat/ping/abc123-def456',
timeout=10
)
except:
pass
return result
Ping URL Options #
Basic Ping #
curl https://yoursite.com/heartbeat/ping/abc123-def456
Ping with Exit Code #
Report success or failure based on your task:
# Report success
curl https://yoursite.com/heartbeat/ping/abc123-def456?status=success
# Report failure
curl https://yoursite.com/heartbeat/ping/abc123-def456?status=failure
# Report with exit code
curl https://yoursite.com/heartbeat/ping/abc123-def456?exit_code=$?
Ping with Timing #
Track execution duration:
start_time=$(date +%s)
# Your task here
end_time=$(date +%s)
duration=$((end_time - start_time))
curl "https://yoursite.com/heartbeat/ping/abc123-def456?duration=${duration}"
Ping with Message #
Include a message with the ping:
curl -X POST https://yoursite.com/heartbeat/ping/abc123-def456 \
-d "message=Processed 1234 records"
Bulk Import #
CSV Format #
name,timeframe
Daily Backup,1d
Queue Processor,10m
Weekly Report,1w
Monthly Cleanup,1m
Import Process #
- Navigate to Heartbeats
- Click Import
- Upload CSV file
- Review imported heartbeats
- Copy ping URLs for each heartbeat
Heartbeat Dashboard #
The dashboard shows:
- Total Heartbeats: Number of configured heartbeats
- Healthy: Heartbeats receiving pings on time
- Missing: Heartbeats that missed expected pings
- Last Ping: When each heartbeat was last pinged
Notifications #
When Alerts Trigger #
Notifications are sent when:
- A heartbeat goes from healthy to missing
- A missing heartbeat recovers (first ping after missing)
Notification Content #
💔 Heartbeat Missing: Daily Database Backup
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Expected: Every 1 day
Last Ping: 26 hours ago
Missing Since: 2 hours ago
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Plan Limits #
Heartbeats share limits with servers:
| Plan | Servers + Heartbeats |
|---|---|
| Free | 50 combined |
| Basic | 200 combined |
| Pro | 500 combined |
| Enterprise | Unlimited |
Data Retention #
Ping History #
- Last 1000 pings per heartbeat are retained
- Older pings are automatically cleaned up
- Cleanup happens during each new ping
Log Retention #
Status change logs follow the same retention as servers:
- Free: 7 days
- Basic: 30 days
- Pro/Enterprise: 90 days
Best Practices #
Ping at Task Completion #
# Good - ping after task succeeds
backup.sh && curl https://...
# Bad - ping before task runs
curl https://... && backup.sh
Handle Ping Failures Gracefully #
# Don't let ping failure break your task
curl -fsS --retry 3 https://... || true
Use Appropriate Timeframes #
- Set timeframe slightly longer than task duration
- Account for network delays
- Include grace period for variable-length tasks
Include Error Handling #
#!/bin/bash
if backup.sh; then
curl "https://...?status=success"
else
curl "https://...?status=failure&message=Backup%20failed"
exit 1
fi
Troubleshooting #
Heartbeat Always Missing #
Check ping URL:
# Test manually
curl -v https://yoursite.com/heartbeat/ping/abc123-def456
Verify task is running:
- Check cron logs
- Verify task execution
- Check for errors in task output
False Positives #
Increase Timeframe:
- If task sometimes takes longer than expected
- Add buffer time for variable execution
Add Grace Period:
- Accounts for network delays
- Provides additional buffer
Ping Not Recorded #
Check Network:
- Firewall rules allowing outbound HTTPS
- DNS resolution working
- Verify endpoint is accessible
Check URL:
- URL is correct and complete
- No typos in the unique ID
- HTTPS protocol used
Previous: Server Management | Next: Status Pages