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

.NET 6下ASP.NET Core WebApi中Serilog失败时记录POST请求体及分Sink问题

针对Serilog请求日志的两个问题解决方案

1. POST请求失败时记录请求体:无现成配置,需自定义扩展

Serilog的UseSerilogRequestLogging中间件默认不提供仅在POST请求失败时记录请求体的现成配置,需要通过自定义逻辑实现,核心思路是允许请求体重读+在请求结束后判断状态并读取请求体:

实现步骤

  • 第一步:确保请求体可重读
    在Program.cs的管道配置中,先添加启用请求体重读的中间件(必须放在其他处理请求的中间件之前):
    app.Use(async (context, next) =>
    {
        context.Request.EnableBuffering();
        await next();
    });
    
  • 第二步:扩展请求日志逻辑
    修改UseSerilogRequestLogging的配置,通过EnrichDiagnosticContext委托在请求结束后判断条件并读取请求体:
    app.UseSerilogRequestLogging(options =>
    {
        options.EnrichDiagnosticContext = (diagnosticContext, httpContext) =>
        {
            // 仅处理POST请求且响应状态码>299的情况
            if (httpContext.Request.Method.Equals("POST", StringComparison.OrdinalIgnoreCase) &&
                httpContext.Response.StatusCode > 299)
            {
                // 重置请求体读取位置
                httpContext.Request.Body.Position = 0;
                // 读取请求体(可根据实际编码调整)
                using var reader = new StreamReader(httpContext.Request.Body, Encoding.UTF8, leaveOpen: true);
                var requestBody = reader.ReadToEnd();
                // 将请求体添加到诊断上下文,后续日志会包含该属性
                diagnosticContext.Set("RequestBody", requestBody);
                // 再次重置位置,避免后续中间件读取异常
                httpContext.Request.Body.Position = 0;
            }
        };
    });
    
  • 注意事项:
    • 需过滤敏感字段(如密码、令牌),避免日志泄露敏感数据
    • 若请求体过大,需考虑性能问题,可添加大小限制逻辑

2. 将请求体写入独立Sink:通过日志过滤实现

要把包含请求体的日志单独发送到指定Sink,可利用Serilog的日志过滤+子日志器功能,结合环境区分虚拟机/容器的Sink类型:

实现步骤

  • 第一步:在Serilog配置中添加带过滤的独立Sink
    在Program.cs配置Serilog时,通过WriteTo.Logger()创建子日志器,仅将包含RequestBody属性的日志路由到独立Sink,同时保留原有日志的Sink配置:
    var builder = WebApplication.CreateBuilder(args);
    var env = builder.Environment;
    
    builder.Host.UseSerilog((context, config) =>
    {
        // 基础日志配置(原有虚拟机/容器的日志Sink)
        config.ReadFrom.Configuration(context.Configuration)
              .Enrich.FromLogContext();
    
        // 添加独立Sink:仅记录包含RequestBody的日志
        config.WriteTo.Logger(lc =>
        {
            lc.Filter.ByIncludingOnly(evt => evt.Properties.ContainsKey("RequestBody"));
            // 根据环境选择Sink:虚拟机用文件,容器用控制台
            if (env.IsEnvironment("VM")) // 需自定义环境标识,或用env.IsProduction()等区分
            {
                lc.WriteTo.File("logs/request-bodies-.txt", rollingInterval: RollingInterval.Day);
            }
            else
            {
                lc.WriteTo.Console();
            }
        });
    });
    
  • 第二步:(可选)排除原有Sink中的请求体日志
    如果不想让请求体日志出现在原有文件/控制台日志中,可给原有Sink添加排除过滤:
    // 原有文件Sink示例(添加排除逻辑)
    config.WriteTo.File("logs/app-.txt", 
                        rollingInterval: RollingInterval.Day,
                        restrictedToMinimumLevel: LogEventLevel.Information,
                        filter: evt => !evt.Properties.ContainsKey("RequestBody"));
    
  • 注意事项:
    • 确保环境标识准确,可通过环境变量ASPNETCORE_ENVIRONMENT设置虚拟机/容器的环境值
    • 独立Sink的配置(如文件路径、滚动策略)可根据实际需求调整

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.18 11:46:08