如何在 Logstash Encoder of Logback 中使用来自配置服务器的 Spring 环境值



我想将 Spring 环境值用作 Logback 追加器的 Logstash 编码器中的自定义字段。

有一个通用配置标记可以使用属性

<property resource="logstash.properties" />

并且有一个来自 Spring 的特殊配置标签用于此目的

<springProperty name="appEnv" source="environment"/>

然后,可以在 Logstash 编码器的自定义字段中使用这两个标记的属性

<encoder class="net.logstash.logback.encoder.LogstashEncoder">
<customFields>{"application.environment":"${appEnv}"</customFields>
</encoder>

问题是,据我了解,这只在某些情况下有效。问题可能是Logback 在构建 Spring 环境时已经完成了配置

它似乎在以下情况下起作用

  • 该属性是本地和静态的(在配置时可用)
  • 该属性位于 bootstrap.properties 中

它似乎不起作用时

  • 该属性是动态的,就像从Spring 配置服务器检索时一样

配置Logback时,从配置服务器传递的属性值null,因此日志将它们显示为名为appEnv的属性的appEnv_IS_UNDEFINED

因为大多数例子只是使用spring.application.name这似乎大多没有被注意到。

为了解决计时问题,我寻找了一种重新加载 Logback 配置onApplicationEvent的方法。我找到了这个答案,它证实了我的问题并提供了一个框架解决方案。

我发现了其他解决方案,其中使用 Logstash 编码器的 Logback 追加器完全以编程方式构建并添加到LoggerContext中。

但是,我想知道是否还有一种方法可以坚持使用追加器的XML配置,并在Spring环境准备就绪时以编程方式"重新加载"配置。我该怎么做?

我找到了这个答案来重新加载,但它对我的情况不起作用。appEnv_IS_UNDEFINED继续显示在日志文件中。

我能够通过实现 SpringApplicationContextInitializer来解决我的问题。

在调用initialize方法中,我可以通过RootLogger访问我的Logback Appender和Encoder。

Logger rootLogger = (Logger) LoggerFactory.getLogger(Logger.ROOT_LOGGER_NAME);
RollingFileAppender jsonFileAppender = (RollingFileAppender) rootLogger.getAppender(LOGSTASH_APPENDER_NAME);
LogstashEncoder encoder = (LogstashEncoder) jsonFileAppender.getEncoder();

从 LogstashEncoder 中,我可以获取自定义字段

String customFields = encoder.getCustomFields();

在那里,我按预期在 JSON 字符串中找到了未解析的属性

{"application.environment":"appEnv_IS_UNDEFINED"}

因为我可以从传递的ApplicationContext中获得构建的弹簧Environment

springEnvironment = applicationContext.getEnvironment();

我可以将未解析的属性与正则表达式(w+)_IS_UNDEFINED匹配,并将它们替换为 Spring 环境中的实际值。

令人惊讶的是,我不需要重新加载或重新启动任何东西只需在编码器上设置固定的自定义字段就足够了。紧接着,日志消息包含正确的值。

encoder.setCustomFields(fixedCustomFields);

有了这个初始值设定项,我可以在logback-spring.xml或包含的文件中完全配置我的追加器和 LogstashEncoder。

最新更新