Docs/Features

Cron job monitoring

Our cron job monitoring uses an industry-standard way of monitoring the health of your scheduled tasks. We use a callback URL, sometimes called a heartbeat or pingback.

When you create a cron job definition in Oh Dear, you will be given a unique URL specific to that cron job.

You can then modify your cron job in your code or on your servers, to do a quick network fetch to that unique URL. If we receive that pingback on time, we know the cron job was executed correctly.

If we don't receive a hit on that unique URL, we know the cron job hasn't been executed, and we can alert you.

Amount of cron jobs to monitor

Per website in your subscription package, you have a quota of 5 cron jobs you can monitor.

For instance: if you are currently on the 10-site plan, you will have a total quota of 50 cron jobs you can monitor.

You are free to use those any way you like, you can add 45 cron jobs to a single site and the remaining 5 cron jobs to another one. To monitor more cron jobs, you can upgrade your subscription.

Simple cron job monitoring

By default, we have the option to do simple cron job monitoring.

For simple cron job monitoring, you would only need to provide the frequency. In other words, how often does this cron job run on your systems?

This would be set to the exact frequency the scheduled tasks are executed. If a cron job runs every five minutes, you would set the frequency to 5.

Cron expression monitoring

An alternative to the simple cron job monitoring is the method where you define a crontab schedule instead.

To use this, you can enter the exact crontab syntax you would find on your servers. For instance, for cron expression type monitoring, you could enter the following:

  • * * * * *: this would run every minute
  • */5 * * * *: this would run every five minutes
  • 0 */4 * * *: this would run every 4 hours
  • 0 10 1 * *: this would run at 10AM on the first day of each month

While the syntax is more arcane (it's default crontab syntax), it allows you to copy/paste directly from your crontab.

Server Timezone

If you're using the cron expression to define your cron job monitors, we need to know the timezone of your server. It's that timezone that determines when the scheduled tasks will be executed.

Not sure what timezone your server is configured in? You can find out here.

Grace time

What's the grace time in cron job monitoring? It defines how much time should we allow for a pingback to be received.

To understand this option better, consider the following example.

  1. You have a cron job that runs every 5 minutes.
  2. Sometimes, the cron job finishes in a matter of seconds. Sometimes it takes a few minutes to complete, as it has to import data or calculate results.

Because the cron job is executed every five minutes, the frequency option would be set to 5.

Because there's a variable execution time in the cron job, we want to allow a bit more time for the cron job to actually finish and report back to us. If you know the job itself should not take more than two minutes to complete, you could set the grace time to 3 - slightly higher than your maximum execution time.

This gives us a little more wiggle room before we send out a notification.

In this example, if the cronjob isn't executed, we will wait for 3 more minutes before we send the notifications. If we receive the ping that the cron was executed during that grace time, we won't send any notifications.

Implementing the Ping URL in your application

In order to use your cron job monitoring, your application should be configured to make an HTTP call to the Ping URL whenever the job is completed. Here are some ways you could implement this.

We have example code available for:

We have support for even more advanced options, like providing runtime duration and memory usage or failure states. Have a look at at the advanced options & parameters to see what's possible.

Crontab

Oh Dear users can add cron job monitoring to any existing crontab on your Linux servers. When you create a cronjob monitor in your Oh Dear account, you're given a unique pingback URL that should be called every time a cronjob completes.

In this guide, we'll cover how you can implement that in your existing crontab.

Example crontab monitoring

Imagine you have the following cronjob configured on your Linux server.

$ crontab -l
55 * * * * script.sh

You can modify this line so it calls back to our Ping URL whenever your script has executed successfuly.

$ crontab -l
55 * * * * script.sh && curl -fsS --retry 3 -o /dev/null https://ping.ohdear.app/e536e771-9ff6

By using the && operation in Bash, we will only call our URL if your script finished with an exit code of 0. In other words: we'll only call our URL if your script executed without any error.

Note: make sure your script throws a non-zero exit code whenever it has encountered a failure condition.

Example script monitoring in Bash

Alternatively, if you are calling a Bash script in your crontab, you can move the curl call to the very last line of your Bash script instead. If curl is not available on your system, you may also use wget.

curl --retry 3 https://ping.ohdear.app/e536e771-9ff6
wget -O /dev/null https://ping.ohdear.app/e536e771-9ff6

This allows you to implement cron job monitoring to any Bash script, regardless of how it's being called.

Advanced use of cron job reporting

Next to providing us a ping whenever your script has finished, you can also actively send failure states to us.

For more information about sending failures or debug-information like memory consumption & runtime duration, please see the advanced options of our cron job monitoring.

PHP

Oh Dear users can add cron job monitoring to any existing PHP script. When you create a cronjob monitor in your account, you're given a unique pingback URL that should be called every time a script completes.

In this guide, we'll cover how you can implement that in your existing PHP code.

Cron monitoring in generic PHP

This is a technique that can be used in any PHP application, regardless of the framework you use.

At the very bottom of your scheduled command, add a call to the file_get_contents() function that will call back to us and inform you the job has ended.

@file_get_contents('https://ping.ohdear.app/e536e771-9ff6');

Note: make sure your script stops executing on error conditions, so the file_get_contents() function isn't called even if the script has failed.

Cron monitoring in Laravel (PHP)

Note: there's a convenient Laravel package called spatie/laravel-schedule-monitor you can use that syncs up nicely with Oh Dear. Please refer to this package's documentation on how it works.

In standard Laravel, you can use the thenPing() method in your Console scheduler. You'll find this in the app/Console/Kernel.php file.

class Kernel extends ConsoleKernel
{
    protected function schedule(Schedule $schedule)
    {
        $schedule->command('emails:send')
            ->daily()
            ->thenPing('https://ping.ohdear.app/e536e771-9ff6');
    }
}

Cron monitoring in Symfony (PHP)

This example uses the zenstruck/schedule-bundle scheduler in Symfony.

You can either define it in your PHP code:

use Zenstruck\ScheduleBundle\Schedule\Task\PingTask;

/* @var \Zenstruck\ScheduleBundle\Schedule $schedule */

$schedule->add(new PingTask('https://ping.ohdear.app/e536e771-9ff6'));

Or in your configurations:

# config/packages/zenstruck_schedule.yaml
zenstruck_schedule:
  tasks:
    # note the "ping:" prefix
    - task: ping:https://ping.ohdear.app/e536e771-9ff6
      frequency: '0 * * * *'

Python

Oh Dear users can add cron job monitoring to any existing Python script. When you create a cronjob monitor in your Oh Dear account, you're given a unique pingback URL that should be called every time a cronjob completes.

In this guide, we'll cover how you can implement that in your existing Python code.

Cron job monitoring in generic Python

You can use the requests library in Python to make an outgoing HTTPs call to our Ping URL.

import requests

requests.get("https://ping.ohdear.app/e536e771-9ff6")

_Note: make sure your script stops executing on error conditions, so the requests.get function isn't called even if the script ha

Ruby

Oh Dear users can add cron job monitoring to any existing Ruby script. When you create a cronjob monitor in your Oh Dear account, you're given a unique pingback URL that should be called every time a cronjob completes.

In this guide, we'll cover how you can implement that in your existing Ruby code.

Cron job monitoring in generic Ruby

Here's how you can add the Ping URL to any existing Ruby script.

require 'net/http'
require 'uri'

Net::HTTP.get(URI.parse('https://ping.ohdear.app/e536e771-9ff6'))

Note: make sure your script stops executing on error conditions, so the Net::HTTP.get function isn't called even if the script has failed.

NodeJS

Oh Dear users can add cron job monitoring to any existing NodeJS script. When you create a cronjob monitor in your Oh Dear account, you're given a unique pingback URL that should be called every time a cronjob completes.

In this guide, we'll cover how you can implement that in your existing NodeJS code.

Cron job monitoring in generic NodeJS

You can use the built-in functions from https to make outgoing network calls.

var https = require('https');
https.get("https://ping.ohdear.app/e536e771-9ff6");

Note: make sure your script stops executing on error conditions, so the https.get function isn't called even if the script has failed.

Perl

Oh Dear users can add cron job monitoring to any existing Perl script. When you create a cronjob monitor in your Oh Dear account, you're given a unique pingback URL that should be called every time a cronjob completes.

In this guide, we'll cover how you can implement that in your existing Perl code.

Cron job monitoring in generic Perl

You can make use of the LWP::Simple library for making network calls.

use LWP::Simple;
get("https://ping.ohdear.app/e536e771-9ff6");

Note: make sure your script stops executing on error conditions, so the get function isn't called even if the script has failed.

Golang

Oh Dear users can add cron job monitoring to any existing Golang script. When you create a cronjob monitor in your Oh Dear account, you're given a unique pingback URL that should be called every time a cronjob completes.

In this guide, we'll cover how you can implement that in your existing Golang code.

Cron job monitoring in generic Golang

You can make use of the net/http library for making network calls.

package main import ( "fmt" "log" "net/http" ) func main() { response, _, err := http.Get("https://ping.ohdear.app/e536e771-9ff6") if err != nil { log.Println('Couldnt ping Oh Dear endpoint') } }

_Note: make sure your script stops executing on error conditions, so the http.Get function isn't called even if the script has failed

Advanced usage

We aim to keep our cron job monitoring as simple to use as possible, but that doesn't mean we don't support some more advanced usage cases.

View our scheduled task API documentation for creating, retrieving and syncing tasks from any application.

Bypassing CDNs or caching layers

Our default usage suggests using a GET method to ping your cron URL, to let us know your cron job ran on time. In some cases, this may not work as intended because of proxies or middleware between your servers and our endpoint.

If you have a caching layer in between, subsequent GET calls may be returned by your proxy instead of our system, and we'd never see the pingback.

If that is the case, you can modify your code to perform a POST call to us, instead. This can be done as follows:

curl -X POST --retry 3 https://ping.ohdear.app/e536e771-9ff6

Note the addition of the -X POST parameter.

Any proxy or caching layer should always let POST calls be sent to our endpoint, these should never be cached.

Providing memory usage, script duration and exit codes

Our Ping URL has support for providing the total memory consumption and the duration of your script, as optional parameters.

To send this data along, you can change the pingback URL to a POST call with a payload of memory, runtime, exit_code or failure_message formatted as a plain form submission.

That sounds complex, so here's an example implemented in curl:

$ curl -X POST https://ping.ohdear.app/e536e771-9ff6 \
    -F 'memory=29360128' \
    -F 'runtime=0.25' \
    -F 'exit_code=0' \
    -F 'failure_message="Everything ran successfully (exit_code = 0)"'

You provide the form fields using the -F option parameter to curl.

The data should be provided as:

  • memory: numeric, the total memory consumption of your cron job, measured in bytes (in the example above, the script used 28MB of memory)
  • runtime: numeric, the total duration of your cron job, measured in seconds (in this example: 0.25 seconds)
  • exit_code: numeric, the exit code of your script. A value of 0 means your script executed successfully.
  • failure_message: string, a text-version (human readable) for why the script has failed. This can be your debug information. Max 255 characters.

You can choose to pass along just one of these items or all of them at once:

$ curl -X POST https://ping.ohdear.app/e536e771-9ff6 \
    -F 'memory=29360128' \
    -F 'runtime=0.25'

Every payload field is entirely optional.

Starting and finishing jobs

We also support /starting and /finished tasks to help identify issues and runtime without sending additional POST parameters.

A starting ping will not reset your fixed frequency or cron-based check period.

Providing active callbacks for failure states

Our default method of operating is to send you a notification when we have not received a pingback to your unique URL on time.

There are 2 ways you can provide an active callback to us that report the cron job has failed.

This has the benefit that we don't have to wait for the frequency or grace time to expire, we can fire notifications directly when we receive a failure confirmation from your scripts.

Reporting failure via a simple GET call

Every ping URL you see in your Oh Dear account can have the /failed path appended to it.

If that URL receives a ping, we consider it a confirmation from your end that your script has failed and we'll send out the alert to your notification channels.

Take this as an example:

curl https://ping.ohdear.app/e536e771-9ff6/failed

By adding the /failed path to the end of the ping URL, you can confirm us that this particular cron job has failed.

You can also optionally make this a POST call with the same meta data as runtime, memory and failure_message.

$ curl -X POST https://ping.ohdear.app/e536e771-9ff6/failed \
    -F 'memory=29360128' \
    -F 'runtime=0.25' \
    -F 'exit_code=3' \
    -F 'failure_message="Oh Dear, something went wrong"'

These extra parameters are entirely optional.

Reporting failure with details through a POST call

You can also perform a POST call to your endpoint with a non-zero exit_code to let us know your script has failed.

This way, you can do a pingback to us and use the exit-code in your script to let us know the state of your cron jobs. Additionally, you can provide memory and runtime information as well (see above).

To do so, implement the following API call to your pingback URL.

$ curl -X POST https://ping.ohdear.app/e536e771-9ff6 \
    -F 'exit_code=1'

The exit_code parameter should be an integer (numeric) value. A value of 0 means the script exited correctly, and we interpret that as a success state.

Any non-zero value submitted back to us will be interpreted as a failed job, and will lead to notifications being sent.

Was this page helpful?

Feel free to reach out via support@ohdear.app or on Twitter via @OhDearApp if you have any other questions. We'd love to help!