Always create a new ILogger or store them?

52 views Asked by At

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 ...
0

There are 0 answers