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

如何在Serilog中自定义TimeSpan的日志格式化方式?

解决Serilog中TimeSpan类型指标的格式化问题

问题根源

直接使用{Elapsed:ss.fff}报错是因为Serilog默认的消息模板解析逻辑中,格式说明符的语法和.NET原生TimeSpan自定义格式存在冲突,导致解析失败。

解决方案

以下两种方法可以在保留结构化日志原始TimeSpan数据的前提下,优化人类可读的输出格式:

方法一:转义.NET TimeSpan自定义格式字符串

在消息模板中,将TimeSpan自定义格式里的特殊符号(比如冒号、点)进行转义,让Serilog正确识别为.NET原生格式化规则:

// 单次迭代(仅秒和毫秒)
Log.Information("单次迭代完成,耗时 {Elapsed:ss\\.fff}", elapsedTime);

// 累计时长(分钟+秒+毫秒)
Log.Information("累计运行时长 {Total:mm\\:ss\\.fff}", totalTime);

这种方法无需额外代码,适合格式固定的场景。

方法二:自定义TimeSpan格式化器

如果需要根据时长动态调整格式(比如短时长显示秒级,长时长显示分钟级),可以实现一个自定义的ITextFormatter:

public class AdaptiveTimeSpanFormatter : ITextFormatter
{
    public void Format(object value, TextWriter output)
    {
        if (value is not TimeSpan ts)
        {
            output.Write(value.ToString());
            return;
        }

        // 根据时长选择对应格式
        if (ts.TotalMinutes < 1)
        {
            // 小于1分钟,显示秒+毫秒
            output.Write(ts.ToString("ss\\.fff"));
        }
        else
        {
            // 1分钟以上,显示分钟+秒+毫秒
            output.Write(ts.ToString("mm\\:ss\\.fff"));
        }
    }
}

然后在Serilog配置中注册这个格式化器:

Log.Logger = new LoggerConfiguration()
    .WriteTo.Console(
        outputTemplate: "{Timestamp:HH:mm:ss} [{Level:u3}] {Message:lj}{NewLine}{Exception}",
        formatProviders: new[] { new AdaptiveTimeSpanFormatter() })
    // 其他配置(如文件输出等)
    .CreateLogger();

之后在日志调用中直接使用{Elapsed}和{Total}即可,格式化器会自动处理显示逻辑:

Log.Information("单次迭代完成,耗时 {Elapsed}", elapsedTime);
Log.Information("累计运行时长 {Total}", totalTime);

核心优势

两种方法都能保证结构化日志中保留原始的TimeSpan类型数据(支持后续的数据分析、统计),仅在人类可读的日志输出中使用简化格式,完全符合结构化日志的设计理念。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.01 20:11:46