如何按自定义标识符分类Serilog日志并设置专属日志级别?
基于业务上下文配置Serilog差异化日志级别
针对你提到的需求——按业务分组(比如Users实体、特定SQL查询)设置不同日志级别,而非局限于命名空间/类型,下面提供几个可行的实现方案:
方案1:过滤器+级别开关,精准控制上下文日志级别
核心思路是给不同业务场景的日志打上统一标记,再通过Serilog的过滤器和独立级别开关,为每个标记的日志组单独配置级别。
第一步:定义全局级别开关
先为每个业务分组创建独立的级别开关,方便后续动态调整:
// 全局开关集合,控制不同业务上下文的日志级别 public static class BusinessLogSwitches { // 默认给Users组设Error级别,调试时可动态修改 public static LoggingLevelSwitch UsersContext { get; } = new LoggingLevelSwitch(LogEventLevel.Error); // 特定SQL查询组直接启用Verbose级别 public static LoggingLevelSwitch CriticalSqlContext { get; } = new LoggingLevelSwitch(LogEventLevel.Verbose); }
第二步:给日志打业务上下文标记
在需要的业务代码中,用ForContext给日志打上对应分组的标记:
// Users相关业务的日志实例,统一标记为"Users" var usersLogger = Log.ForContext("BusinessContext", "Users"); // 需要详细记录的SQL查询日志,标记为"CriticalSql" var criticalSqlLogger = Log.ForContext("BusinessContext", "CriticalSql");
第三步:配置Serilog绑定规则
初始化日志器时,通过过滤器匹配标记的日志,再用MinimumLevel.Override将每个标记与对应的级别开关绑定:
Log.Logger = new LoggerConfiguration() .ReadFrom.Configuration(builder.Configuration) // 设置全局默认日志级别 .MinimumLevel.Information() // 为Users上下文绑定对应的级别开关 .MinimumLevel.Override("BusinessContext:Users", BusinessLogSwitches.UsersContext) // 为CriticalSql上下文绑定级别开关 .MinimumLevel.Override("BusinessContext:CriticalSql", BusinessLogSwitches.CriticalSqlContext) // 过滤出带BusinessContext标记的日志,确保规则仅作用于目标分组 .Filter.ByIncludingOnly(evt => evt.Properties.TryGetValue("BusinessContext", out var ctx) && (ctx.ToString() == "\"Users\"" || ctx.ToString() == "\"CriticalSql\"")) .CreateLogger();
动态调整级别
调试时直接修改开关级别即可,不会影响其他日志组:
if (builder.Environment.IsDevelopment()) { // 开发环境下开启Users组的Verbose级详细日志 BusinessLogSwitches.UsersContext.MinimumLevel = LogEventLevel.Verbose; }
方案2:自定义Enricher,规范上下文标记
如果需要更规范的标记方式,或要给日志附加更多业务属性,可以自定义Enricher来统一处理:
编写自定义Enricher
public class BusinessContextEnricher : ILogEventEnricher { private readonly string _contextName; public BusinessContextEnricher(string contextName) { _contextName = contextName; } public void Enrich(LogEvent logEvent, ILogEventPropertyFactory propertyFactory) { // 为日志添加统一的BusinessContext属性 logEvent.AddPropertyIfAbsent(propertyFactory.CreateProperty("BusinessContext", _contextName)); } }
创建带Enricher的日志实例
var usersLogger = Log.Logger.ForContext(new BusinessContextEnricher("Users"));
后续的Serilog配置逻辑与方案1完全一致,这种方式更适合团队统一规范标记规则。
方案3:子日志器,实现输出+级别双重隔离
如果不仅要控制级别,还要给不同业务分组的日志分配不同输出目标(比如Users日志输出到控制台,SQL日志写入文件),可以用子日志器实现完全隔离:
Log.Logger = new LoggerConfiguration() .ReadFrom.Configuration(builder.Configuration) // 主日志器的全局级别设置 .MinimumLevel.Information() // Users上下文子日志器:仅处理标记为Users的日志,用单独开关控制级别,输出到控制台 .WriteTo.Logger(lc => lc .Filter.ByIncludingOnly(evt => evt.Properties.ContainsKey("BusinessContext") && evt.Properties["BusinessContext"].ToString() == "\"Users\"") .MinimumLevel.ControlledBy(BusinessLogSwitches.UsersContext) .WriteTo.Console(outputTemplate: "[Users业务] {Timestamp:HH:mm:ss} [{Level}] {Message}{NewLine}{Exception}")) // CriticalSql上下文子日志器:仅处理标记为CriticalSql的日志,单独写入文件 .WriteTo.Logger(lc => lc .Filter.ByIncludingOnly(evt => evt.Properties.ContainsKey("BusinessContext") && evt.Properties["BusinessContext"].ToString() == "\"CriticalSql\"") .MinimumLevel.ControlledBy(BusinessLogSwitches.CriticalSqlContext) .WriteTo.File("critical-sql-logs.txt", rollingInterval: RollingInterval.Day)) .CreateLogger();
内容的提问来源于stack exchange,提问作者Kaldo
相关产品推荐
相关产品推荐

