Build status NuGet Samples

Logging heartbeats from Hangfire

Scheduling recurring tasks with Hangfire is easy. Monitoring if tasks are successfully executed or even run can be a challenge. With elmah.io Heartbeats, we provide native monitoring of Hangfire recurring tasks.

To publish heartbeats from Hangifre, install the Elmah.Io.Heartbeats.Hangfire NuGet package:

Install-Package Elmah.Io.Heartbeats.Hangfire
dotnet add package Elmah.Io.Heartbeats.Hangfire
<PackageReference Include="Elmah.Io.Heartbeats.Hangfire" Version="5.*" />
paket add Elmah.Io.Heartbeats.Hangfire

For this example, we'll schedule a method named Test to execute every minute:

RecurringJob.AddOrUpdate(() => Test(), Cron.Minutely);

To automatically publish a heartbeat when the job is executed, add the following using:

using Elmah.Io.Heartbeats.Hangfire;

And decorate the Test-method with the ElmahIoHeartbeat attribute:

[ElmahIoHeartbeat("API_KEY", "LOG_ID", "HEARTBEAT_ID")]
public void Test()
{
    // ...
}

Replace API_KEY (Where is my API key?), LOG_ID (Where is my log ID?), and HEARTBEAT_ID with the correct variables from elmah.io.

When the job successfully runs, a Healthy heartbeat is logged to elmah.io. If an exception is thrown an Unhealthy heartbeat is logged. elmah.io will automatically create an error if a heartbeat is missing, as long as the heartbeat is correctly configured as explained in Set up Heartbeats.

Move configuration to config files

You normally don't include your API key, log ID, and heartbeat ID in C# code as shown in the example above. Unfortunately, Hangfire attributes doesn't support dependency injection or configuration from config files. There's a small "hack" that you can use to move the configuration to a configuration file by creating a custom attribute:

using Elmah.Io.Heartbeats.Hangfire;
using Hangfire.Common;
using Hangfire.Server;
using System.Configuration;

public class AppSettingsElmahIoHeartbeatAttribute : JobFilterAttribute, IServerFilter
{
    private readonly ElmahIoHeartbeatAttribute _inner;

    public AppSettingsElmahIoHeartbeatAttribute()
    {
        var apiKey = ConfigurationManager.AppSettings["apiKey"];
        var logId = ConfigurationManager.AppSettings["logId"];
        var heartbeatId = ConfigurationManager.AppSettings["heartbeatId"];
        _inner = new ElmahIoHeartbeatAttribute(apiKey, logId, heartbeatId);
    }

    public void OnPerformed(PerformedContext filterContext)
    {
        _inner.OnPerformed(filterContext);
    }

    public void OnPerforming(PerformingContext filterContext)
    {
        _inner.OnPerforming(filterContext);
    }
}

In the example the AppSettingsElmahIoHeartbeatAttribute class wrap ElmahIoHeartbeatAttribute. By doing so, it is possible to fetch configuration from application settings as part of the constructor. The approach would be similar when using IConfiguration (like in ASP.NET Core), but you will need to share a reference to the configuration object somehow.

To use AppSettingsElmahIoHeartbeatAttribute simply add it to the method:

[AppSettingsElmahIoHeartbeat]
public void Test()
{
    // ...
}

As an alternative, you can register the ElmahIoHeartbeatAttribute as a global attribute. In this example we use IConfiguration in ASP.NET Core to fetch configuration from the appsettings.json file:

public class Startup
{
    public Startup(IConfiguration configuration)
    {
        Configuration = configuration;
    }

    public IConfiguration Configuration { get; }

    // This method gets called by the runtime. Use this method to add services to the container.
    public void ConfigureServices(IServiceCollection services)
    {
        services.AddHangfire(config => config
            // ...
            .UseFilter(new ElmahIoHeartbeatAttribute(
                Configuration["ElmahIo:ApiKey"],
                Configuration["ElmahIo:LogId"],
                Configuration["ElmahIo:HeartbeatId"])));
    }

    // ...
}

This will execute the ElmahIoHeartbeat filter for every Hangfire job which isn't ideal if running multiple jobs within the same project.


This article was brought to you by the elmah.io team. elmah.io is the best error management system for .NET web applications. We monitor your website, alert you when errors start happening, and help you fix errors fast.

See how we can help you monitor your website for crashes Monitor your website