Guide · Serverless
Monitor Azure Functions (timer trigger)
A timer-triggered function can silently stop firing (a bad deploy, a disabled app, an exhausted plan) and nothing tells you. Add one HTTPS call at the end of the handler and Mortemain will.
1. Create a check
Create a check in Mortemain and copy its unique ping URL:
https://ping.mortemain.com/your-check-uuid
2. Ping at the end of the handler (C#)
Call the URL when the function finishes; call /fail from the catch block so an unhandled exception alerts immediately instead of waiting for the next scheduled run:
using System;
using System.Net.Http;
using System.Threading.Tasks;
using Microsoft.Azure.WebJobs;
using Microsoft.Extensions.Logging;
public static class NightlyExport
{
private static readonly HttpClient client = new HttpClient();
private const string PingUrl = "https://ping.mortemain.com/your-check-uuid";
[FunctionName("NightlyExport")]
public static async Task Run(
[TimerTrigger("0 0 3 * * *")] TimerInfo myTimer, ILogger log)
{
try
{
await RunExportAsync(); // your work
await client.GetAsync(PingUrl); // success
}
catch (Exception ex)
{
await client.PostAsync(PingUrl + "/fail",
new StringContent(ex.Message)); // failure, alerts immediately
throw;
}
}
}
3. Same idea in Python
The Python v2 programming model wires up the same pattern with requests:
import azure.functions as func import requests app = func.FunctionApp() PING_URL = "https://ping.mortemain.com/your-check-uuid" @app.timer_trigger(schedule="0 0 3 * * *", arg_name="myTimer", run_on_startup=False, use_monitor=False) def nightly_export(myTimer: func.TimerRequest) -> None: try: run_export() # your work requests.get(PING_URL, timeout=10) # success except Exception: requests.get(f"{PING_URL}/fail", timeout=10) # failure, alerts immediately raise
4. Match the NCRONTAB schedule
Timer triggers use NCRONTAB expressions: six fields ({second} {minute} {hour} {day} {month} {day-of-week}) instead of the usual five, evaluated in UTC unless the app sets WEBSITE_TIME_ZONE. 0 0 3 * * * fires once a day at 03:00 UTC. Give the Mortemain check the same schedule (drop the seconds field) and a grace window that covers your typical run time plus some margin for a cold start on the Consumption plan.
Track duration (optional)
Call /start right as the handler begins and Mortemain records how long each run takes, useful for spotting a job that's quietly getting slower:
await client.GetAsync(PingUrl + "/start"); // marks the run as started
Test it
Trigger the function once (wait for the schedule, run it locally with func start, or use the "Test/Run" panel in the portal). The check flips to up within a second or two of the ping; miss its window and you'll get the down alert. Throw a test exception to confirm the /fail path too.