This article shows how to use elmah.io error management with an ASP.NET Core application. The error, log data is added to elmah.io using different elmah.io nuget packages, directly from ASP.NET Core and also using an NLog elmah.io target.
Code: https://github.com/damienbod/AspNetCoreElmah
elmah.io is an error management system which can help you monitor, find and fix application problems fast. While structured logging is supported, the main focus of elmah.io is handling errors.
Getting started with Elmah.Io
Before you can start logging to elmah.io, you need to create an account and setup a log. Refer to the documentation here.
Logging exceptions, errors with Elmah.Io.AspNetCore and Elmah.Io.Extensions.Logging
You can add logs, exceptions to elmah.io directly from an ASP.NET Core application using the Elmah.Io.AspNetCore and the Elmah.Io.Extensions.Logging nuget packages. These packages can be added to the project using the nuget package manager.
Or you can just add the packages directly in the csproj file.
<Project Sdk="Microsoft.NET.Sdk.Web"> <PropertyGroup> <TargetFramework>netcoreapp1.1</TargetFramework> </PropertyGroup> <PropertyGroup> <UserSecretsId>AspNetCoreElmah-c23d2237a4-eb8832a1-452ac4</UserSecretsId> </PropertyGroup> <ItemGroup> <Content Include="wwwroot\index.html" /> </ItemGroup> <ItemGroup> <PackageReference Include="Elmah.Io.AspNetCore" Version="3.2.39-pre" /> <PackageReference Include="Elmah.Io.Extensions.Logging" Version="3.1.22-pre" /> <PackageReference Include="Microsoft.ApplicationInsights.AspNetCore" Version="2.0.0" /> <PackageReference Include="Microsoft.AspNetCore" Version="1.1.1" /> <PackageReference Include="Microsoft.AspNetCore.Mvc" Version="1.1.2" /> <PackageReference Include="Microsoft.AspNetCore.StaticFiles" Version="1.1.1" /> <PackageReference Include="Microsoft.Extensions.Logging.Debug" Version="1.1.1" /> <PackageReference Include="Microsoft.Extensions.Configuration.UserSecrets" Version="1.1.1" /> </ItemGroup> <ItemGroup> <DotNetCliToolReference Include="Microsoft.VisualStudio.Web.CodeGeneration.Tools" Version="1.0.0" /> </ItemGroup> </Project>
The Elmah.Io.AspNetCore package is used to catch unhandled exceptions in the application. This is configured in the Startup class. The OnMessage method is used to set specific properties in the messages which are sent to elmah.io. Setting the Hostname and the Application properties are very useful when evaluating the logs in elmah.io.
app.UseElmahIo( _elmahAppKey, new Guid(_elmahLogId), new ElmahIoSettings() { OnMessage = msg => { msg.Version = "1.0.0"; msg.Hostname = "dev"; msg.Application = "AspNetCoreElmah"; } });
The Elmah.Io.Extensions.Logging package is used to log messages using the built in ILoggerFactory. You should only send warning, errors, critical messages and not just log everything to elmah.io, but it is possible to do this. Again the OnMessage method can be used to set the Hostname and the Application name for each log.
loggerFactory.AddElmahIo( _elmahAppKey, new Guid(_elmahLogId), new FilterLoggerSettings { {"ValuesController", LogLevel.Information} }, new ElmahIoProviderOptions { OnMessage = msg => { msg.Version = "1.0.0"; msg.Hostname = "dev"; msg.Application = "AspNetCoreElmah"; } });
Using User Secrets for the elmah.io API-KEY and LogID
ASP.NET Core user secrets can be used to set the elmah.io API-KEY and the LogID as you don’t want to commit these to your source. The AddUserSecrets method can be used to set this.
private string _elmahAppKey; private string _elmahLogId; public Startup(IHostingEnvironment env) { var builder = new ConfigurationBuilder() .SetBasePath(env.ContentRootPath) .AddJsonFile("appsettings.json", optional: false, reloadOnChange: true) .AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true) .AddEnvironmentVariables(); if (env.IsDevelopment()) { builder.AddUserSecrets("AspNetCoreElmah-c23d2237a4-eb8832a1-452ac4"); } Configuration = builder.Build(); }
The user secret properties can then be used in the ConfigureServices method.
public void ConfigureServices(IServiceCollection services) { _elmahAppKey = Configuration["ElmahAppKey"]; _elmahLogId = Configuration["ElmahLogId"]; // Add framework services. services.AddMvc(); }
A dummy exception is thrown in this example, which then sends the data to elmah.io.
[HttpGet("{id}")] public string Get(int id) { throw new System.Exception("something terrible bad here!"); return "value"; }
Logging exceptions, errors to elmah.io using NLog
NLog using the Elmah.Io.NLog target can also be used in ASP.NET Core to send messages to elmah.io. This can be added using the nuget package manager.
Or you can just add it to the csproj file.
<PackageReference Include="Elmah.Io.NLog" Version="3.1.28-pre" /> <PackageReference Include="NLog.Web.AspNetCore" Version="4.3.1" />
NLog for ASP.NET Core applications can be configured in the Startup class. You need to set the target properties with the elmah.io API-KEY and also the LogId. You could also do this in the nlog.config file.
loggerFactory.AddNLog(); app.AddNLogWeb(); LogManager.Configuration.Variables["configDir"] = "C:\\git\\damienbod\\AspNetCoreElmah\\Logs"; foreach (ElmahIoTarget target in LogManager.Configuration.AllTargets.Where(t => t is ElmahIoTarget)) { target.ApiKey = _elmahAppKey; target.LogId = _elmahLogId; } LogManager.ReconfigExistingLoggers();
The IHttpContextAccessor and the HttpContextAccessor also need to be registered to the default IoC in ASP.NET Core to get the extra information from the web requests.
public void ConfigureServices(IServiceCollection services) { services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>(); _elmahAppKey = Configuration["ElmahAppKey"]; _elmahLogId = Configuration["ElmahLogId"]; // Add framework services. services.AddMvc(); }
The nlog.config file can then be configured for the target with the elmah.io type. The application property is also set which is useful in elmah.io.
<?xml version="1.0" encoding="utf-8" ?> <nlog xmlns="http://www.nlog-project.org/schemas/NLog.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" autoReload="true" internalLogLevel="Warn" internalLogFile="C:\git\damienbod\AspNetCoreElmah\Logs\internal-nlog.txt"> <extensions> <add assembly="NLog.Web.AspNetCore"/> <add assembly="Elmah.Io.NLog"/> </extensions> <targets> <target name="elmahio" type="elmah.io" apiKey="API_KEY" logId="LOG_ID" application="AspNetCoreElmahUI"/> <target xsi:type="File" name="allfile" fileName="${var:configDir}\nlog-all.log" layout="${longdate}|${event-properties:item=EventId.Id}|${logger}|${uppercase:${level}}|TraceId=${aspnet-traceidentifier}| url: ${aspnet-request-url} | action: ${aspnet-mvc-action} |${message} ${exception}" /> <target xsi:type="File" name="ownFile-web" fileName="${var:configDir}\nlog-own.log" layout="${longdate}|${event-properties:item=EventId.Id}|${logger}|${uppercase:${level}}|TraceId=${aspnet-traceidentifier}| url: ${aspnet-request-url} | action: ${aspnet-mvc-action} | ${message} ${exception}" /> <target xsi:type="Null" name="blackhole" /> </targets> <rules> <logger name="*" minlevel="Warn" writeTo="elmahio" /> <!--All logs, including from Microsoft--> <logger name="*" minlevel="Trace" writeTo="allfile" /> <!--Skip Microsoft logs and so log only own logs--> <logger name="Microsoft.*" minlevel="Trace" writeTo="blackhole" final="true" /> <logger name="*" minlevel="Trace" writeTo="ownFile-web" /> </rules> </nlog>
The About method calls the AspNetCoreElmah application method which throws the dummy exception, so we send exceptions from both applications.
public async Task<IActionResult> About() { _logger.LogInformation("HomeController About called"); // throws exception HttpClient _client = new HttpClient(); var response = await _client.GetAsync("http://localhost:37209/api/values/1"); response.EnsureSuccessStatusCode(); var responseString = System.Text.Encoding.UTF8.GetString( await response.Content.ReadAsByteArrayAsync() ); ViewData["Message"] = "Your application description page."; return View(); }
Now both applications can be started, and the errors can be viewed in the elmah.io dashboard.
Where you open the dashboard in elmah.io and access you logs, you can view the exceptions.
Here’s the log sent from the AspNetCoreElmah application.
Here’s the log sent from the AspNetCoreElmahUI application using NLog with Elmah.Io.
Links
https://github.com/elmahio/elmah.io.nlog
