Skip to content

Cron Alerting — Automated Alerts for Cron Job Failures and Anomalies

DodaTech Updated 2026-06-28 6 min read

In this tutorial, you will learn about Cron Alerting. We cover key concepts, practical examples, and best practices to help you master this topic.

Learn cron alerting strategies: configure automated alerts for cron job failures, duration anomalies, missed executions, and success rate degradation. Integrate with Slack, email, and PagerDuty for reliable notification.

What You Learn

You will learn how to set up alerting for Cron Jobs: defining alert rules for failures, duration anomalies, missed executions, configuring notification channels, and implementing escalation policies.

Why It Matters

A cron job that silently fails is worse than no cron job at all. Alerting turns failures into actionable notifications. Without alerting, a failed database backup is discovered only when a restore is attempted and the backup is missing.

Real-World Use

DodaTech alerting rules for cron: Page PagerDuty if a critical job fails, send Slack message to #cron-alerts for any job failure, send email digest of all failures every 6 hours. Consecutive failures escalate: 1 failure -> Slack, 2 consecutive -> PagerDuty low, 3 consecutive -> PagerDuty high.

Alert Rule Engine

import time
import json
from datetime import datetime

class CronAlertRule:
    def __init__(self, name, condition_fn, severity='warning', message_template=''):
        self.name = name
        self.condition = condition_fn
        self.severity = severity
        self.message = message_template
        self.firing = False

class CronAlertManager:
    def __init__(self):
        self.rules = []
        self.alerts = []

    def add_rule(self, rule):
        self.rules.append(rule)

    def evaluate(self, job_metrics):
        for rule in self.rules:
            try:
                triggered = rule.condition(job_metrics)
                if triggered and not rule.firing:
                    rule.firing = True
                    self._fire_alert(rule, job_metrics)
                elif not triggered:
                    rule.firing = False
            except Exception as e:
                print(f"Alert rule '{rule.name}' evaluation error: {e}")

    def _fire_alert(self, rule, metrics):
        alert = {
            'rule': rule.name,
            'severity': rule.severity,
            'job': metrics.get('job_name', 'unknown'),
            'message': rule.message.format(**metrics),
            'timestamp': datetime.now().isoformat(),
            'metrics': metrics
        }
        self.alerts.append(alert)
        channel = {'warning': 'Slack', 'critical': 'PagerDuty', 'info': 'email'}
        print(f"[{rule.severity.upper()}] Alert: {alert['message']} -> {channel.get(rule.severity, 'Slack')}")

def failure_condition(m):
    return m.get('success', 1) == 0

def duration_condition(m):
    max_dur = m.get('expected_max_duration', 300)
    return m.get('duration_seconds', 0) > max_dur * 2

def missed_condition(m):
    age_min = m.get('age_minutes_since_last_run', 0)
    expected = m.get('expected_interval_minutes', 1440)
    return age_min > expected * 2

manager = CronAlertManager()
manager.add_rule(CronAlertRule("JobFailure", failure_condition, "critical", "Job {job_name} failed"))
manager.add_rule(CronAlertRule("JobDuration", duration_condition, "warning", "Job {job_name} took {duration_seconds}s (max: {expected_max_duration}s)"))
manager.add_rule(CronAlertRule("JobMissed", missed_condition, "critical", "Job {job_name} has not run in {age_minutes_since_last_run} min"))

manager.evaluate({'job_name': 'db-backup', 'success': 0, 'duration_seconds': 45, 'expected_max_duration': 60})
manager.evaluate({'job_name': 'cache-warm', 'success': 1, 'duration_seconds': 120, 'expected_max_duration': 30})

Expected output:

[CRITICAL] Alert: Job db-backup failed -> PagerDuty
[WARNING] Alert: Job cache-warm took 120s (max: 30s) -> Slack

Escalation Policy

import time
from datetime import datetime, timedelta

class EscalationPolicy:
    def __init__(self, name, levels=None):
        self.name = name
        self.levels = levels or []
        self.consecutive_failures = {}

    def add_level(self, after_minutes, channel, severity):
        self.levels.append({'after': after_minutes, 'channel': channel, 'severity': severity})

    def evaluate(self, job_name, consecutive_failures):
        failure_count = consecutive_failures.get(job_name, 0)
        for level in reversed(self.levels):
            if failure_count >= level['after']:
                print(f"Escalation [{self.name}/{job_name}]: level={level['after']} failures -> {level['channel']} ({level['severity']})")
                return level
        return None

policy = EscalationPolicy("cron-escalation")
policy.add_level(1, "Slack", "warning")
policy.add_level(2, "PagerDuty", "critical")
policy.add_level(5, "Phone Call", "emergency")

failures = {'db-backup': 1, 'cache-warm': 3, 'report-gen': 6}
for job, count in failures.items():
    policy.evaluate(job, failures)

Expected output:

Escalation [cron-escalation/db-backup]: level=1 failures -> Slack (warning)
Escalation [cron-escalation/cache-warm]: level=2 failures -> PagerDuty (critical)
Escalation [cron-escalation/report-gen]: level=5 failures -> Phone Call (emergency)

Common Mistakes

1. Alerting Fatigue

Alerting on every single failure desensitizes the team. Use: alert on consecutive failures (2+), not single. Use different channels for different severities: Slack for warnings, PagerDuty for critical.

2. No Escalation Path

A Slack message sent at 3 AM may not be seen until 9 AM. Implement escalation: Slack -> PagerDuty -> phone call. Each level has a different notification channel and response expectation.

3. Alerting Without Context

"Job failed" tells the on-call engineer nothing. Include: job name, hostname, exit code, duration, last N log lines, and a link to the full logs. Context reduces mean time to resolution.

4. No Maintenance Window Support

If a cron job is intentionally disabled for maintenance, all alert rules should be silenced. Implement maintenance Windows: specify start/end time and affected jobs. Suppress alerts during the window.

5. Alert Rules Never Reviewed

Alert rules that were useful 6 months ago may be noisy or irrelevant now. Review alert rules monthly. Tune thresholds based on observed patterns. Remove rules that never fire or always fire.

Practice Questions

1. What is a good default alert severity for cron job failures?

Warning: first failure of non-critical job, duration exceeds 2x expected. Critical: consecutive failures (2+) of any job, no successful run in 2x interval, critical job failure. Emergency: 5+ consecutive failures, no run in 5x interval.

2. How do you implement escalation policies for cron alerts?

Define escalation tiers: tier 1 (Slack, immediate), tier 2 (PagerDuty, after 2 consecutive failures), tier 3 (phone call, after 5 consecutive failures). Each tier has a higher severity and faster expected response time.

3. How do you prevent alert fatigue from cron failures?

Require consecutive failures before alerting (2+). Use maintenance windows. Implement daily/weekly digests for non-urgent alerts. Route different severities to different channels. Review and tune thresholds monthly.

4. What information should every cron alert include?

Job name, hostname, exit code, duration, expected duration, last N log lines, timestamp, next scheduled run, and a link to the job's runbook. For failure alerts, include the error message and stack trace.

Challenge

Build a cron alerting system: (1) alert rules: failure (consecutive > 1), duration (> 2x expected), missed (no run in 2x interval), (2) escalation: 1 failure -> Slack, 2 consecutive -> PagerDuty, 5 consecutive -> phone call, (3) notification channels: Slack (with attachment showing key fields), email (HTML with full context), PagerDuty (with dedup key per job), (4) maintenance windows: YAML config with start/end and affected jobs, suppress alerts during maintenance, (5) digest: daily email summary of all alerts with pass/fail counts, (6) dashboard: alert history, escalation status per job.

FAQ

Should I alert on every single cron job failure?

No. Alert on consecutive failures. One failure may be transient (network blip, temporary resource exhaustion). Two+ consecutive failures indicate a real problem. Use different thresholds for critical vs non-critical jobs.

What is the difference between an alert and a notification?

An alert is a rule that triggers when a condition is met (e.g., job failed). A notification is the delivery method (Slack, email, PagerDuty). One alert can trigger multiple notifications at different escalation levels.

How do I handle alerting for jobs that run infrequently (monthly)?

Use longer thresholds: alert on missed execution after 2x the interval (60 days for a monthly job). Use a heartbeat approach: the job sends a heartbeat on success. Alert if heartbeat is absent beyond the expected interval + grace period.

Should I create separate alerts for duration anomalies and failures?

Yes. A job that succeeds but takes 10x longer than usual indicates a problem. Separate alerts for failures and duration anomalies allow different response paths: duration may not require immediate page, but a failure of a critical job does.

How do I test alert rules without causing false positives?

Use a test mode: alert rules evaluate and log but do not send notifications. Or inject test metrics that match the alert condition and verify the notification fires. Test alert rules after each change.

Mini Project: Cron Alerting System

Build a comprehensive alerting system: (1) alert rules engine: failure (consecutive > 1), duration (> 2x expected P95), missed (no run in 2x interval), stale (no metrics for 3x interval), (2) escalation tiers: tier 1 -> Slack (#cron-alerts), tier 2 -> PagerDuty (after 2 consecutive), tier 3 -> phone call (after 5 consecutive), (3) notification formatter: Slack with colorful attachments, email HTML with table, PagerDuty with dedup key, (4) maintenance windows: YAML config, suppress during window, (5) alert suppression: silence duplicate alerts for 1 hour, aggregate multiple failures of the same job into one alert, (6) dashboard: alert history by job, escalation status, MTTR (mean time to resolve), (7) monthly review: alert frequency report, false positive rate, tuning recommendations.

What's Next

Now that you understand cron alerting, explore SLA compliance for cron jobs, then learn about capacity planning for cron.

Built by the developers of DodaTech

Doda Browser, DodaZIP & Durga Antivirus Pro