Logging infrastructure of ASP.NET Core supports logs filtering that is useful when we need one logging configuration for development environment and the another for live environment by example. This blog post introduces log filtering in ASP.NET Core through simple dummy controller code samples.
- ASP.NET Core: How log filtering works
- ASP.NET Core: Implementing Syslog logger
- File logging on ASP.NET Core
- Defensive logging on ASP.NET Core
In ASP.NET Core loggers have names. When we ask for logger we also specify the name for logger. Example below shows dummy controller that accepts logger factory as constructor argument and asks for logger names as “My Logger”.
public class HomeController : Controller
{
private readonly ILogger _logger;
public HomeController(ILoggerFactory loggerFactory)
{
_logger = loggerFactory.CreateLogger("My logger");
}
}
The case of multiple loggers. One may ask why I inject logger factory to controller. This way my controller can support multiple loggers. Suppose the case where application is using some external service. For application I want to keep logs at warning level but as external service can be very sensitive of input data I want this logger to run at information level.
Loggers are added to application pipeline in Configure() method of start-up class.
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{
loggerFactory.AddConsole(Configuration.GetSection("Logging"));
loggerFactory.AddDebug();
// ...
}
By default we don’t have any filters and all we write log goes to log targets. Default targets are console and debug.
Sample controller
To play with log filtering we will use simple dummy controller.
public class HomeController : Controller
{
private readonly ILogger _logger;
public HomeController(ILoggerFactory loggerFactory)
{
_logger = loggerFactory.CreateLogger("My logger");
}
public IActionResult Index()
{
_logger.LogInformation("This is info by my logger");
_logger.LogCritical("This is critical by my logger");
return View();
}
}
When we run application we will see the following output.
Now let’s add filtering for “My log” in start-up class.
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{
loggerFactory
.WithFilter(new FilterLoggerSettings
{
{ "My logger", LogLevel.Warning }
})
.AddConsole(Configuration.GetSection("Logging"))
.AddDebug();
// ..
}
For “My logger” now only warning level logs and above are allowed. Let’s run application again and see the output.
Although our dummy controller added two messages to logs – one informative and one critical – only the critical message is shown because all messages below warning are ignored.
Wrapping up
Log filtering allows us to set minimal log levels for all loggers our application uses. We can log messages with lower importance when debugging and we can go to live with warning as minimal log level. As filters are set by logger name then applications where multiple loggers are used can configure different loggers to log messages at different levels. Perhaps some loggers are configured to log only critical messages and for some components warning or information level messages are logged. This kind of filtering support allows us to build very flexible logging also for more complex applications.