Reputation: 13
In a layered web application I want to move all error logging from the Domain and Data layers to the global exception handler, but I'm not sure what is the trade-off. I want to remove any logging call and replace it by a more specific Exception (custom if it's necessary) or remove the catching:
try{
. . .
}
catch
{
Logger.Error('Info'); // <-- remove this for a: throw new CustomException('Info', ex);
throw; // <-- then, remove this line
}
There is a configured Global Exception Handler as middle-ware in the WebAPI, then as part of the handler method I'm going to log any exception occurred
// Startup.cs
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
app.UseExceptionHandler(
error =>
{
GlobalExceptionHandler.ErrorHandling(error, env);
});
}
// GlobalExceptionHandler.cs
public static class GlobalExceptionHandler
{
public static void ErrorHandling(IApplicationBuilder errorApp, IHostingEnvironment env)
{
errorApp.Run(async context =>
{
.
.
.
Log.Current.Error(exception.Message, () => exception);
}
}
}
Could be a better approach to avoid duplicated logging records?
Upvotes: 1
Views: 3970
Reputation: 2227
In the applications I build I like to use the approach you are suggesting. I'll post the middleware that I use:
using System;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Http;
using MyProject.Interfaces;
namespace MyProject.Middlewares
{
public class ErrorReporterMiddleware
{
private readonly RequestDelegate RequestDelegate;
public ErrorReporterMiddleware(RequestDelegate requestDelegate)
{
RequestDelegate = requestDelegate ?? throw new ArgumentNullException(nameof(requestDelegate));
}
public async Task Invoke(HttpContext httpContext, IErrorReporter errorReporter)
{
try
{
await RequestDelegate(httpContext);
}
catch (Exception e)
{
await errorReporter?.CaptureAsync(e);
throw;
}
}
}
}
In this case IErrorReporter
is an interface I have defined in the MyProject.Interfaces
namespace. I use it to abstract the logging service:
using System;
using System.Threading.Tasks;
namespace MyProject.Interfaces
{
public interface IErrorReporter
{
Task CaptureAsync(Exception exception);
Task CaptureAsync(string message);
}
}
Then in the Startup.cs
I just add the following line to the Configure
method:
app.UseMiddleware<ErrorReporterMiddleware>();
Nothing special but I think it's a clean approach.
Upvotes: 1