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

无需新建自定义ILogger,能否为不同参数类型注册格式化器?

.NET日志系统:无需自定义ILogger即可注册类型专属格式化器

完全可以在不创建全新ILogger类型的前提下,为特定参数类型注册自定义格式化逻辑,替代默认的ToString()行为。针对你提到的Protobuf IMessage类型场景,有几种可行的实现方式:

1. 全局注册类型专属格式化器(.NET 6+)

通过日志提供者的配置扩展,为所有IMessage类型参数应用统一格式化逻辑,最适合全局场景:

步骤1:实现自定义格式化逻辑

public static class ProtobufFormatHelper
{
    // 自定义Protobuf消息格式化逻辑,比如序列化为带缩进的文本或JSON
    public static string FormatProtobufMessage(IMessage message)
    {
        // 使用Protobuf自带的文本格式化(需引用Google.Protobuf NuGet包)
        return message.ToString(Google.Protobuf.TextFormattingIndented);
        // 或者序列化为JSON:JsonFormatter.Default.Format(message)
    }
}

步骤2:扩展日志提供者的ValueFormatter

以常用的JSON控制台日志为例,注册全局格式化器:

var builder = WebApplication.CreateBuilder(args);

// 配置日志,替换默认的ValueFormatter
builder.Logging.AddJsonConsole(options =>
{
    options.FormatterOptions.ValueFormatter = new CustomProtobufValueFormatter();
});

// 自定义ValueFormatter,拦截IMessage类型
public class CustomProtobufValueFormatter : JsonValueFormatter
{
    protected override void WriteValue(Utf8JsonWriter writer, object? value, JsonValueFormatterOptions options)
    {
        if (value is IMessage protoMessage)
        {
            writer.WriteStringValue(ProtobufFormatHelper.FormatProtobufMessage(protoMessage));
            return;
        }
        // 其他类型沿用默认格式化逻辑
        base.WriteValue(writer, value, options);
    }
}

配置完成后,所有通过logger.Log*方法传入的IMessage参数,都会自动使用你定义的格式化逻辑,无需修改原有日志调用代码。

2. 封装强类型日志扩展方法

如果希望仅在特定场景下使用自定义格式化,可以封装扩展方法,利用LoggerMessage.Define实现高效的强类型日志:

public static class ProtobufLoggerExtensions
{
    private static readonly Action<ILogger, IMessage, Exception?> _logProtobufDebug =
        LoggerMessage.Define<IMessage>(
            LogLevel.Debug,
            new EventId(101, "ProtobufDebug"),
            "Debug: Protobuf message content - {Message}");

    public static void LogProtobufDebug(this ILogger logger, IMessage message)
    {
        _logProtobufDebug(logger, message, null);
    }
}

使用时直接调用扩展方法即可:

logger.LogProtobufDebug(myProtobufMessage);

3. 针对特定模板格式的格式化器

如果需要在日志模板中指定格式化规则(比如{MyProp:Protobuf}),可以实现ICustomFormatter:

public class ProtobufFormatter : ICustomFormatter, IFormatProvider
{
    public object? GetFormat(Type? formatType)
    {
        return formatType == typeof(ICustomFormatter) ? this : null;
    }

    public string Format(string? format, object? arg, IFormatProvider? formatProvider)
    {
        if (arg is IMessage message && format?.Equals("Protobuf", StringComparison.OrdinalIgnoreCase) == true)
        {
            return ProtobufFormatHelper.FormatProtobufMessage(message);
        }
        // 其他类型使用默认ToString()
        return arg?.ToString() ?? string.Empty;
    }
}

调用时需要传递格式化器实例:

logger.LogDebug(new ProtobufFormatter(), "Message: {MyProp:Protobuf}", myProtobufMessage);

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.07 20:45:23