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

.NET Core中Serilog数据库日志冗余问题求助(需保留请求响应体)

减少Serilog数据库日志行数(保留请求与响应体)

核心优化方向

在保留请求、响应体的前提下压缩日志行数,关键是避免重复日志条目、过滤框架冗余输出,同时将请求全生命周期的核心数据合并到单条日志中。


具体实现方案

1. 补全并调整Serilog配置

完善你的appsettings.json配置,过滤低级别框架日志,精简输出字段:

"Serilog": {
  "MinimumLevel": {
    "Default": "Information",
    "Override": {
      "Microsoft": "Warning", // 过滤微软类库的Info及以下冗余日志
      "System": "Warning"
    }
  },
  "WriteTo": [
    {
      "Name": "MSSqlServer", // 按实际使用的数据库调整
      "Args": {
        "connectionString": "你的数据库连接字符串",
        "tableName": "Logs",
        "autoCreateSqlTable": true,
        "columnOptionsSection": {
          "removeStandardColumns": ["MessageTemplate"], // 移除重复的模板列(非必需可删除)
          "customColumns": [
            {
              "ColumnName": "RequestBody",
              "DataType": "nvarchar(max)"
            },
            {
              "ColumnName": "ResponseBody",
              "DataType": "nvarchar(max)"
            }
          ]
        }
      }
    }
  ]
}

2. 合并请求响应日志为单条

通过自定义中间件,在请求结束时一次性输出包含请求体、响应体的单条日志,避免请求开始/结束时分别打日志:

public class RequestResponseLoggingMiddleware
{
    private readonly RequestDelegate _next;
    private readonly ILogger<RequestResponseLoggingMiddleware> _logger;

    public RequestResponseLoggingMiddleware(RequestDelegate next, ILogger<RequestResponseLoggingMiddleware> logger)
    {
        _next = next;
        _logger = logger;
    }

    public async Task InvokeAsync(HttpContext context)
    {
        // 读取请求体
        context.Request.EnableBuffering();
        var requestBody = await new StreamReader(context.Request.Body).ReadToEndAsync();
        context.Request.Body.Position = 0;

        // 捕获响应体
        var originalResponseBody = context.Response.Body;
        using var responseBodyStream = new MemoryStream();
        context.Response.Body = responseBodyStream;

        await _next(context);

        responseBodyStream.Seek(0, SeekOrigin.Begin);
        var responseBody = await new StreamReader(responseBodyStream).ReadToEndAsync();
        responseBodyStream.Seek(0, SeekOrigin.Begin);
        await responseBodyStream.CopyToAsync(originalResponseBody);
        context.Response.Body = originalResponseBody;

        // 输出单条合并日志
        _logger.LogInformation(
            "请求路径: {Path}, 请求方法: {Method}, 请求体: {RequestBody}, 响应体: {ResponseBody}",
            context.Request.Path, context.Request.Method, requestBody, responseBody);
    }
}

// 在Program.cs注册中间件
app.UseMiddleware<RequestResponseLoggingMiddleware>();

3. 精简日志上下文 enrichment

如果日志中包含自动添加的非必需字段(如请求ID、会话ID等),可移除不必要的Enrich配置,只保留核心上下文信息:

Log.Logger = new LoggerConfiguration()
    .ReadFrom.Configuration(Configuration)
    // 只保留必需的enricher,比如下面示例只保留环境信息
    .Enrich.WithEnvironmentName()
    .WriteTo.Console()
    .CreateLogger();

效果验证

调整后,每个请求仅生成一条包含请求体、响应体的日志,同时过滤掉框架自动生成的冗余日志,既能保留核心业务数据,又能大幅减少日志表的行数。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.25 11:52:14