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

复用Serilog模板:避免日志消息重复编写的方案咨询

解决方案:避免日志模板重复编写

针对你遇到的既要保留Serilog结构化日志能力(适配ElasticSearch的JSON存储需求),又要生成格式化日志消息存入数据库的问题,以下是两种实用的解决方法:

方法1:直接复用Serilog消息渲染API

通过Serilog内置的模板解析与渲染工具,仅定义一次日志模板,同时完成结构化日志记录和数据库用消息生成:

public async Task Timeout(StartSendTradeSaga state, IMessageHandlerContext context)
{
    var tradeId = Data.TradeId;
    // 仅定义一次日志模板
    var logTemplate = "Stale trade: Trade {TradeId} has been awaiting reply for more than one hour";
    var logParameters = new object[] { tradeId };

    // 渲染出格式化后的消息,用于数据库存储
    var messageTemplate = Serilog.Parsing.MessageTemplateParser.Parse(logTemplate);
    var msg = Serilog.Formatting.Display.MessageTemplateRenderer.Render(messageTemplate, logParameters);

    // 用Serilog记录结构化日志(保留字段信息,适配ElasticSearch)
    Log.Error(logTemplate, logParameters);

    Data.LogStatus = LogStatus.Error;
    Data.LogMessage = msg;
    if (Data.SaharaLogId != -1)
    {
        await SaveLog();
        MarkAsComplete();
    }
    else
    {
        throw new Exception("Unable to write log to database - missing audit trail id");
    }
}

方法2:封装工具类统一处理

如果多个业务场景都有类似需求,可以封装工具方法简化重复逻辑:

public static class LogUtility
{
    public static string LogAndGetRenderedMessage(LogEventLevel level, string template, params object[] parameters)
    {
        var parsedTemplate = Serilog.Parsing.MessageTemplateParser.Parse(template);
        var renderedMessage = Serilog.Formatting.Display.MessageTemplateRenderer.Render(parsedTemplate, parameters);

        // 根据日志级别调用对应Serilog方法
        switch (level)
        {
            case LogEventLevel.Error:
                Log.Error(template, parameters);
                break;
            case LogEventLevel.Warning:
                Log.Warning(template, parameters);
                break;
            case LogEventLevel.Information:
                Log.Information(template, parameters);
                break;
            // 按需扩展其他日志级别
        }

        return renderedMessage;
    }
}

使用时只需一行代码完成日志记录和消息获取:

public async Task Timeout(StartSendTradeSaga state, IMessageHandlerContext context)
{
    var msg = LogUtility.LogAndGetRenderedMessage(
        LogEventLevel.Error,
        "Stale trade: Trade {TradeId} has been awaiting reply for more than one hour",
        Data.TradeId);

    Data.LogStatus = LogStatus.Error;
    Data.LogMessage = msg;
    if (Data.SaharaLogId != -1)
    {
        await SaveLog();
        MarkAsComplete();
    }
    else
    {
        throw new Exception("Unable to write log to database - missing audit trail id");
    }
}

核心逻辑说明

  • 坚持使用Serilog模板语法({TradeId})是为了保留结构化日志的字段信息,让ElasticSearch能生成独立的TradeId字段,而非将值直接拼接成普通字符串,这是JSON日志存储的核心要求。
  • 通过Serilog的内置API复用同一模板,既满足了ElasticSearch的结构化需求,又避免了重复编写日志内容的冗余问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.16 09:05:21