Skip to content

Monitor Azure Functions timer triggers

A timer-triggered function runs with no server to watch. When it starts throwing, times out, or the function app is stopped, nothing tells you unless you’ve set up alerts in Azure Monitor. A heartbeat check is a simpler net: the function reports to Pingstack after its work succeeds, and Pingstack alerts you when that report doesn’t arrive on time.

1. Create a heartbeat check that matches the schedule

Section titled “1. Create a heartbeat check that matches the schedule”

Azure Functions timers use NCRONTAB expressions with six fields, starting with seconds:

0 0 2 * * *

Pingstack uses standard five-field cron. Drop the seconds field:

Azure Functions Pingstack
0 0 2 * * * 0 2 * * *
0 30 6 * * 1-5 30 6 * * 1-5
0 */15 * * * * */15 * * * *

Create a heartbeat check with the converted schedule. Timers run in UTC unless the app sets the WEBSITE_TIME_ZONE app setting, which isn’t available on every hosting plan. Choose the same timezone in Pingstack. See schedules and timezones.

Set a grace period that covers the function’s runtime plus cold start. Attach a notification group.

Copy the location’s ping URL from the check in Pingstack. Add it to the function app’s Settings › Environment variables as PINGSTACK_PING_URL, or store it in Key Vault and reference it from the setting with @Microsoft.KeyVault(SecretUri=...).

3. Report after the function’s work succeeds

Section titled “3. Report after the function’s work succeeds”
public class NightlyReport(IReportService reports, IHttpClientFactory httpFactory, ILogger<NightlyReport> log)
{
[Function("NightlyReport")]
public async Task Run([TimerTrigger("0 0 2 * * *")] TimerInfo timer)
{
await reports.SendNightlyAsync();
var url = Environment.GetEnvironmentVariable("PINGSTACK_PING_URL");
if (string.IsNullOrEmpty(url)) return;
try
{
var http = httpFactory.CreateClient();
http.Timeout = TimeSpan.FromSeconds(10);
(await http.GetAsync(url)).EnsureSuccessStatusCode();
}
catch (Exception e) when (e is HttpRequestException or TaskCanceledException)
{
log.LogWarning("Pingstack heartbeat failed: {Error}", e.GetType().Name);
}
}
}
const { app } = require('@azure/functions');
app.timer('nightlyReport', {
schedule: '0 0 2 * * *',
handler: async (timer, context) => {
await sendNightlyReport();
try {
await fetch(process.env.PINGSTACK_PING_URL, { signal: AbortSignal.timeout(10_000) });
} catch (error) {
context.warn(`Pingstack heartbeat failed: ${error.name}`);
}
},
});

The report runs only after the work completes, so a run that throws sends nothing and Pingstack alerts you when the deadline passes.

In the Azure portal, open the function and choose Test/Run, then Run. Open the check in Pingstack and confirm the location received a heartbeat and shows a next deadline.

Append a count the function produces as a numeric value, for example ?value=42 on the ping URL, and set warning and critical thresholds on the check.

  • Stopped app. A stopped function app or a disabled function runs nothing. Pingstack alerts, which is usually what you want.
  • Timeouts. A function that exceeds its plan’s timeout is stopped before it reports. Raise functionTimeout in host.json or split the work.
  • Several instances. Timer triggers run on one instance at a time, but a long run that overlaps the next schedule can delay it.
  • Timezone mismatch. Without WEBSITE_TIME_ZONE, timers run in UTC.

If alerts still don’t match what you expect, see troubleshooting monitoring.