Multiple filters for one logger with Serilog
Solution 1
Serilog will also do this as you describe, by filtering by namespace:
var isController = Matching.FromSource("MyApp.Controllers");
var isService = Matching.FromSource("MyApp.Services");
Log.Logger = new LoggerConfiguration()
.MinimumLevel.Verbose()
.WriteTo.RollingFile("d:/logs/recon-api-all-{Date}.log")
.WriteTo.Logger(l => l
.Filter.ByIncludingOnly(isController)
.WriteTo.RollingFile("d:/logs/recon-api-controller-{Date}.log"))
.WriteTo.Logger(l => l
.Filter.ByIncludingOnly(isService)
.WriteTo.RollingFile("d:/logs/recon-api-service-{Date}.log"))
.WriteTo.Logger(l => l
.Filter.ByExcluding(e => isController(e) || iService(e))
.WriteTo.RollingFile("d:/logs/recon-api-other-{Date}.log"))
.CreateLogger();
If the controllers and services aren't identifiable by namespace, you can write a lambda function in place of isController
or isService
to identify them.
(Your scenario might be better suited to a logging format that permits easier filtering, so that you can selectively view controller events, service events and so-on by filtering after the fact. Check out the other Serilog provided sinks for some options.)
Solution 2
The question was already answered. but in case if you want to log different levels into different files you can use the following configurations:
var conn = configuration.GetSection("ConnectionStrings:SqlConn").Value;
var serilogLogger = new LoggerConfiguration()
.MinimumLevel.Information()
.WriteTo.Console()
.WriteTo.MSSqlServer(conn, new MSSqlServerSinkOptions { TableName = "ErrorLogs", AutoCreateSqlTable = true }, restrictedToMinimumLevel: Serilog.Events.LogEventLevel.Warning)
.WriteTo.MSSqlServer(conn, new MSSqlServerSinkOptions { TableName = "InfoLogs", AutoCreateSqlTable = true }, restrictedToMinimumLevel: Serilog.Events.LogEventLevel.Information)
.CreateLogger();
![Carsten Franke](https://i.stack.imgur.com/ZuhDy.jpg?s=256&g=1)
Carsten Franke
Updated on June 21, 2022Comments
-
Carsten Franke about 2 years
I am trying to setup Serilog with my ASP.NET Core application. I'd like to have one log file for all controllers, one for all services, one for the rest and ideally one which contains everything. Every controller is inheriting
BaseController
and every serviceBaseService
. The controller and the service I am calling are writing a trace log event.The logger and the service are retrieved via dependy injection. The service looks like the controller (regarding the logger).
public class UsersController: BaseController { private UserService service { get; } public UsersController(ILogger<UsersController> logger, UserService userService) : base(logger) { service = userService; } } public abstract class BaseController: Controller { protected readonly ILogger<BaseController> Logger; public BaseController(ILogger<BaseController> logger) { Logger = logger; } }
Approach 1 (working with the base clases only)
Log.Logger = new LoggerConfiguration() .MinimumLevel.Verbose() .WriteTo.Logger(l => l .MinimumLevel.Verbose() .WriteTo.Logger(l2 => l2 .WriteTo.Logger(l3 => l3 .Filter.ByIncludingOnly(Matching.FromSource<BaseController>()) .MinimumLevel.Verbose() .WriteTo.RollingFile("d:/logs/recon-api-controller-{Date}.log")) .WriteTo.Logger(l3 => l3 .Filter.ByIncludingOnly(Matching.FromSource<BaseService>()) .MinimumLevel.Verbose() .WriteTo.RollingFile("d:/logs/recon-api-service-{Date}.log")) .WriteTo.Logger(l3 => l3 .Filter.ByExcluding(Matching.FromSource<BaseController>()) .Filter.ByExcluding(Matching.FromSource<BaseService>()) .MinimumLevel.Verbose() .WriteTo.RollingFile("d:/logs/recon-api-other-{Date}.log")) ) .WriteTo.RollingFile("d:/logs/recon-api-all-{Date}.log")) .CreateLogger();
This creates the log files for "other" and "all" only. Both contain the log events from controller and service.
Approach 2 (working with the concrete classes)
Log.Logger = new LoggerConfiguration() .MinimumLevel.Verbose() .WriteTo.Logger(l => l .MinimumLevel.Verbose() .WriteTo.Logger(l2 => l2 .WriteTo.Logger(l3 => l3 .Filter.ByIncludingOnly(Matching.FromSource<BaseController>()) .Filter.ByIncludingOnly(Matching.FromSource<PrivilegeGroupsController>()) .Filter.ByIncludingOnly(Matching.FromSource<PrivilegesController>()) .Filter.ByIncludingOnly(Matching.FromSource<UsersController>()) .MinimumLevel.Verbose() .WriteTo.RollingFile("d:/logs/recon-api-controller-{Date}.log")) .WriteTo.Logger(l3 => l3 .Filter.ByIncludingOnly(Matching.FromSource<BaseService>()) .Filter.ByIncludingOnly(Matching.FromSource<PrivilegeGroupService>()) .Filter.ByIncludingOnly(Matching.FromSource<PrivilegeService>()) .Filter.ByIncludingOnly(Matching.FromSource<UserService>()) .MinimumLevel.Verbose() .WriteTo.RollingFile("d:/logs/recon-api-service-{Date}.log")) .WriteTo.Logger(l3 => l3 .Filter.ByExcluding(Matching.FromSource<BaseController>()) .Filter.ByExcluding(Matching.FromSource<UsersController>()) .Filter.ByExcluding(Matching.FromSource<PrivilegeGroupsController>()) .Filter.ByExcluding(Matching.FromSource<PrivilegesController>()) .Filter.ByExcluding(Matching.FromSource<BaseService>()) .Filter.ByExcluding(Matching.FromSource<UserService>()) .Filter.ByExcluding(Matching.FromSource<PrivilegeGroupService>()) .Filter.ByExcluding(Matching.FromSource<PrivilegeService>()) .MinimumLevel.Verbose() .WriteTo.RollingFile("d:/logs/recon-api-other-{Date}.log")) ) .WriteTo.RollingFile("d:/logs/recon-api-all-{Date}.log")) .CreateLogger();
This creates the log files for "other" and "all" only. "all" contains the log events from controller and service.
Approach 3 (working with the user classes only)
Log.Logger = new LoggerConfiguration() .MinimumLevel.Verbose() .WriteTo.Logger(l => l .MinimumLevel.Verbose() .WriteTo.Logger(l2 => l2 .WriteTo.Logger(l3 => l3 .Filter.ByIncludingOnly(Matching.FromSource<UsersController>()) .MinimumLevel.Verbose() .WriteTo.RollingFile("d:/logs/recon-api-controller-{Date}.log")) .WriteTo.Logger(l3 => l3 .Filter.ByIncludingOnly(Matching.FromSource<UserService>()) .MinimumLevel.Verbose() .WriteTo.RollingFile("d:/logs/recon-api-service-{Date}.log")) .WriteTo.Logger(l3 => l3 .Filter.ByExcluding(Matching.FromSource<UsersController>()) .Filter.ByExcluding(Matching.FromSource<UserService>()) .MinimumLevel.Verbose() .WriteTo.RollingFile("d:/logs/recon-api-other-{Date}.log")) ) .WriteTo.RollingFile("d:/logs/recon-api-all-{Date}.log")) .CreateLogger();
This creates all the log files and every file contains the expected messages.
What needs to be done to achieve the desired goal (see second sentence of this post).
Best regards, Carsten
-
Carsten Franke almost 8 yearsSo... back from vacation: Your suggestion behaves exactly like my first approach (it creates log files for "all" and "other" and both contain all the messages). Some code for sanity check:
var isController = Matching.FromSource("ReconAPI.Controllers");
andnamespace ReconAPI.Controllers
-
Nicholas Blumhardt almost 8 yearsPlacing a breakpoint in
.Filter.ByExcluding(e => isController(e) || iService(e))
and examining the events might help get to the bottom of it. Are your events correctly tagged withSourceContext
? -
Carsten Franke almost 8 yearsI was using
Log.Logger
only. UsingLog.ForContext<T>()
helped a lot and now the messages appear exactly where they should. Thanks a bunch! -
Nicholas Blumhardt almost 8 yearsGreat. glad to hear it :-)
-
Idothisallday almost 6 years@NicholasBlumhardt how would you this method .Filter.ByExcluding() in json file to exclude microsoft logs?
-
CodeConstruct over 5 yearshow can we implement this in appsetting.json. (Mainly filtering a specific class)