Serilog开发自定义Sink:是否有ExpressionTemplateParser提取令牌?
解析Serilog ExpressionTemplate的正确方式
Serilog的ExpressionTemplate解析逻辑并未完全公开,但可以通过以下几种方式绕过复制源码的问题:
利用反射访问内部解析器
Serilog.Expressions库中负责解析ExpressionTemplate的核心类型是Serilog.Expressions.Templates.TemplateParser及配套的TemplateRewriter等内部类型。可以通过反射调用其解析方法,获取结构化的模板抽象语法树(AST):// 需先引用Serilog.Expressions NuGet包 var parserType = Type.GetType("Serilog.Expressions.Templates.TemplateParser, Serilog.Expressions"); var parseMethod = parserType.GetMethod("Parse", BindingFlags.Public | BindingFlags.Instance); var parser = Activator.CreateInstance(parserType); // 传入目标ExpressionTemplate字符串 var templateAst = parseMethod.Invoke(parser, new object[] { "[{@t:HH:mm:ss} {@l:u3}{#if SourceContext is not null} ({SourceContext}){#end}] {@m}\n{@x}" });解析得到的
templateAst包含条件块、属性令牌、字面量等结构化节点,可遍历节点提取所需信息。注意这种方式依赖Serilog.Expressions的内部实现,版本升级时需验证兼容性。基于现有格式化器拦截渲染逻辑
若仅需修改输出样式(如添加颜色),无需完整解析模板,可包装ExpressionTemplate生成的ITextFormatter,在渲染流程中插入自定义处理:var expressionTemplate = new ExpressionTemplate("[{@t:HH:mm:ss} {@l:u3}{#if SourceContext is not null} ({SourceContext}){#end}] {@m}\n{@x}"); public class CustomSinkFormatter : ITextFormatter { private readonly ITextFormatter _innerFormatter; public CustomSinkFormatter(ITextFormatter innerFormatter) { _innerFormatter = innerFormatter; } public void Format(LogEvent logEvent, TextWriter output) { // 捕获原格式化器的输出结果 using var sw = new StringWriter(); _innerFormatter.Format(logEvent, sw); var renderedContent = sw.ToString(); // 示例:给日志级别添加ANSI颜色标记 renderedContent = Regex.Replace(renderedContent, @"(\s+([A-Z]{3})\s*)", "\x1b[33m$1\x1b[0m"); output.Write(renderedContent); } } // 使用时包装原格式化器 var customFormatter = new CustomSinkFormatter(expressionTemplate);这种方式无需解析模板结构,直接对最终渲染结果加工,适合样式修改类需求。
轻量自定义解析器
若仅需处理常见的ExpressionTemplate语法(#if/#end条件块、属性令牌、字面量),可自行实现简单解析器:- 按
{}分割模板字符串,区分字面量与令牌/表达式块 - 识别
#if和#end标记,构建条件块层级结构 - 对属性令牌(如
@t:HH:mm:ss)拆分属性名与格式说明符
这种方式完全可控,不依赖内部实现,适合需求场景较简单的情况。
- 按
需要注意,Serilog官方未公开ExpressionTemplate的解析API,以上方案各有取舍:反射方式灵活但依赖内部实现,包装格式化器方式简单但仅能处理最终输出,自定义解析器可控但需维护语法兼容性。
内容的提问来源于stack exchange,提问作者netcorefan
相关产品推荐
相关产品推荐

