I have written a middleware for my web application.
The middleware handles special requests and writes multiple information from multiple sources to the log. For example like the following code snippet:
public class MyMiddleware
{
public async Task Invoke(HttpContext context)
{
var dataToBeLogged = await context.Request.ReadFromJsonAsync<LogEntry[]>();
foreach(var l in dataToBeLogged)
{
var loggerName = string.IsNullOrEmpty(l.LoggerName) ? "Default" : l.LoggerName;
var logger = _loggerFactory.CreateLogger($"{env.ApplicationName}.Client.{loggerName}");
logger.Log(l.Level, l.Exception, l.Message);
}
}
}
The loggerName and therefor the logger might be differ but it could also be that a logger with the same loggerName hast been created before.
My question is what is the best practice of handling the logger creation?
- Should I always create a new logger? or
- Should I create a Dictionary where I store loggers which has been created before in the
Invoke
method (Example 1)? or - Because the instance of the middleware doesn't change at runtime, should I create the dictionary a class level (Example 2)?
Example 1
public class MyMiddleware
{
public async Task Invoke(HttpContext context)
{
var dataToBeLogged = await context.Request.ReadFromJsonAsync<LogEntry[]>();
var dict = new Dictionary<string, ILogger>();
foreach(var l in dataToBeLogged)
{
var loggerName = string.IsNullOrEmpty(l.LoggerName) ? "Default" : l.LoggerName;
if (!dict.ContainsKey(loggerName))
dict.Add(loggerName, _loggerFactory.CreateLogger($"{env.ApplicationName}.Client.{loggerName}"));
var logger = dict[loggerName];
logger.Log(l.Level, l.Exception, l.Message);
}
}
}
Example 2
public class MyMiddleware
{
private readonly dict = new Dictionary<string, ILogger>();
public async Task Invoke(HttpContext context)
{
var dataToBeLogged = await context.Request.ReadFromJsonAsync<LogEntry[]>();
foreach(var l in dataToBeLogged)
{
var loggerName = string.IsNullOrEmpty(l.LoggerName) ? "Default" : l.LoggerName;
if (!dict.ContainsKey(loggerName))
dict.Add(loggerName, _loggerFactory.CreateLogger($"{env.ApplicationName}.Client.{loggerName}"));
var logger = dict[loggerName];
logger.Log(l.Level, l.Exception, l.Message);
}
}
}
LogEntry class
public class LogEntry
{
public string LoggerName { get;set; }
public int Level { get;set; }
public Exception Exception { get;set; }
public string Message { get;set; }
}
Example data
[
{ loggerName: "LoggerOne", level: 2, exception: null, message: "This is an information" },
{ loggerName: "LoggerTwo", level: 3, exception: null, message: "This is a warning" },
{ loggerName: "LoggerOne", level: 4, exception: { message: "A Exception message", stackTrace: "..." }, message: "This is an error" }
]
Expected log output
MyProject.Client.LoggerOne: Information: This is an information
MyProject.Client.LoggerTwo: Warning: This is a warning
MyProject.Client.LoggerOne: Error: This is an error
MyProject.Client.LoggerOne: Error: A Exception message
at ...
at ...
at ...