复用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
相关产品推荐
相关产品推荐

