How to monitor Google Cloud Scheduler jobs
To monitor a Cloud Scheduler job, watch its execution logs in Cloud Logging: Cloud Scheduler publishes a log at the start and end of every execution, so pair each AttemptStarted entry with its matching AttemptFinished entry and alert when the finish is missing or has a non-2xx status. Create a log-based metric and a Cloud Monitoring alerting policy for failed executions, or route the logs to a Pub/Sub topic for real-time processing.
What does Cloud Scheduler log for each execution?
Cloud Scheduler writes two log entries per HTTP execution to Cloud Logging:
- AttemptStarted: written when the scheduler dispatches the HTTP request to your target.
- AttemptFinished: written when the target responds. Includes the HTTP status code — 2xx is success, anything else is a failure.
- A job that never gets an AttemptFinished (target timed out) or gets a non-2xx status is a failed execution.
How do I create a Cloud Monitoring alert for failed executions?
Create a log-based metric that counts failed AttemptFinished entries, then an alerting policy that fires when the count is above zero:
# Create a log-based metric for failed Cloud Scheduler executions
gcloud logging metrics create cloud_scheduler_failures \
--description="Cloud Scheduler job failures" \
--log-filter='resource.type="cloud_scheduler_job"
jsonPayload.@type="type.googleapis.com/google.cloud.scheduler.logging.AttemptFinished"
jsonPayload.status!="OK"'
# Then create an alerting policy in Cloud Monitoring that fires when
# cloud_scheduler_failures > 0 over the past 5 minutes.How do I detect a job that never ran at all?
A job that was never attempted — disabled state, bad schedule expression, or a quota error — produces no AttemptStarted log entry. The log-based metric above counts failures, not absences. To detect a missing run, add a heartbeat from inside your target endpoint: if no ping arrives in the expected window, your external monitor alerts regardless of what Cloud Logging shows.
import httpx
from flask import Flask, jsonify
app = Flask(__name__)
PING_URL = "https://ping.cronshield.com/<your-check-id>"
@app.route("/cron/nightly")
def nightly():
try:
run_nightly_job()
httpx.get(PING_URL, timeout=10)
return jsonify({"status": "ok"})
except Exception as exc:
return jsonify({"error": str(exc)}), 500Add a missed-run alert to this job
The free tier gives you a heartbeat endpoint and an email alert when an expected ping doesn't arrive. Paid tiers add the log-aware diagnosis — the last log line and a likely cause in the alert. The heartbeat receiver ships in an upcoming release; see the plans to learn what each tier adds.
Frequently asked questions
- Does Cloud Scheduler retry a failed invocation?
- Yes. You can configure a retry config on the job with a maximum retry count and minimum/maximum backoff. Each retry attempt is logged as a separate AttemptStarted/AttemptFinished pair. If all retries are exhausted, the job is counted as failed.
- How do I view Cloud Scheduler logs in Cloud Logging?
- In the Google Cloud Console, go to Logging > Logs Explorer and filter by resource type 'cloud_scheduler_job'. Filter by your job name to see its execution history. Each entry includes the HTTP request, response status code, and execution duration.