Search code examples
c#serilog

How to override a generic type's log level in serilog


I have ASP.NET WebApi application and apgeneric class as follows:

namespace MyNamespace;

public class MyService<T>
{
    private readonly ILogger<MyService<T>> logger;

    public MyService(ILogger<MyService<T>> logger)
    {
        this.logger = logger;
    }

    public void DoWork()
    {
        logger.LogDebug("Hello World!");
    }
}

I have tried following configurations in order to override log level inside MyService but without success:

{
  "Serilog": {
    "MinimumLevel": {
      "Default": "Information",
      "Override": {
        "MyNamespace.MyService": "Debug"
      }
    }
  }
}

and

{
  "Serilog": {
    "MinimumLevel": {
      "Default": "Information",
      "Override": {
        "MyNamespace.MyService<>": "Debug"
      }
    }
  }
}

How do I override log level ONLY for this class?


Solution

  • Logging is configured by logger category, not type. The category is specified when the logger is created using ILoggerFactory.CreateLogger, eg :

    public ContactModel(ILoggerFactory logger)
    {
        _logger = logger.CreateLogger("MyCategory");
    }
    

    Injected loggers use the target type's name as the category. That's not MyService<T> but the concrete type MyService<MyType1> that's getting constructed.

    The easiest way to create a separate category for all MyService<T> concrete types is to use a different namespace, eg :

    namespace MyNamespace.MyServices;
    
    public class MyService<T>
    {
    ...
    }
    

    The other option is to inject ILoggerFactory and create a logger with an explicit category name:

    namespace MyNamespace;
    
    public class MyService<T>
    {
        private readonly ILogger<MyService<T>> logger;
    
        public MyService(ILoggerFactory logger)
        {
            this.logger = logger.Create("MyNamespace.MyService");
        }
    

    or

            this.logger = logger.Create($"MyNamespace.MyService.{typeof(T).Name}");