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

如何配置ILogger实现单条消息单行、多行消息保留原格式?

实现自定义混合格式的日志输出

默认的SimpleConsoleFormatter没有提供直接配置项满足你的需求,但可以通过自定义日志格式化器来实现单条消息头与内容同行、多行消息保留原格式的效果,具体步骤如下:

1. 创建自定义格式化器类

继承ConsoleFormatter,复用原生SimpleConsoleFormatter的头部格式化逻辑,根据消息是否包含换行符切换输出模式:

using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Logging.Console;
using System.Text;

public class SmartConsoleFormatter : ConsoleFormatter
{
    private readonly SimpleConsoleFormatterOptions _options;
    private readonly SimpleConsoleFormatter _innerFormatter;

    public SmartConsoleFormatter(SimpleConsoleFormatterOptions options) 
        : base("SmartConsole")
    {
        _options = options;
        _innerFormatter = new SimpleConsoleFormatter(options);
    }

    public override void Write<TState>(in LogEntry<TState> logEntry, IExternalScopeProvider scopeProvider, TextWriter textWriter)
    {
        var originalSingleLine = _options.SingleLine;
        var message = logEntry.Formatter(logEntry.State, logEntry.Exception);

        try
        {
            if (!message.Contains(Environment.NewLine))
            {
                // 单条消息:强制SingleLine=true,让头与内容同行
                _options.SingleLine = true;
                _innerFormatter.Write(logEntry, scopeProvider, textWriter);
            }
            else
            {
                // 多行消息:先输出头部,再完整输出消息内容
                _options.SingleLine = true;
                using var headerWriter = new StringWriter();
                _innerFormatter.Write(logEntry, scopeProvider, headerWriter);
                var fullHeader = headerWriter.ToString();
                
                // 拆分出头部(去掉消息第一行)
                var firstLineEnd = fullHeader.IndexOf(message.Split(Environment.NewLine)[0], StringComparison.Ordinal);
                if (firstLineEnd != -1)
                {
                    textWriter.Write(fullHeader.Substring(0, firstLineEnd));
                    textWriter.WriteLine(message);
                }
                else
                {
                    //  fallback到原生多行格式
                    _options.SingleLine = false;
                    _innerFormatter.Write(logEntry, scopeProvider, textWriter);
                }
            }
        }
        finally
        {
            // 恢复原配置
            _options.SingleLine = originalSingleLine;
        }
    }
}

2. 注册自定义格式化器

在服务配置中替换默认的控制台格式化器:

services.AddLogging(options =>
{
    options.AddConsole(consoleOptions =>
    {
        // 指定使用自定义格式化器
        consoleOptions.FormatterName = "SmartConsole";
    });

    // 注册自定义格式化器及配置
    options.AddConsoleFormatter<SmartConsoleFormatter, SimpleConsoleFormatterOptions>(formatterOptions =>
    {
        // 可配置时间戳格式等原生选项
        formatterOptions.TimestampFormat = "[yyyy-MM-ddTHH:mm:ss] ";
        // 其他配置如ColorBehavior等可按需设置
    });
});

3. 验证效果

  • 单条消息输出:
[2024-05-20T15:30:49] dbug: Lala.WebUI.Shared.DataManagerHub[0] SaveLanguages in 0s.
  • 多行消息输出:
[2024-05-20T15:30:49] dbug: Microsoft.Extensions.Hosting.Internal.Host[4] Hosting stopped
Unhandled exception. Xunit.Sdk.FailException: Assert.Fail(): An error occurred while saving the entity changes. SQLite Error 19: 'FOREIGN KEY constraint failed'. from MeasureAsync in /home/mist/Projekty/lala/app/Lala.WebUI.Shared/CommonPostDataWorkerBase.cs at line 45

补充说明

  • 该实现复用原生格式化逻辑,避免重复编写日志头的级别、类别、时间戳等格式化代码,仅针对消息换行场景做适配。
  • 若需调整多行消息的缩进或异常格式,可在Write方法中进一步修改消息输出逻辑。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.04 17:06:06