Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Pass ILogger or ILoggerFactory to constructors in AspNet Core?

The MS docs article "Introduction to Logging in ASP.NET Core" gives 2 examples of constructor injection

  • using ILogger

    private readonly ILogger _logger;    public TodoController(ILogger<TodoController> logger)   {      _logger = logger;    } 
  • and ILoggerFactory

    private readonly ILogger _logger;   public TodoController( ILoggerFactory loggerFactory)   {       _logger = loggerFactory.CreateLogger<TodoController>();   } 

My question is what should I pass to child classes called from my controller

  • pass ILoggerFactory to my child classes called from the controller and in each class call LoggerFactoryExtensions.CreateLogger<MyChildClass>() or

  • pass parent controller's ILogger<MyController> to each child class created from the controller and having non-generic parameter ILogger.

In logs I prefer to see separate category 'MyChildClass' for each class, rather than all classes use the category 'MyController' from the parent controller.
However CreateLogger in each object construction can be an expensive operation (e.g. see https://github.com/aspnet/Logging/issues/524)

Which option will you recommend? Can you suggest any other approach?

like image 996
Michael Freidgeim Avatar asked Sep 02 '17 12:09

Michael Freidgeim


People also ask

What is the difference between ILogger and ILoggerFactory?

ILogger: is responsible to write a log message of a given Log Level. ILoggerFactory: you can register one or more ILoggerProvider s with the factory, which in turn uses all of them to create an instance of ILogger . ILoggerFactory holds a collection of ILoggerProviders .

What is the use of ILogger in .NET core?

ILoggerFactory is a factory interface that we can use to create instances of the ILogger type and register logging providers. It acts as a wrapper for all the logger providers registered to it and a logger it creates can write to all the logger providers at once.

What is ILoggerFactory?

WithFilter(ILoggerFactory, IFilterLoggerSettings) Registers a wrapper logger which provides a common way to filter log messages across all registered ILoggerProviders. CreateLogger(ILoggerFactory, Type) Creates a new ILogger instance using the full name of the given type . CreateLogger<T>(ILoggerFactory)


1 Answers

This is more of a design issue.

The controller should not be creating child classes anyway. That is not a concern the controller should be dealing with and goes against SRP (Single Responsibility Principle).

My question is what should I pass to child classes called from my controller

If your preference is to separate the loggers, then there really isn't any other choice here than to have child (dependent) classes have their own loggers.

Have child classes inject their own logger

public class TodoRepository : ITodoRepository {     private readonly ILogger logger;       public TodoRepository(ILogger<TodoRepository> logger) {          this.logger = logger;        }        //... } 

and then inject the child class into the controller.

public class TodoController : Controller {     private readonly ILogger logger;     private readonly ITodoRepository todoRepository;      public TodoController(ILogger<TodoController> logger, ITodoRepository todoRepository) {         this.logger = logger;            this.todoRepository = todoRepository;     }      //... } 

That way, the child loggers will get resolved when the child classes are being resolved and injected into the controller.

like image 101
Nkosi Avatar answered Sep 18 '22 11:09

Nkosi