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

如何配置Serilog实现仅满足条件时才捕获指定scope范围内的日志?

Serilog 条件捕获Scope内日志的实现方案

实现你提的三个需求,核心思路是用缓冲Sink包装 + 作用域属性过滤的组合方案,无需修改现有日志埋点:

基础配置逻辑

首先给需要触发的指定Sink套一层缓冲逻辑,Scope生命周期内的日志先暂存到内存,仅满足触发条件时才批量写入目标Sink,否则直接丢弃。


1. 作用域标识位设置

对应你需要的代码内控制Sink开关的需求,直接通过作用域属性传递标识即可,和你给出的示例写法完全兼容:

// 给当前Scope设置标识,仅设置了EnableCustomSink=true的Scope才会触发目标Sink输出
using var scope = _logger.BeginScope(new Dictionary<string, object>
{
    ["EnableCustomSink"] = true,
    ["RequestTraceId"] = Guid.NewGuid().ToString("N")
});

// 作用域内的日志会先进入缓冲
_logger.LogInformation("请求开始处理");
// 业务逻辑执行
// ...

2. 触发条件配置

Serilog的配置示例如下,同时支持「出现Error/Fatal日志」和「请求未捕获异常」两个触发条件:

Log.Logger = new LoggerConfiguration()
    .MinimumLevel.Information()
    // 其他全局Sink正常配置,比如控制台输出
    .WriteTo.Console()
    // 你的指定目标Sink,加条件过滤和缓冲包装
    .WriteTo.Conditional(
        logEvent => 
            // 首先判断Scope内是否开启了目标Sink的标识
            logEvent.Properties.TryGetValue("EnableCustomSink", out var enableVal) 
            && enableVal.ToString().Trim('"') == bool.TrueString,
        sinkConfig => sinkConfig.Sink(new BufferedTriggerSink(
            // 传入你最终要输出的目标Sink实例,比如写文件、写ES的Sink
            targetSink: new FileSink("logs/triggered.log", new JsonFormatter(), null),
            // 配置最低捕获日志级别
            minimumLevel: LogEventLevel.Information,
            // 配置触发条件:只要有Error以上日志或者异常标记就刷入
            triggerCondition: bufferedLogs => 
                bufferedLogs.Any(x => x.Level >= LogEventLevel.Error 
                    || x.Properties.ContainsKey("HasUnhandledException"))
        ))
    )
    .CreateLogger();

3. 未捕获异常场景兼容

如果是ASP.NET Core场景,直接在全局异常中间件里加异常标记即可触发日志刷入:

public class GlobalExceptionMiddleware
{
    private readonly RequestDelegate _next;
    public GlobalExceptionMiddleware(RequestDelegate next) => _next = next;

    public async Task InvokeAsync(HttpContext context, ILogger<GlobalExceptionMiddleware> logger)
    {
        using var scope = logger.BeginScope(new Dictionary<string, object>
        {
            ["EnableCustomSink"] = true,
            ["RequestTraceId"] = context.TraceIdentifier
        });
        try
        {
            await _next(context);
        }
        catch (Exception ex)
        {
            // 打上异常标记,触发缓冲日志刷入
            using var _ = logger.BeginScope(new Dictionary<string, object> { ["HasUnhandledException"] = true });
            logger.LogError(ex, "请求处理发生未捕获异常");
            throw;
        }
    }
}

注意事项

  • 缓冲Sink建议设置单Scope最大日志条数限制,避免极端场景下内存溢出
  • 如果是无HttpContext的后台任务场景,手动给执行Scope加对应标识即可复用同一套逻辑

内容的提问来源于stack exchange,提问作者RVandersteen

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.23 20:54:01