elmah.io – Error Logging and Health Checks in ASP.NET Core

by | Updated on Jun 20, 2020 | ASP.NET Core

In this article, we will look into features of elmah.io, error logging, and health checks in ASP.NET Core using elmah.io, the steps involved in setting up elmah.io for your ASP.NET Core Application, health monitoring for your Core Applications and much more. The source code is available on my GitHub.

What is elmah.io?

elmah.io is a full-fledged error management system for anything from simple console applications to enterprise-level web applications. To get you guys more excited, elmah.io lets you push the logs of your .NET applications directly to the cloud. This is something really innovative to get started with.

Not only does it handle the error logging part, but it also is hosted and managed completely on the cloud with various features like uptime monitoring of your resources, integrations with other popular error logging frameworks like Serilog / NLog, Realtime notification of occurred errors via mail or other communication channels, quick-fix suggestions directly from StackOverflow. This list of features goes pretty long.

For this article, we will go through the following.

  • Registering on elmah.io and getting your API Keys.
  • Integrating elmah.io Logging with ASP.NET Core.
  • Setting up Health Checks with UI
  • Configuring Heartbeats for elmah.io

Getting your API Keys

In order to log errors to elmah.io from your ASP.NET Core Applications, you will need API Keys. Let’s start by creating a new account at elmah.io. The people at elmah.io offer a generous 21 days Trial to check out their system. Get your FREE trial here.

Error Logging and Health Checks in ASP.NET Core using elmah.io

From there you could sign-up for a new account or use google (and few other external networks) to create a new account with elmah.io. The service mails you the occurred errors to this mail id. Make sure you select your specific timezone while registering. Add your organization name and continue.

thats it 1
waiting

Now what happens is, elmah.io creates a default log container for you into their server. To log errors from an ASP.NET Core Application to this container, you will need to use the API Keys. (I have blurred it out). Let’s use these Keys and setup our actual application over at Visual Studio 2019.

A Small Note on API Keys

API Keys give you complete control over your logs. Now you got to be secured about this. You do not want to share these keys and expose the logs and worst case, manipulation. That is exactly why elmah.io allows you to generate API Keys with specific read/write/delete permissions for each module. Go to the settings of your organization (click on the gear icon next to your organization name) and navigate to the API Keys tab.

settings
aPIKEYS

It’s quite straight forward from here. elmah.io allows you to manage your API Keys and set permissions for each key you generate. This limits the access rights associated with each key.

PERM

Integrating elmah.io Logging with ASP.NET Core

For this demonstration, let’s create a new ASP.NET Core 3.1 WebApi Application. Once that is done, we will install the package required for elmah.io.

Install-Package Elmah.Io.AspNetCore

Next, we will want to add the API Key and Log Id to the startup class and register the elmah.io Service. To keep things secure and clean, we will add the Key and LogId to the appsettings.json file.

Open up your appsettings.json file and add the following. This is where we will add configuration settings related to elmah.io. Replace with your APIKey and LogId.

"ElmahIo": {
  "ApiKey": "<key here>",
  "LogId": "<log id here>",
  "Application": "Elmah.IO.WebApi"
},

Application tag is what elmah.io will use to identify your application. Name it something corresponding to your actual application. Now that we have added the configuration, let’s register elmah.io to the ASP.NET Core Service container.

Navigate to Startup.cs/ConfgireServices method and add in the following.

services.Configure<ElmahIoOptions>(Configuration.GetSection("ElmahIo"));
services.AddElmahIo();

Line #1 – Reads the configuration from our appsettings.json and maps these data to ElmahIoOptions class.

What’s the ElmahIoOptions class? It’s a built-in class that ships with the elmah.io package. You can see the screenshot below.

elmahoptions

Next, navigate to Startup.cs/Configure method and add this line. This registers the elmah.io middleware with the ASP.NET Core Application.

app.UseElmahIo();

That’s it with the setup. Now, just to get started, let’s create a new Empty API Controller to test elmah.io. Name it Controllers/CountController.

This is just an API endpoint to deliberately create errors.

[Route("api/[controller]")]
public class CountController : Controller
{
    [HttpGet]
    public void ErrorThrower()
    {
        int count;
        try
        {
            for (count = 0; count <= 5; count++)
            {
                if (count == 3)
                {
                    throw new Exception($"Random Exception Occured at iteration {count}");
                }
            }
        }
        catch (Exception ex)
        {
            ex.Ship(HttpContext);
        }
    }
}

You may at times need to catch the errors manually to have better control over your application. For this purpose, to log the exception details along with the context data, it is recommended to use e.Ship(HttpContext) – a method that is available with the installed package.

Let’s build the application and run it. To create the error, just navigate to …/api/count. You might have already received a new email by now stating your error and a few other information like the time, application, the exception itself, and so on. Remember that all these work out of the box with minimal configuration upfront. This is what makes elmah.io stand out.

gmail

Email is not the only way to check the log. Let’s login to elmah.io and open up the dashboard.

Exploring elmah.io Dashboard

elmah.io’s dashboard provides quite a rich user experience with all the required information accurately grouped in tabs. The Dashboard shows you the currently active logs. In our case, we just have one Log. Remember Setting up LogId in the appsettings.json? Each log (log container) will have a log id. You can also have a quick glance at the number of errors that occurred for each log.

dashboard

Let’s click on our log container to get the details of the occurred errors. You can notice the segregation between different tabs and also the affected browsers.

overview

We also have a nice bar graph to view the error rate day wise, followed by the most recent, frequent errors along with the most affected URLs (in our case, API endpoints). Let’s click on Total Errors.

graph

Here is a list of all the errors caught by elmah.io. We have a column-wise report along with various filters to pinpoint to a particular error by time, group, or a search string!

errors

By clicking an error message, we get a drill down to more details related to the exception. This is quite similar to the mail that we received earlier.

details

From here you get various options (the bar you have seen on the top-right corner). Here is a brief of what each button does, (listed in order)

  • Fetches quick fixes and suggestions to handle similar errors directly from stack overflow. Neat!
  • Marks the error as fixed.
  • Assigns a bug to a particular user.
  • Get the URL of the specific error.
  • Standard operations (copy / delete).
  • Minimizes the error tab.

Additional Options

elmah.io provides us with events and seamless integration with the default ASP.NET Core Logger as well.

In rare cases, what if an error occurs during logging another error? Here is how you could write the error to the default logger.

services.AddElmahIo(o =>
{
    o.OnError = (message, exception) =>
    {
        logger.LogError(1, exception, "Error during log to elmah.io");
    };
});

There can be cases where you don’t want to log certain types of exception to elmah.io.

services.AddElmahIo(o =>
{
    o.OnFilter = message =>
    {
        return message.Type == "System.NullReferenceException";
    };
});

This makes sure that our ASP.NET Core Application entirely ignores the System.NullReferenceException exception while logging to the elmah.io cloud. There are a couple of more options for which you could refer here.

Health Checks – Overview.

ASP.NET Core provides a middleware that can report the health of our application components. This makes it pretty easy to monitor the status of each component, usually in a microservice architecture. It can test external components like the database server, API endpoints, external services, and can cross-check the integrity and availability of these components. For a highly scaled application, automated traffic monitors can redirect the traffic to the APIs that are healthy. This ensures high uptime for our application.

Health Checks can be configured to a particular endpoint. Once set up, an authenticated user can check the statuses of the linked application by sending a request to this particular health endpoint and receiving the status in a plain text format

What happens when one of your Application components (let’s say an API) is down? And it takes quite a while for you to know of its status? (Because obviously, you wouldn’t be sending a request to the health check endpoint every now and then. ) That would potentially mean a loss of several $$$, right?

Introducing Heartbeats by elmah.io

Now, It’s quite obvious that Healthchecks are quite important for your business/projects to guarantee client satisfaction. Since elmah.io is already a platform to log issues to the cloud, why not integrate the health checks part too? That’s exactly what elmah.io does with their new feature, Heartbeats.

With Heartbeats, you could just configure your ASP.NET Core Application to send you the status reports of the availability of particular resources directly to your mail. Quite convenient, yeah? In the background, your components essentially send a pingback to elmah.io at specific intervals of time. These pingbacks are named Heartbeats.

When there is NO ping from one of your components or the ping contains one or more failed health checks, it means that the service is down or there is some issue in reaching it. elmah.io notifies you about the unavailability of the heartbeat.

Heartbeats is just not for ASP.NET Core Applications. You could also integrate it with Background Job Processors like Hangfire, Worker Services, AWS Lambdas, Azure Functions, and Umbraco.

Setting up Heartbeats with ASP.NET Core

To get a better picture of this feature, let’s try to implement and see it live. I will work on the ASP.NET Core WebAPI project that we have already built earlier.

Install the required package.

Install-Package Elmah.Io.AspNetCore.HealthChecks

elmah.io provides a Heartbeat Id for every application of your with which you track the status. To set up a new HeartbeatId, Open up elmah.io and log in to the dashboard.

Navigate to the Heartbeats (on the top menu).

heartbeat

Let’s create a new Heartbeats Container. Click on the Add Heartbeat button. Give an appropriate name for your new Heartbeat and set up the time interval. The interval ranges from a minute to over a day through which elmah.io checks for your component’s heartbeats. I have set it for a 2-minute interval.

new heartbeat

Ideally, if elmah.io doesn’t receive a heartbeat from my registered API every 2 minutes, I would be notified on the 3rd minute. Let’s see how to implement this.

Now elmah.io provides an id for every heartbeat container. Since we have already created one, here is how to retrieve your heartbeat id.

beat

Click on Instructions. Here is where you can find your Heartbeat Id.

hbid

Before continuing, let’s make sure that our API key has permission to write a new Heartbeat. (PS, this is enabled by default). But let’s just go through it to avoid confusion in the future. Make sure the Heartbeats option is enabled. Save it.

permissions

Let’s start by adding the heartbeat id to our appsettings.json file. Since we have already created an “ElmahIo” element in our appsettings.json, let’s just extend it by adding “Heartbeatid” property and filling it with our actual Heartbeat id. Navigate to appsettings.json.

"ElmahIo": {
  "ApiKey": "<key here>",
  "LogId": "<log id here>",
  "HeartbeatId": "<heart beat id here>",
  "Application": "Elmah.IO.WebApi"
},

Now we will have to bind these configurations into our ASP.NET Core application and map it to a corresponding elmah.io class. Navigate to Startup.cs/ConfigureServices method and add the following.

Make sure to add these lines ABOVE the services.AddElmahIo()

services.Configure<ElmahIoPublisherOptions>(Configuration.GetSection("ElmahIo"));
services.AddHealthChecks().AddElmahIoPublisher();

Build and run your ASP.NET Core Application. Navigate back to the elmah.io Dashboard. You can see that your Heartbeat is quite healthy! By now you would also have received a mail regarding the status. You can also check the history of the heartbeats.

I seriously wonder if any other logging frameworks provide this amount of detailed and practical features with so minimal lines of code and configuration.

api 1
health history 1

With that working as excepted, let’s check what happens if I stop my API from running on the server. Stop the Project on your Visual Studio. We except some kind of notification within 3 minutes of API unavailability. Try to refresh the Heartbeats History in about 3-4 minutes.

missing heartbeat

You can see that we are missing the heartbeat. Instantly, you will also be receiving an email notification from elmah.io. I can’t start imagining how helpful these features would be for mid to enterprise-level applications.

mail missing heartbeat

Additional Heartbeat Options.

Similar to the general logging, Heartbeats too have some neat additional options while registering in the service container. The one approach that is quite is handy is to ignore heartbeats if they are hosted on to localhost or staging. You can do this by adding a simple heartbeat id check before registering the Heartbeat publisher. It would go somewhat like this.

if (!string.IsNullOrWhiteSpace(Configuration["ElmahIo:HeartbeatId"]))
{
    services.AddHealthChecks().AddElmahIoPublisher();
}

Summary

We have gone in-depth about the basics of elmah.io, it’s integration with ASP.NET Core Applications, Error Logging to the cloud, Health checks, and Heartbeat monitoring, and much more. View the source code at my Github. Get your free trial here. Do you have experience working with this tool in your projects? Leave your feedback and suggestions in the comment section below. Happy Coding. 🙂

If you found this article helpful, consider supporting.

Buy me a coffeeBuy me a coffee

1 Comment

  1. Victor

    Great article. It’s awesome to learn about services that can improve my application maintenance.

    Reply

Submit a Comment

Your email address will not be published. Required fields are marked *

Follow codewithmukesh

Support Me!

Buy me a coffeeBuy me a coffee

Pin It on Pinterest