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

如何通过Serilog(含MS日志扩展)限制EF Core commandText日志大小

限制EF Core日志中CommandText的大小(Serilog + Serilog MS Logging Extensions)

方法一:自定义EF Core日志拦截器

直接通过EF Core的命令拦截器,在数据库命令执行前截断过长的CommandText,所有后续日志都会使用处理后的内容。

实现步骤:

  1. 创建继承自DbCommandInterceptor的拦截类,重写同步/异步命令执行方法:
using Microsoft.EntityFrameworkCore.Diagnostics;
using System.Data.Common;

public class CommandTextTruncationInterceptor : DbCommandInterceptor
{
    private readonly int _maxLength;

    public CommandTextTruncationInterceptor(int maxCommandTextLength)
    {
        _maxLength = maxCommandTextLength;
    }

    public override InterceptionResult<DbDataReader> CommandExecuting(
        DbCommand command,
        CommandEventData eventData,
        InterceptionResult<DbDataReader> result)
    {
        TruncateCommandText(command);
        return base.CommandExecuting(command, eventData, result);
    }

    public override ValueTask<InterceptionResult<DbDataReader>> CommandExecutingAsync(
        DbCommand command,
        CommandEventData eventData,
        InterceptionResult<DbDataReader> result,
        CancellationToken cancellationToken = default)
    {
        TruncateCommandText(command);
        return base.CommandExecutingAsync(command, eventData, result, cancellationToken);
    }

    private void TruncateCommandText(DbCommand command)
    {
        if (command.CommandText.Length > _maxLength)
        {
            command.CommandText = $"{command.CommandText[.._maxLength]}... [TRUNCATED]";
        }
    }
}
  1. 在DbContext配置中注册拦截器:
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
    // 这里设置你需要的最大长度,比如1000
    optionsBuilder.AddInterceptors(new CommandTextTruncationInterceptor(1000));
}

方法二:Serilog层面处理日志事件

无需修改EF Core逻辑,直接在Serilog的日志事件流转中截断CommandText属性。

实现方式1:日志输出时转换

在Serilog的输出配置中添加转换逻辑:

Log.Logger = new LoggerConfiguration()
    .ReadFrom.Configuration(Configuration)
    .WriteTo.Console(
        outputTemplate: "{Timestamp:HH:mm:ss} [{Level}] {Message}{NewLine}{Exception}",
        transform: logEvent =>
        {
            const int maxLength = 1000;
            if (logEvent.Properties.TryGetValue("CommandText", out var prop) &&
                prop is ScalarValue scalar && scalar.Value is string commandText)
            {
                if (commandText.Length > maxLength)
                {
                    logEvent.AddOrUpdateProperty(new LogEventProperty(
                        "CommandText",
                        new ScalarValue($"{commandText[..maxLength]}... [TRUNCATED]")));
                }
            }
            return logEvent;
        })
    .CreateLogger();

实现方式2:自定义Enricher

创建日志增强器统一处理所有日志事件:

public class CommandTextTruncationEnricher : ILogEventEnricher
{
    private readonly int _maxLength;

    public CommandTextTruncationEnricher(int maxLength)
    {
        _maxLength = maxLength;
    }

    public void Enrich(LogEvent logEvent, ILogEventPropertyFactory propertyFactory)
    {
        if (logEvent.Properties.TryGetValue("CommandText", out var value) &&
            value is ScalarValue scalar && scalar.Value is string commandText)
        {
            if (commandText.Length > _maxLength)
            {
                var truncatedText = $"{commandText[.._maxLength]}... [TRUNCATED]";
                logEvent.AddOrUpdateProperty(propertyFactory.CreateProperty("CommandText", truncatedText));
            }
        }
    }
}

然后在Serilog配置中注册:

Log.Logger = new LoggerConfiguration()
    .Enrich.With(new CommandTextTruncationEnricher(1000))
    // 其他配置项
    .CreateLogger();

注意事项

  • 截断长度根据实际调试需求调整,避免丢失关键SQL片段。
  • 若使用异步数据库操作,必须同时重写拦截器的同步和异步方法。
  • EF Core日志中CommandText的属性键固定为CommandText,无需额外适配。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.25 06:03:01