Build status NuGet Samples

Logging to elmah.io from Microsoft.Extensions.Logging

Microsoft.Extensions.Logging is a common logging abstraction from Microsoft, much like log4net and Serilog. Microsoft.Extensions.Logging started as a new logging mechanism for ASP.NET Core, but now acts as a logging framework for all sorts of project types.

Start by installing the Elmah.Io.Extensions.Logging package:

Install-Package Elmah.Io.Extensions.Logging

Locate your API key (Where is my API key?) and log ID. The two values will be referenced as API_KEY and LOG_ID (Where is my log ID?) in the following.

Logging from ASP.NET Core

In the Program.cs file, call the ConfigureLogging-method and configure elmah.io like shown here:

WebHost.CreateDefaultBuilder(args)
    .UseStartup<Startup>()
    .ConfigureLogging((ctx, logging) =>
    {
        logging.AddElmahIo(options =>
        {
            options.ApiKey = "API_KEY";
            options.LogId = new Guid("LOG_ID");
        });
        logging.AddFilter<ElmahIoLoggerProvider>(null, LogLevel.Warning);
    })
    .Build();

By calling, the AddFilter-method, you ensure that only warnings and up are logged to elmah.io.

API key and log ID can also be configured in appsettings.json:

{
  ...
  "ElmahIo": {
    "ApiKey": "API_KEY",
    "LogId": "LOG_ID"
  }
}

Then configure the section and use the AddElmahIo overload (without any parameters):

WebHost.CreateDefaultBuilder(args)
    .UseStartup<Startup>()
    .ConfigureLogging((ctx, logging) =>
    {
        logging.Services.Configure<ElmahIoProviderOptions>(ctx.Configuration.GetSection("ElmahIo"));
        logging.AddElmahIo();
    })
    .Build();

Call AddElmahIo in the Configure-method in Startup.cs:

public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory fac)
{
    ...
    fac.AddElmahIo("API_KEY", new Guid("LOG_ID"));
    ...
}

Start logging messages by injecting an ILogger in your controllers:

public class HomeController : Controller
{
    private readonly ILogger _logger;

    public HomeController(ILogger logger)
    {
        _logger = logger;
    }

    public IActionResult Index()
    {
        _logger.LogWarning("Request to index");
        return View();
    }
}

Filtering log messages

As default, the elmah.io logger for Microsoft.Extensions.Logging only logs warnings, errors and fatals. The rationale behind this is that we build an error management system and really doesn't do much to support millions of debug messages from your code. Sometimes you may want to log non-exception messages, though. To do so, use filters in Microsoft.Extensions.Logging.

To log everything from log level Information and up, do the following:

Inside the ConfigureLogging-method in Startup.cs, change the minimum level:

WebHost.CreateDefaultBuilder(args)
    .UseStartup<Startup>()
    .ConfigureLogging((ctx, logging) =>
    {
        ...
        logging.AddFilter<ElmahIoLoggerProvider>(null, LogLevel.Information);
    })
    .Build();

Use the AddElmahIo overload which accepts a filter:

factory.AddElmahIo("API_KEY", new Guid("LOG_ID"), new FilterLoggerSettings
{
    {"*", LogLevel.Information}
});

In the code sample, every log message with log level of Information and up, will be logged to elmah.io. To log a new information message, create a logger with the elmah.io category and call the LogInformation method:

var logger = factory.CreateLogger("elmah.io");
logger.LogInformation("This is an information message");

Decorating log messages

Since Microsoft.Extensions.Logging isn't specific for web applications, messages logged through Elmah.Io.Extensions.Logging, doesn't include any properties from the HTTP context (like Elmah.Io.AspNetCore). To add additional properties, use one of two approaches as described below.

Elmah.Io.Extensions.Logging provides a range of reserved property names, that can be used to fill in data in the correct fields on the elmah.io UI. Let's say you want to fill the User field using structured logging only:

logger.LogInformation("{Quote} from {User}", "Hasta la vista, baby", "Arnold Schwarzenegger");

This will fill in the value Arnold Schwarzenegger in the User field, as well as add two key/value pairs (Quote and User) to the Data tab on elmah.io. For a reference of all possible property names, check out the property names on CreateMessage.

An alternative is to use the OnMessage action. As an example, we'll add the name of the current user to all log messages:

public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory factory)
{
    factory.AddElmahIo("API_KEY", new Guid("LOG_ID"), new ElmahIoProviderOptions
    {
        OnMessage = msg =>
        {
            var context = app.ApplicationServices.GetRequiredService<IHttpContextAccessor>().HttpContext;
            if (context == null) return;

            msg.User = context.User?.Identity?.Name;
        }
    });

    ....
}

For ASP.NET Core 2.x projects, you will need to use the old way of configuring logging (using ILoggerFactory), in order to resolve the IHttpContextAccessor object from DI.

appsettings.json configuration

Some of the configuration for Elmah.Io.Extensions.Logging, can be done through the appsettings.json file when using ASP.NET Core 2.x. To configure the minimum log level, add a new logger named ElmahIo to the settings file:

{
  "Logging": {
    ...
    "ElmahIo": {
      "LogLevel": {
        "Default": "Warning"
      }
    }
  }
}

Finally, tell the logger to look for this information, by adding a bit of code to the ConfigureLogging-method:

WebHost.CreateDefaultBuilder(args)
    .UseStartup<Startup>()
    .ConfigureLogging((ctx, logging) =>
    {
        logging.AddConfiguration(ctx.Configuration.GetSection("Logging"));
        ...
    })
    .Build();

Logging from a console application

Create a new LoggerFactory:

var factory = new LoggerFactory();

Configure Microsoft.Extensions.Logging to use elmah.io:

factory.AddElmahIo("API_KEY", new Guid("LOG_ID"));

Finally, create a new logger and start logging exceptions:

var logger = factory.CreateLogger("MyLog");
logger.LogError(1, ex, "Unexpected error");

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