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

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条件块、属性令牌、字面量),可自行实现简单解析器:

    1. 按{}分割模板字符串,区分字面量与令牌/表达式块
    2. 识别#if和#end标记,构建条件块层级结构
    3. 对属性令牌(如@t:HH:mm:ss)拆分属性名与格式说明符
      这种方式完全可控,不依赖内部实现,适合需求场景较简单的情况。

需要注意,Serilog官方未公开ExpressionTemplate的解析API,以上方案各有取舍:反射方式灵活但依赖内部实现,包装格式化器方式简单但仅能处理最终输出,自定义解析器可控但需维护语法兼容性。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.20 08:25:17