diff --git a/templates/docs/api.html b/templates/docs/api.html index 3c3d2554..8583b8ee 100644 --- a/templates/docs/api.html +++ b/templates/docs/api.html @@ -113,12 +113,12 @@ specified value.

The API key is either missing or invalid.

Example Request

-
curl --header "X-Api-Key: your-api-key" SITE_ROOT/api/v1/checks/
-
+
curl --header "X-Api-Key: your-api-key" SITE_ROOT/api/v1/checks/
+

Example Response

-
{
+
{
   "checks": [
     {
       "name": "Filesystem Backup",
@@ -155,13 +155,13 @@ specified value.

} ] } -
+

When using the read-only API key, the following fields are omitted: ping_url, update_url, pause_url, channels. An extra unique_key field is added which can be used to GET a check in place of the UUID. The unique_key identifier is stable across API calls. Example:

-
{
+
{
   "checks": [
     {
       "name": "Filesystem Backup",
@@ -192,7 +192,7 @@ is added which can be used to GET a check
     }
   ]
 }
-
+

Get a Single Check

@@ -213,12 +213,12 @@ using the read-only API key) as an identifier.

The specified check does not exist.

Example Request

-
curl --header "X-Api-Key: your-api-key" SITE_ROOT/api/v1/checks/<uuid>
-
+
curl --header "X-Api-Key: your-api-key" SITE_ROOT/api/v1/checks/<uuid>
+

Example Response

-
{
+
{
   "name": "Database Backup",
   "tags": "production db",
   "desc": "Runs ~/db-backup.sh",
@@ -235,7 +235,7 @@ using the read-only API key) as an identifier.

"schedule": "15 5 * * *", "tz": "UTC" } -
+

Example Read-Only Response

@@ -245,7 +245,7 @@ added. This identifier is stable across API calls.

Note: the ping_url, update_url and pause_url fields, although omitted, are not really secret. The client already knows the check's unique UUID and so can easily construct these URLs by itself.

-
{
+
{
   "name": "Database Backup",
   "tags": "production db",
   "desc": "Runs ~/db-backup.sh",
@@ -259,7 +259,7 @@ construct these URLs by itself.

"schedule": "15 5 * * *", "tz": "UTC" } -
+

Create a Check

@@ -371,20 +371,20 @@ field values. the limit is 20 checks per account.

Example Request

-
curl SITE_ROOT/api/v1/checks/ \
+
curl SITE_ROOT/api/v1/checks/ \
     --header "X-Api-Key: your-api-key" \
     --data '{"name": "Backups", "tags": "prod www", "timeout": 3600, "grace": 60}'
-
+

Or, alternatively:

-
curl SITE_ROOT/api/v1/checks/ \
+
curl SITE_ROOT/api/v1/checks/ \
     --data '{"api_key": "your-api-key", "name": "Backups", "tags": "prod www", "timeout": 3600, "grace": 60}'
-
+

Example Response

-
{
+
{
   "channels": "",
   "desc": "",
   "grace": 60,
@@ -400,7 +400,7 @@ the limit is 20 checks per account.
   "timeout": 3600,
   "update_url": "SITE_ROOT/api/v1/checks/f618072a-7bde-4eee-af63-71a77c5723bc",
 }
-
+

Update an Existing Check

@@ -495,20 +495,20 @@ field values.
The specified check does not exist.

Example Request

-
curl SITE_ROOT/api/v1/checks/f618072a-7bde-4eee-af63-71a77c5723bc \
+
curl SITE_ROOT/api/v1/checks/f618072a-7bde-4eee-af63-71a77c5723bc \
     --header "X-Api-Key: your-api-key" \
     --data '{"name": "Backups", "tags": "prod www", "timeout": 3600, "grace": 60}'
-
+

Or, alternatively:

-
curl SITE_ROOT/api/v1/checks/f618072a-7bde-4eee-af63-71a77c5723bc \
+
curl SITE_ROOT/api/v1/checks/f618072a-7bde-4eee-af63-71a77c5723bc \
     --data '{"api_key": "your-api-key", "name": "Backups", "tags": "prod www", "timeout": 3600, "grace": 60}'
-
+

Example Response

-
{
+
{
   "channels": "",
   "desc": "",
   "grace": 60,
@@ -524,7 +524,7 @@ field values.
   "timeout": 3600,
   "update_url": "SITE_ROOT/api/v1/checks/f618072a-7bde-4eee-af63-71a77c5723bc",
 }
-
+

Pause Monitoring of a Check

@@ -544,16 +544,16 @@ state. You can resume monitoring of the check by pinging it.

The specified check does not exist.

Example Request

-
curl SITE_ROOT/api/v1/checks/0c8983c9-9d73-446f-adb5-0641fdacc9d4/pause \
+
curl SITE_ROOT/api/v1/checks/0c8983c9-9d73-446f-adb5-0641fdacc9d4/pause \
     --request POST --header "X-Api-Key: your-api-key" --data ""
-
+

Note: the --data "" argument forces curl to send a Content-Length request header even though the request body is empty. For HTTP POST requests, the Content-Length header is sometimes required by some network proxies and web servers.

Example Response

-
{
+
{
   "channels": "",
   "desc": "",
   "grace": 60,
@@ -569,7 +569,7 @@ header is sometimes required by some network proxies and web servers.

"timeout": 3600, "update_url": "SITE_ROOT/api/v1/checks/f618072a-7bde-4eee-af63-71a77c5723bc" } -
+

Delete Check

@@ -589,13 +589,13 @@ check that was just deleted.

The specified check does not exist.

Example Request

-
curl SITE_ROOT/api/v1/checks/f618072a-7bde-4eee-af63-71a77c5723bc \
+
curl SITE_ROOT/api/v1/checks/f618072a-7bde-4eee-af63-71a77c5723bc \
     --request DELETE --header "X-Api-Key: your-api-key"
-
+

Example Response

-
{
+
{
   "channels": "",
   "desc": "",
   "grace": 60,
@@ -611,7 +611,7 @@ check that was just deleted.

"timeout": 3600, "update_url": "SITE_ROOT/api/v1/checks/f618072a-7bde-4eee-af63-71a77c5723bc", } -
+

Get a list of check's logged pings

@@ -632,13 +632,13 @@ number of returned pings depends on account's billing plan: 100 for free account
The specified check does not exist.

Example Request

-
curl SITE_ROOT/api/v1/checks/f618072a-7bde-4eee-af63-71a77c5723bc/pings/ \
+
curl SITE_ROOT/api/v1/checks/f618072a-7bde-4eee-af63-71a77c5723bc/pings/ \
     --header "X-Api-Key: your-api-key"
-
+

Example Response

-
{
+
{
   "pings": [
     {
       "type": "success",
@@ -680,7 +680,7 @@ number of returned pings depends on account's billing plan: 100 for free account
     }
   ]
 }
-
+

Get a list of check's status changes

@@ -723,13 +723,13 @@ number of returned pings depends on account's billing plan: 100 for free account
The specified check does not exist.

Example Request

-
curl SITE_ROOT/api/v1/checks/f618072a-7bde-4eee-af63-71a77c5723bc/flips/ \
+
curl SITE_ROOT/api/v1/checks/f618072a-7bde-4eee-af63-71a77c5723bc/flips/ \
     --header "X-Api-Key: your-api-key"
-
+

Example Response

-
[
+
[
     {
       "timestamp": "2020-03-23T10:18:23+00:00",
       "up": 1
@@ -743,7 +743,7 @@ number of returned pings depends on account's billing plan: 100 for free account
       "up": 1
     }
 ]
-
+

Get a List of Existing Integrations

@@ -757,12 +757,12 @@ number of returned pings depends on account's billing plan: 100 for free account
The API key is either missing or invalid.

Example Request

-
curl --header "X-Api-Key: your-api-key" SITE_ROOT/api/v1/channels/
-
+
curl --header "X-Api-Key: your-api-key" SITE_ROOT/api/v1/channels/
+

Example Response

-
{
+
{
   "channels": [
     {
       "id": "4ec5a071-2d08-4baa-898a-eb4eb3cd6941",
@@ -776,4 +776,4 @@ number of returned pings depends on account's billing plan: 100 for free account
     }
   ]
 }
-
\ No newline at end of file +
\ No newline at end of file diff --git a/templates/docs/attaching_logs.html b/templates/docs/attaching_logs.html index 75e8876b..65dd7b2a 100644 --- a/templates/docs/attaching_logs.html +++ b/templates/docs/attaching_logs.html @@ -6,17 +6,17 @@ the request body, so you can inspect it later.

Logging Command Output

In this example, we run certbot renew, capture its output, and submit the captured output to SITE_NAME:

-
#!/bin/sh
+
#!/bin/sh
 
 m=$(/usr/bin/certbot renew 2>&1)
 curl -fsS --retry 3 --data-raw "$m" PING_URL
-
+

In Combination with the /fail Endpoint

We can extend the previous example and signal either success or failure depending on the exit code:

-
#!/bin/sh
+
#!/bin/sh
 
 url=PING_URL
 
@@ -24,11 +24,11 @@ depending on the exit code:

if [ $? -ne 0 ]; then url=$url/fail; fi curl -fsS --retry 3 --data-raw "$m" $url -
+

All in One Line

Finally, all of the above can be packaged in a single line. The one-line version can be put directly in crontab, without using a wrapper script.

-
m=$(/usr/bin/certbot renew 2>&1); curl -fsS --data-raw "$m" "PING_URL$([ $? -ne 0 ] && echo -n /fail)"
-
\ No newline at end of file +
m=$(/usr/bin/certbot renew 2>&1); curl -fsS --data-raw "$m" "PING_URL$([ $? -ne 0 ] && echo -n /fail)"
+
\ No newline at end of file diff --git a/templates/docs/bash.html b/templates/docs/bash.html index 6d31cd7b..4c41a2bc 100644 --- a/templates/docs/bash.html +++ b/templates/docs/bash.html @@ -4,7 +4,7 @@ have to do is make a HTTP request at the end of the script. curl and wget are two common command line HTTP clients you can use.

-
# Sending a HTTP GET request with curl:
+
# Sending a HTTP GET request with curl:
 curl --retry 3 PING_URL
 
 # Silent version (no stdout/stderr output unless curl hits an error):
@@ -12,7 +12,7 @@ curl -fsS --retry 3 PING_URL
 
 # Sending a HTTP GET request with wget:
 wget PING_URL -O /dev/null
-
+

Signalling Failure from Shell Scripts

@@ -23,13 +23,13 @@ signal a failure. The below example:

  • if the certbot command is successful (exit code 0), send HTTP GET to PING_URL
  • otherwise, send HTTP GET to PING_URL/fail
  • -
    #!/bin/sh
    +
    #!/bin/sh
     
     # Payload here:
     /usr/bin/certbot renew
     # Ping SITE_NAME
     curl --retry 3 "PING_URL$([ $? -ne 0 ] && echo -n /fail)"
    -
    +

    Logging Command Output

    @@ -37,11 +37,11 @@ curl --retry 3 "PING_URL

    In the below example, certbot's output is captured and submitted via HTTP POST:

    -
    #!/bin/sh
    +
    #!/bin/sh
     
     m=$(/usr/bin/certbot renew 2>&1)
     curl -fsS --retry 3 --data-raw "$m" PING_URL
    -
    +

    Auto-provisioning New Checks

    @@ -49,7 +49,7 @@ curl -fsS --retry 3 --data-raw " -
    #!/bin/bash
    +
    #!/bin/bash
     
     API_KEY=your-api-key-here
     
    @@ -62,4 +62,4 @@ register with SITE_NAME the first time they run.

    # Finally, send a ping: curl --retry 3 $URL -
    \ No newline at end of file +
    \ No newline at end of file diff --git a/templates/docs/cloning_checks.html b/templates/docs/cloning_checks.html index 8206e999..83598075 100644 --- a/templates/docs/cloning_checks.html +++ b/templates/docs/cloning_checks.html @@ -16,7 +16,7 @@ an existing deployment in a new region. The SITE_NAME web interface does not have a function to clone an entire project, but this can be done relatively easily using the Management API calls. Below is an example using Python and the requests library:

    -
    import requests
    +
    import requests
     
     API_URL = "SITE_ROOT/api/v1/checks/"
     SOURCE_PROJECT_READONLY_KEY = "..."
    @@ -24,6 +24,6 @@ and the requests library:

    r = requests.get(API_URL, headers={"X-Api-Key": SOURCE_PROJECT_READONLY_KEY}) for check in r.json()["checks"]: - print("Cloning %s" % check["name"]) + print("Cloning %s" % check["name"]) requests.post(API_URL, json=check, headers={"X-Api-Key": TARGET_PROJECT_KEY}) -
    \ No newline at end of file +
    \ No newline at end of file diff --git a/templates/docs/configuring_prometheus.html b/templates/docs/configuring_prometheus.html new file mode 100644 index 00000000..31c8ce80 --- /dev/null +++ b/templates/docs/configuring_prometheus.html @@ -0,0 +1,20 @@ +

    Configuring Prometheus

    +

    Healthchecks.io supports exporting metrics and check statuses to Prometheus, for use with Grafana.

    +

    You can generate the metrics export endpoint by going to your project settings (last tab up top) and clicking "Create API Keys". You will then see the link to the prometheus endpoint, which looks like this:

    +
    https://healthchecks.io/projects/45sd78-eeee-dddd-8888-b25a9887ecfd/metrics/NXyGzks4s8xcF1J-wzoaioyoqXIANGD0
    +
    + + +

    Update the prometheus.yml

    +

    You can take that link and add it to the prometheus config:

    +
      - job_name: "healthchecks"
    +    scrape_interval: 60s
    +    scheme: https
    +    metrics_path: /projects/45sd78-eeee-dddd-8888-b25a9887ecfd/metrics/NXyGzks4s8xcF1J-wzoaioyoqXIANGD0
    +    static_configs:
    +      - targets: ["healthchecks.io"]
    +
    + + +

    Notice how we split up the URL and paste in the scheme, domain, and path separately.

    +

    Reload promethus and your changes should be live, coming in under the hc_ prefix.

    \ No newline at end of file diff --git a/templates/docs/csharp.html b/templates/docs/csharp.html index 270612a2..ebfb87c6 100644 --- a/templates/docs/csharp.html +++ b/templates/docs/csharp.html @@ -1,7 +1,7 @@

    C

    Below is an example of making a HTTP request to SITE_NAME from C#.

    -
    using (var client = new System.Net.WebClient())
    +
    using (var client = new System.Net.WebClient())
     {
            client.DownloadString("PING_URL");
     }
    -
    \ No newline at end of file +
    \ No newline at end of file diff --git a/templates/docs/http_api.html b/templates/docs/http_api.html index 59550d10..40625c65 100644 --- a/templates/docs/http_api.html +++ b/templates/docs/http_api.html @@ -15,20 +15,20 @@ If the request body looks like a UTF-8 string, SITE_NAME stores the request body

    Successful responses will have the "200 OK" HTTP response status code and a short and simple string "OK" in the response body.

    Signal Success ("ping")

    -
    HEAD|GET|POST PING_ENDPOINT{uuid}
    -
    +
    HEAD|GET|POST PING_ENDPOINT{uuid}
    +

    Signals to SITE_NAME that the job has completed successfully (or, for continuously running processes, is still running and healthy). The uuid parameter is unique for each check.

    Example

    -
    GET /5bf66975-d4c7-4bf5-bcc8-b8d8a82ea278 HTTP/1.0
    +
    GET /5bf66975-d4c7-4bf5-bcc8-b8d8a82ea278 HTTP/1.0
     Host: hc-ping.com
    -
    +
    -
    HTTP/1.1 200 OK
    +
    HTTP/1.1 200 OK
     Server: nginx
     Date: Wed, 29 Jan 2020 09:58:23 GMT
     Content-Type: text/plain; charset=utf-8
    @@ -37,23 +37,23 @@ is unique for each check.

    Access-Control-Allow-Origin: * OK -
    +

    Signal Failure

    -
    HEAD|GET|POST PING_ENDPOINT{uuid}/fail
    -
    +
    HEAD|GET|POST PING_ENDPOINT{uuid}/fail
    +

    Signals to SITE_NAME that the job has failed. Actively signalling a failure minimizes the delay from your monitored service failing to you receiving an alert.

    Example

    -
    GET /5bf66975-d4c7-4bf5-bcc8-b8d8a82ea278/fail HTTP/1.0
    +
    GET /5bf66975-d4c7-4bf5-bcc8-b8d8a82ea278/fail HTTP/1.0
     Host: hc-ping.com
    -
    +
    -
    HTTP/1.1 200 OK
    +
    HTTP/1.1 200 OK
     Server: nginx
     Date: Wed, 29 Jan 2020 09:58:23 GMT
     Content-Type: text/plain; charset=utf-8
    @@ -62,12 +62,12 @@ minimizes the delay from your monitored service failing to you receiving an aler
     Access-Control-Allow-Origin: *
     
     OK
    -
    +

    Signal a Start

    -
    HEAD|GET|POST PING_ENDPOINT{uuid}/start
    -
    +
    HEAD|GET|POST PING_ENDPOINT{uuid}/start
    +

    Sends a "job has started!" message to SITE_NAME. This is @@ -77,12 +77,12 @@ optional but enables a few extra features:

  • SITE_NAME will detect if the job runs longer than its configured grace time
  • Example

    -
    GET /5bf66975-d4c7-4bf5-bcc8-b8d8a82ea278/start HTTP/1.0
    +
    GET /5bf66975-d4c7-4bf5-bcc8-b8d8a82ea278/start HTTP/1.0
     Host: hc-ping.com
    -
    +
    -
    HTTP/1.1 200 OK
    +
    HTTP/1.1 200 OK
     Server: nginx
     Date: Wed, 29 Jan 2020 09:58:23 GMT
     Content-Type: text/plain; charset=utf-8
    @@ -91,4 +91,4 @@ optional but enables a few extra features:

    Access-Control-Allow-Origin: * OK -
    \ No newline at end of file +
    \ No newline at end of file diff --git a/templates/docs/javascript.html b/templates/docs/javascript.html index 4e0e1c3c..2dd7ee40 100644 --- a/templates/docs/javascript.html +++ b/templates/docs/javascript.html @@ -1,13 +1,13 @@

    Javascript

    Below is an example of making a HTTP request to SITE_NAME from Node.js.

    -
    var https = require('https');
    +
    var https = require('https');
     https.get("PING_URL");
    -
    +

    You can also send pings from a browser environment. SITE_NAME sets the Access-Control-Allow-Origin:* CORS header, so cross-domain AJAX requests work.

    -
    var xhr = new XMLHttpRequest();
    +
    var xhr = new XMLHttpRequest();
     xhr.open('GET', 'PING_URL', true);
     xhr.send(null);
    -
    \ No newline at end of file +
    \ No newline at end of file diff --git a/templates/docs/measuring_script_run_time.html b/templates/docs/measuring_script_run_time.html index 5217d455..a957de54 100644 --- a/templates/docs/measuring_script_run_time.html +++ b/templates/docs/measuring_script_run_time.html @@ -7,7 +7,7 @@

    Signalling a start kicks off a separate timer: the job now must signal a success within its configured "Grace Time", or it will get marked as "down".

    Below is a code example in Python:

    -
    import requests
    +
    import requests
     URL = "PING_URL"
     
     
    @@ -23,11 +23,11 @@ success within its configured "Grace Time", or it will get marked as "down".

    # TODO: run the job here fib = lambda n: n if n < 2 else fib(n - 1) + fib(n - 2) -print("F(42) = %d" % fib(42)) +print("F(42) = %d" % fib(42)) # Signal success: requests.get(URL) -
    +

    Viewing Measured Run Times

    diff --git a/templates/docs/monitoring_cron_jobs.html b/templates/docs/monitoring_cron_jobs.html index c2051859..ba63c2c7 100644 --- a/templates/docs/monitoring_cron_jobs.html +++ b/templates/docs/monitoring_cron_jobs.html @@ -3,10 +3,10 @@ update your cron job command to send a HTTP request to SITE_NAME after a job completes.

    Let's look at an example:

    -
    $ crontab -l
    +
    $ crontab -l
     # m h dom mon dow command
       8 6 * * * /home/user/backup.sh
    -
    +

    The above job runs /home/user/backup.sh every day at 6:08. The backup @@ -40,10 +40,10 @@ increasingly important as you add more checks to your account.

    Finally, edit your cron job definition and append a curl or wget call after the command:

    -
    $ crontab -e
    +
    $ crontab -e
     # m h dom mon dow command
       8 6 * * * /home/user/backup.sh && curl -fsS --retry 3 -o /dev/null PING_URL
    -
    +

    Now, each time your cron job runs, it will send a HTTP request to the ping URL. @@ -101,7 +101,7 @@ there is an error. Feel free to adjust the curl options to suit your needs.

    Looking up Your Machine's Time Zone

    On modern GNU/Linux systems, you can look up the time zone using the timedatectl status command and looking for "Time zone" in its output:

    -
    $ timedatectl status
    +
    $ timedatectl status
     
                    Local time: C  2020-01-23 12:35:50 EET
                Universal time: C  2020-01-23 10:35:50 UTC
    @@ -110,4 +110,4 @@ there is an error. Feel free to adjust the curl options to suit your needs.

    System clock synchronized: yes NTP service: active RTC in local TZ: no -
    \ No newline at end of file +
    \ No newline at end of file diff --git a/templates/docs/php.html b/templates/docs/php.html index b7c3bfbe..0901a278 100644 --- a/templates/docs/php.html +++ b/templates/docs/php.html @@ -1,4 +1,4 @@

    PHP

    Below is an example of making a HTTP request to SITE_NAME from PHP.

    -
    file_get_contents('https://hc-ping.com/your-uuid-here');
    -
    \ No newline at end of file +
    file_get_contents('https://hc-ping.com/your-uuid-here');
    +
    \ No newline at end of file diff --git a/templates/docs/powershell.html b/templates/docs/powershell.html index 65156c33..f14dfe4b 100644 --- a/templates/docs/powershell.html +++ b/templates/docs/powershell.html @@ -5,19 +5,19 @@

    Here is a simple PowerShell script that pings SITE_NAME. When scheduled to run with Task Scheduler, it will essentially just send regular "I'm alive" messages. You can of course extend it to do more things.

    -
    # inside a PowerShell script:
    +
    # inside a PowerShell script:
     Invoke-RestMethod PING_URL
    -
    +

    Save the above to e.g. C:\Scripts\healthchecks.ps1. Then use the following command in a Scheduled Task to run the script:

    -
    powershell.exe -ExecutionPolicy bypass -File C:\Scripts\healthchecks.ps1
    -
    +
    powershell.exe -ExecutionPolicy bypass -File C:\Scripts\healthchecks.ps1
    +

    In simple cases, you can also pass the script to PowerShell directly, using the "-command" argument:

    -
    # Without an underlying script, passing the command to PowerShell directly:
    +
    # Without an underlying script, passing the command to PowerShell directly:
     powershell.exe -command &{Invoke-RestMethod PING_URL}
    -
    \ No newline at end of file +
    \ No newline at end of file diff --git a/templates/docs/python.html b/templates/docs/python.html index be16fdc0..f5ff16b1 100644 --- a/templates/docs/python.html +++ b/templates/docs/python.html @@ -1,26 +1,26 @@

    Python

    If you are already using the requests library, it's convenient to also use it here:

    -
    # using requests:
    +
    # using requests:
     import requests
     requests.get("PING_URL")
    -
    +

    Otherwise, you can use the urllib standard module.

    -
    # urllib with python 3.x:
    +
    # urllib with python 3.x:
     import urllib.request
     urllib.request.urlopen("PING_URL")
    -
    +
    -
    # urllib with python 2.x:
    +
    # urllib with python 2.x:
     import urllib
     urllib.urlopen("PING_URL")
    -
    +

    You can include additional diagnostic information in the in the request body (for POST requests):

    -
    # Passing diagnostic information in the POST body:
    +
    # Passing diagnostic information in the POST body:
     import requests
     requests.post("PING_URL", data="temperature=-7")
    -
    \ No newline at end of file +
    \ No newline at end of file diff --git a/templates/docs/ruby.html b/templates/docs/ruby.html index 25070483..e73e6b57 100644 --- a/templates/docs/ruby.html +++ b/templates/docs/ruby.html @@ -1,7 +1,7 @@

    Ruby

    Below is an example of making a HTTP request to SITE_NAME from Ruby.

    -
    require 'net/http'
    +
    require 'net/http'
     require 'uri'
     
     Net::HTTP.get(URI.parse('PING_URL'))
    -
    \ No newline at end of file +
    \ No newline at end of file diff --git a/templates/docs/signalling_failures.html b/templates/docs/signalling_failures.html index f5161d74..fdd9a180 100644 --- a/templates/docs/signalling_failures.html +++ b/templates/docs/signalling_failures.html @@ -6,7 +6,7 @@ to you getting a notification.

    Shell Scripts

    The below shell script sends either a "success" or "failure" ping depending on command's (certbot in this example) exit code:

    -
    #!/bin/sh
    +
    #!/bin/sh
     
     url=PING_URL
     
    @@ -14,26 +14,26 @@ command's (certbot in this example) exit code:

    if [ $? -ne 0 ]; then url=$url/fail; fi curl --retry 3 $url -
    +

    Python

    Below is a skeleton code example in Python which signals a failure when the work function returns an unexpected value or throws an exception:

    -
    import requests
    +
    import requests
     URL = "PING_URL"
     
     def do_work():
         # Do your number crunching, backup dumping, newsletter sending work here.
         # Return a truthy value on success.
         # Return a falsy value or throw an exception on failure.
    -    return True
    +    return True
     
    -success = False
    +success = False
     try:
         success = do_work()
     finally:
         # On success, requests PING_URL
         # On failure, requests PING_URL/fail
         requests.get(URL if success else URL + "/fail")
    -
    \ No newline at end of file +
    \ No newline at end of file