You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何按自定义标识符分类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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.23 14:42:03