Reputation:
I read some asp.net core source code and get confused about injecting a Logger, let's take a middleware for example:
public class CookiePolicyMiddleware {
private readonly RequestDelegate _next;
private readonly ILogger _logger;
public CookiePolicyMiddleware(RequestDelegate next, IOptions<CookiePolicyOptions> options, ILoggerFactory factory) {
Options = options.Value;
_next = next;
_logger = factory.CreateLogger<CookiePolicyMiddleware>();
}
// ...
}
so why not we just inject ILogger directly as:
public class CookiePolicyMiddleware {
private readonly RequestDelegate _next;
private readonly ILogger<CookiePolicyMiddleware> _logger;
public CookiePolicyMiddleware(RequestDelegate next, IOptions<CookiePolicyOptions> options, ILogger<CookiePolicyMiddleware> logger) {
Options = options.Value;
_next = next;
_logger = logger;
}
// ...
}
because the default CreateDefaultBuilder method in Program.cs will call services.AddLogging()
which will registe ILogger<>
as Logger<>
(https://source.dot.net/#Microsoft.Extensions.Logging/LoggingServiceCollectionExtensions.cs,42)
Isn't the second approach more straightforward?
Upvotes: 1
Views: 1605
Reputation: 64150
Well, not sure if your example is a copy & paste mistake and if you were meant to inject it a middleware's .Invoke
.
In constructor injection, they act same and ILogger<T>
should be preferred unless you are manually instantiating types and want pass a specific logger to it.
Inside .Invoke
, the case is different, because the middleware runs as singleton.
If you inject ILogger<T>
in the middle ware constructor, it will create a logger with the log level at the point when it was first created.
If you change the log in appsettings.json
while the application runs, it won't use the new values in the middleware logger and still log according to the old settings until the application is restarted.
This is because Logger<T>
is only a wrapper around ILoggerFactory.Create
to easily inject an typed logger w/o going over to the factory. The actual logger class is Logger
. When the logger is created, it gets a copy of the filter options (see source).
So the changes in filter settings will only be applied on newly created loggers.
What happens in the code above is, that the factory is injected and the logger created in the Invoke
method, which creates a new logger on every request, thus also loading the most recent filter and settings from appsettings.json
and allows live changing of log level without restarting of the application.
Upvotes: 2