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

如何为Microsoft ILogger注册ProblemDetails类型自定义格式化器?

实现自定义类型的日志序列化(无需手动调用Format)

完全可行,根据你使用的日志框架类型,通过注册自定义处理器/转换器就能实现ProblemDetails类型的自动序列化,不用每次手动调用Format方法,也不会仅输出ToString()的默认结果。

针对Microsoft.Extensions.Logging(.NET默认日志框架)

可以自定义控制台格式化器(或其他输出目标的格式化器),在其中处理ProblemDetails的序列化逻辑:

  1. 创建自定义格式化器类,继承ConsoleFormatter并重写Write方法:
public class CustomConsoleFormatter : ConsoleFormatter
{
    private readonly CustomConsoleFormatterOptions _options;

    public CustomConsoleFormatter(CustomConsoleFormatterOptions options) : base(nameof(CustomConsoleFormatter))
    {
        _options = options;
    }

    public override void Write<TState>(in LogEntry<TState> logEntry, IExternalScopeProvider scopeProvider, TextWriter textWriter)
    {
        var message = logEntry.Formatter(logEntry.State, logEntry.Exception);
        
        if (logEntry.State is IEnumerable<KeyValuePair<string, object>> stateProperties)
        {
            foreach (var prop in stateProperties)
            {
                if (prop.Value is ProblemDetails pd)
                {
                    message = message.Replace($"{{{prop.Key}}}", Format(pd));
                }
            }
        }

        textWriter.WriteLine(message);
    }
}

public class CustomConsoleFormatterOptions : ConsoleFormatterOptions
{
}
  1. 在DI容器中注册自定义格式化器:
var builder = WebApplication.CreateBuilder(args);

builder.Services.AddLogging(loggingBuilder =>
{
    loggingBuilder.AddConsole(options =>
    {
        options.FormatterName = nameof(CustomConsoleFormatter);
    })
    .AddConsoleFormatter<CustomConsoleFormatter, CustomConsoleFormatterOptions>();
});

针对Serilog日志框架

Serilog提供直接的类型解构配置,为ProblemDetails注册自定义序列化逻辑即可:

Log.Logger = new LoggerConfiguration()
    // 注册自定义字符串格式化逻辑
    .Destructure.ByTransforming<ProblemDetails>(problemDetails => Format(problemDetails))
    // 若需结构化输出,可返回键值对形式的对象
    // .Destructure.ByTransforming<ProblemDetails>(pd => new { pd.Title, pd.Status, pd.Detail })
    .WriteTo.Console()
    .CreateLogger();

配置完成后,直接调用_logger.LogInformation("Found a problem {Problem}", problemDetails),Serilog会自动用你指定的逻辑序列化ProblemDetails。

注意事项

  • 不建议直接重写ProblemDetails的ToString()方法,这会影响该类型在所有场景下的字符串输出,而我们通常只需要日志里用自定义格式。
  • 结构化日志场景下,优先返回键值对形式的结构化数据,方便后续日志分析工具解析。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.30 21:39:36