I have a React app that uses a .NET 7 API. We are using Graylog for logging. The idea is to provide an API endpoint for the react app to POST its error logs. I want to use a different log source if the errors are coming from the web app. In order to do it, I have written a middleware class based on the route of the request. If /logs
route is hit, I add a new logger configuration to the Logger factory.
Middleware class:
using Gelf.Extensions.Logging;
namespace MyProject1.Api.Extensions
{
public class LoggingMiddleware
{
private readonly RequestDelegate _next;
private readonly IConfiguration _configuration;
private readonly ILoggerFactory _loggerFactory;
public LoggingMiddleware(
RequestDelegate next,
IConfiguration configuration,
ILoggerFactory loggerFactory)
{
_next = next;
_configuration = configuration;
_loggerFactory = loggerFactory;
}
public async Task Invoke(HttpContext context)
{
if (context.Request.Path.StartsWithSegments("/logs"))
{
var gelfOptions = new GelfLoggerOptions();
_configuration.GetSection("Logging:WebAppGELF").Bind(gelfOptions);
gelfOptions.AdditionalFields["machine_name"] = Environment.MachineName;
_loggerFactory.AddGelf(gelfOptions);
await _next(context);
}
else
{
await _next(context);
}
}
}
}
Here's the logging section in appsettings.json
:
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning"
},
"GELF": {
"Host": "xxx.graylog.com",
"LogSource": "API"
},
"WebAppGELF": {
"Host": "xxx.graylog.com",
"LogSource": "WebApp"
}
}
The configuration in program.cs
:
app.UseMiddleware<LoggingMiddleware>();
using (var serviceScope = app.Services.CreateScope())
{
var services = serviceScope.ServiceProvider;
var logger = services.GetRequiredService<MyProject1.Logging.IMyLogger<MyProject1.Api.Extensions.Project1Exception>>();
app.ConfigureExceptionHandler(logger);
}
With the above, two log entries are being written every time the /logs
endpoint is hit. Content is the same but one log entry contains LogSource : API
and the other contains LogSource : WebApp
. I assume this is happening because the logger factory contains two loggers and both are being invoked.
What's the right way of doing this? Basically, I want to use different loggers or logging configurations based on the controller or class the logger is being used in.