如何配置Serilog使特定Info级日志写入Event Log(突破级别限制)
问题描述
在ASP.NET项目中使用Serilog配置日志,当前Event Log接收器仅记录Warning及以上级别的日志(通过restrictedToMinimumLevel配置),但需要让指定分类的Info级日志也能写入Event Log。之前尝试添加全局Filter.ByIncludingOnly规则,但该规则会作用于所有日志接收器(Console、File、Event Log),不符合需求。
现有日志配置代码:
_ = pServiceCollection.AddSerilog((serviceProvider, loggerConfiguration) => loggerConfiguration.ReadFrom.Configuration(pConfiguration) .ReadFrom.Services(serviceProvider) .Enrich.FromLogContext() .WriteTo.Console(outputTemplate: LogMessageTemplate, formatProvider: CultureInfo.InvariantCulture) .WriteTo.File(path: logFilePath, outputTemplate: LogMessageTemplate, rollingInterval: RollingInterval.Day, retainedFileCountLimit: 30, formatProvider: CultureInfo.InvariantCulture) .WriteTo.EventLog(source: CommonConstants.ProductName, manageEventSource: true, restrictedToMinimumLevel: LogEventLevel.Warning, formatProvider: CultureInfo.InvariantCulture));
日志调用代码(生成指定分类的Info日志):
var forcelogger = app.Services.GetService<ILoggerProvider>()!.CreateLogger(CommonConstants.ForceLoggingToEventLogCategory); forcelogger.LogInformation("force hallo Welt");
需要实现:保留原有日志配置(Console、File记录所有符合全局规则的日志,Event Log默认记录Warning+),同时让指定分类的Info日志也写入Event Log。
解决方案
可以通过给Event Log接收器单独配置过滤规则实现,不影响其他接收器。核心思路是用WriteTo.Logger创建一个子Logger,在子Logger中定义仅针对Event Log的过滤逻辑,再将Event Log接收器挂在这个子Logger下。
修改后的配置代码如下:
_ = pServiceCollection.AddSerilog((serviceProvider, loggerConfiguration) => loggerConfiguration.ReadFrom.Configuration(pConfiguration) .ReadFrom.Services(serviceProvider) .Enrich.FromLogContext() // 原有Console接收器,不受影响 .WriteTo.Console(outputTemplate: LogMessageTemplate, formatProvider: CultureInfo.InvariantCulture) // 原有File接收器,不受影响 .WriteTo.File(path: logFilePath, outputTemplate: LogMessageTemplate, rollingInterval: RollingInterval.Day, retainedFileCountLimit: 30, formatProvider: CultureInfo.InvariantCulture) // 给Event Log单独配置过滤规则 .WriteTo.Logger(lc => lc // 过滤规则:保留Warning+级别,或指定分类的Info级别 .Filter.ByIncludingOnly(e => e.Level >= LogEventLevel.Warning || (e.Level == LogEventLevel.Information && e.Properties.TryGetValue("SourceContext", out var sourceContext) && sourceContext.ToString().Contains(CommonConstants.ForceLoggingToEventLogCategory))) // 挂载Event Log接收器 .WriteTo.EventLog(source: CommonConstants.ProductName, manageEventSource: true, formatProvider: CultureInfo.InvariantCulture)));
关键说明
- 子Logger隔离过滤:通过
WriteTo.Logger创建独立的日志分支,过滤规则仅作用于该分支下的Event Log接收器,不会影响Console和File接收器。 - 过滤逻辑优化:用
TryGetValue替代ContainsKey+索引访问,避免键不存在时抛出异常;合并条件逻辑,更清晰。 - 移除冗余配置:因为过滤规则已经包含了级别判断,Event Log的
restrictedToMinimumLevel可以移除,避免重复判断。
配置完成后:
- Console和File接收器依然按照原有逻辑记录日志
- Event Log接收器会记录:所有Warning及以上级别日志,加上指定
SourceContext的Info级别日志
内容的提问来源于stack exchange,提问作者hardfork
相关产品推荐
相关产品推荐

