.NET 5控制台应用使用Serilog实现多日志文件独立输出方案
.NET 5控制台应用基于Serilog实现多独立文件日志输出
原场景与问题
我有一个安装了Serilog NuGet包的.NET 5.0控制台应用,appsettings.json中Serilog相关初始配置如下:
"Enrich": [ "FromLogContext", "WithMachineName", "WithProcessId", "WithThreadId" ], "WriteTo": [ { "Name": "Console", "Args": { "outputTemplate": "[{Timestamp:HH:mm:ss.fff} [{Level}] {SourceContext} {Message}{NewLine}{Exception}", "theme": "Serilog.Sinks.SystemConsole.Themes.AnsiConsoleTheme::Code, Serilog.Sinks.Console" } }, { "Name": "File", "Args": { "path": "/Logs/SharedTreatment_logs.txt", "outputTemplate": "{Timestamp:G} {SourceContext} [{Level}] {Message}{NewLine:1}{Exception:1}", "formatter": "Serilog.Formatting.Json.JsonFormatter, Serilog", "fileSizeLimitBytes": 1000000, "rollOnFileSizeLimit": "true", "shared": "true", "flushToDiskInterval": 3 } } ]
配置加载代码如下:
Serilog.Debugging.SelfLog.Enable(Console.Error); var configuration = new ConfigurationBuilder() .AddJsonFile("appsettings.json") .Build(); var logger = loggerConfiguration.ReadFrom.Configuration(configuration).CreateLogger(); Log.Logger = logger?.ForContext<T>() ?? throw new ArgumentNullException(nameof(logger)); Host.CreateDefaultBuilder(args).UseSerilog((hostingContext, loggerConfiguration) => loggerConfiguration.ReadFrom.Configuration(hostingContext.Configuration))
项目内每个类都通过依赖注入获取ILogger实例,例如ILogger<MyClass> logger。需求是:如何在这类类中创建新的日志器,读取appsettings.json中的其他日志配置段,将日志输出到另一个独立文件中?
已验证的实现方案
经过测试,通过子日志器+属性过滤的方案可以实现需求,思路是创建两个子日志器,一个用于主日志记录,过滤排除带指定属性的日志输出到原有文件,另一个仅收录带指定属性的日志输出到新文件。
更新后的配置
{ "Serilog": { "Using": [ "Serilog.Sinks.Console", "Serilog.Sinks.File" ], "MinimumLevel": "Debug", "Enrich": [ "FromLogContext" ], "WriteTo": [ { "Name": "Console", "Args": { "outputTemplate": "[{Timestamp:HH:mm:ss.fff} [{Level}] {SourceContext} {Message}{NewLine}{Exception}", "theme": "Serilog.Sinks.SystemConsole.Themes.AnsiConsoleTheme::Code, Serilog.Sinks.Console" } }, { "Name": "Logger", "Args": { "configureLogger": { "Filter": [ { "Name": "ByIncludingOnly", "Args": { "expression": "@p['LogToFile']" } } ], "WriteTo": [ { "Name": "File", "Args": { "path": "Logs/SharedTreatment_logs_Second.txt", "outputTemplate": "{Timestamp:yyyy-MM-dd HH:mm:ss.fff} [{Level:u3}] {Message:lj}{NewLine}{Exception}" } } ] } } }, { "Name": "Logger", "Args": { "configureLogger": { "Filter": [ { "Name": "ByExcluding", "Args": { "expression": "@p['LogToFile']" } } ], "WriteTo": [ { "Name": "File", "Args": { "path": "Logs/SharedTreatment_logs.txt", "outputTemplate": "{Timestamp:G} {SourceContext} [{Level}] {Message}{NewLine:1}{Exception:1}", "formatter": "Serilog.Formatting.Json.JsonFormatter, Serilog", "fileSizeLimitBytes": 1000000, "rollOnFileSizeLimit": "true", "shared": "true", "flushToDiskInterval": 3 } } ] } } } ] } }
调用代码
static void Main(string[] args) { Console.WriteLine("Hello World!"); Log.Logger = new LoggerConfiguration().DefaultLoggerSetup<Program>(); using (LogContext.PushProperty("LogToFile", true)) { Log.Information("LogToFileTest"); } Log.Information("Just log"); Log.CloseAndFlush(); }
该方案运行后会成功生成两个日志文件,日志按照过滤规则输出到对应文件中。
方案优化建议
你当前的实现是Serilog多输出场景下的标准可行方案,针对不同使用场景可以做进一步优化:
- 如果独立日志按业务模块/类区分,不需要手动控制单条日志的输出目标,可以直接在过滤器中匹配
SourceContext(类名/命名空间),不需要手动PushProperty打标记,配置更简洁,比如过滤表达式写StartsWith(SourceContext, 'MyApp.SpecialBusiness')即可将指定命名空间下所有类的日志输出到独立文件。 - 如果两个日志体系完全独立,不需要共享公共配置,可以单独注册一个独立的ILogger实例到DI容器,直接读取appsettings中单独的配置段(比如命名为
Serilog:SecondLogger),需要使用独立日志的类直接注入该实例即可,完全和主日志隔离。
内容的提问来源于stack exchange,提问作者Banshee
相关产品推荐
相关产品推荐

