Cron job monitoring can be tricky, mainly because they do not work as a regular network monitors where there is a webserver exposing a port. This is why there is a special monitor type called Heartbeat.
heartbeat works like a “pulse” from the server, signaling that the cron job is active and running as expected. Each time the job completes a cycle, it sends a “heartbeat” (or “ping”) to uptinio. If the service receives these heartbeats at the expected intervals, everything is operating normally.
However, if a heartbeat is missed—meaning the server or job fails to send the expected signal—this can alert us that there’s an issue. The monitoring service then triggers an alert, allowing us to investigate and resolve the problem before it impacts critical processes.
Heartbeats are especially useful for identifying issues in background jobs that handle essential tasks like data processing, notifications, or backups. By integrating heartbeat monitoring, we can ensure that these jobs run smoothly and address issues proactively.
Setting up your first heartbeat.
-
Log in to uptinio
-
Click on New Monitor
-
Change the Check type to Heartbeat
-
Set a name for your heartbeat, this way it is easier to track
-
Choose any integration you wish to notify if there is an error
-
Set the interval of your background job in minutes. This is how often does your background task runs.
-
Once you submit it, a heartbeat URL will be generated. You will run a GET request on this URL on any background job you have
Samples on different languages
Bash
# Replace <HEARTBEAT_URL> with your heartbeat URL
curl -X GET <HEARTBEAT_URL>
Python
import requests
# Replace <HEARTBEAT_URL> with your heartbeat service URL
response = requests.get("<HEARTBEAT_URL>")
if response.status_code == 200:
print("Heartbeat sent successfully")
else:
print("Failed to send heartbeat")
Ruby
import requests
# Replace <HEARTBEAT_URL> with your heartbeat service URL
response = requests.get("<HEARTBEAT_URL>")
if response.status_code == 200:
print("Heartbeat sent successfully")
else:
print("Failed to send heartbeat")
Javascript
const https = require('https');
// Replace <HEARTBEAT_URL> with your heartbeat service URL
https.get('<HEARTBEAT_URL>', (res) => {
if (res.statusCode === 200) {
console.log('Heartbeat sent successfully');
} else {
console.log('Failed to send heartbeat');
}
}).on('error', (e) => {
console.error(`Error: ${e.message}`);
});
C
#include <stdio.h>
#include <curl/curl.h>
int main() {
CURL *curl = curl_easy_init();
if(curl) {
curl_easy_setopt(curl, CURLOPT_URL, "<HEARTBEAT_URL>");
CURLcode res = curl_easy_perform(curl);
if(res == CURLE_OK) {
printf("Heartbeat sent successfully\n");
} else {
fprintf(stderr, "Failed to send heartbeat: %s\n", curl_easy_strerror(res));
}
curl_easy_cleanup(curl);
}
return 0;
}
C++
#include <iostream>
#include <curl/curl.h>
int main() {
CURL *curl = curl_easy_init();
if(curl) {
curl_easy_setopt(curl, CURLOPT_URL, "<HEARTBEAT_URL>");
CURLcode res = curl_easy_perform(curl);
if(res == CURLE_OK) {
std::cout << "Heartbeat sent successfully" << std::endl;
} else {
std::cerr << "Failed to send heartbeat: " << curl_easy_strerror(res) << std::endl;
}
curl_easy_cleanup(curl);
}
return 0;
}
Go
package main
import (
"fmt"
"net/http"
)
func main() {
// Replace <HEARTBEAT_URL> with your heartbeat service URL
resp, err := http.Get("<HEARTBEAT_URL>")
if err != nil {
fmt.Println("Failed to send heartbeat:", err)
return
}
defer resp.Body.Close()
if resp.StatusCode == http.StatusOK {
fmt.Println("Heartbeat sent successfully")
} else {
fmt.Println("Failed to send heartbeat, status code:", resp.StatusCode)
}
}
Rust
use reqwest;
#[tokio::main]
async fn main() {
// Replace <HEARTBEAT_URL> with your heartbeat service URL
let url = "<HEARTBEAT_URL>";
match reqwest::get(url).await {
Ok(response) if response.status().is_success() => {
println!("Heartbeat sent successfully");
}
Ok(response) => {
println!("Failed to send heartbeat, status code: {}", response.status());
}
Err(e) => {
println!("Failed to send heartbeat: {}", e);
}
}
}