如何确定Serilog配置中的可用Enrichers并实现动态值注入
Serilog 动态Enricher实现相关问题解答
已注册Enrichers枚举需求实现方案
Serilog 公开API没有直接提供枚举已注册Enrichers的方法,配置完成后的Enricher默认封装在ILogger实现类的内部处理链路中,不对外暴露。你可以通过两种方式实现需求:
- 配置阶段自行维护自定义Enricher的注册列表:新增一个
CustomEnricherRegistry静态类,每次调用Enrich.With()添加你自定义的Enricher实例时,同步将实例存入该静态类的集合中,后续需要赋值时直接从集合中取出对应实例即可,该方案无兼容性风险,是最稳妥的实现方式。 - 反射读取内部字段(不推荐):
Serilog.Core.Logger类包含私有字段_messageTemplateProcessors,该字段存储了所有注册的日志事件处理器,其中就包含所有Enricher实例,你可以通过反射读取该字段后筛选出你自定义的Enricher类型即可,该方案依赖Serilog内部实现,版本升级可能会失效。
更简化的动态值注入Enricher实现方案
不需要通过枚举全量Enrichers的方式实现动态赋值,直接调整自定义Enricher的结构即可,参考实现如下:
public class DynamicValueEnricher : ILogEventEnricher { // 全局共享动态值用静态容器,需要实例隔离则改为实例属性 public static ConcurrentDictionary<string, object> RuntimeValues { get; } = new(); public void Enrich(LogEvent logEvent, ILogEventPropertyFactory propertyFactory) { foreach (var (key, value) in RuntimeValues) { logEvent.AddPropertyIfAbsent(propertyFactory.CreateProperty(key, value)); } } // 对外暴露操作动态值的入口 public static void SetValue(string key, object value) => RuntimeValues[key] = value; public static void RemoveValue(string key) => RuntimeValues.TryRemove(key, out _); }
配置时注册该Enricher后,后续需要动态赋值时直接调用DynamicValueEnricher.SetValue("属性名", 属性值)即可,完全不需要枚举已注册的Enricher,实现逻辑更简单。
其他补充方案
如果你要注入的动态值是和作用域/请求绑定的,LogContext本身是Serilog官方推荐的实现方式,如果你觉得调用繁琐,可以自己封装一层辅助语法糖,比如封装成using (LogScope.SetUserId(123))的形式,用起来和自定义Enricher一样简洁,不需要额外开发自定义Enricher。
内容的提问来源于stack exchange,提问作者user4266661
相关产品推荐
相关产品推荐

