首页 > 解决方案 > 如何在 Logback 的 Logstash 编码器中使用来自配置服务器的 Spring 环境值

问题描述

我想在Logback appender的 Logstash 编码器中使用 Spring 环境值作为自定义字段。

有一个通用的配置标签来使用属性

<property resource="logstash.properties" />

Spring为此提供了一个特殊的配置标签

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

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

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

问题是,据我了解,这仅在某些情况下有效。问题大概是在Spring环境搭建的时候Logback已经配置好了

它似乎在什么时候起作用

它似乎不起作用

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

因为大多数示例只是使用spring.application.namethis 似乎几乎没有被注意到。

为了解决时间问题,我搜索了一种重新加载 Logback 配置 onApplicationEvent的方法。我发现这个答案证实了我的问题并提供了一个框架解决方案。

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

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

我找到了这个答案来重新加载,但它不适用于我的情况。appEnv_IS_UNDEFINED继续出现在日志文件中。

标签: spring-bootspring-cloud-configlogstash-logback-encoder

解决方案


我能够通过实施 Spring 来解决我的问题ApplicationContextInitializer

在被调用的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,我可以得到 customFields

String customFields = encoder.getCustomFields();

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

{"application.environment":"appEnv_IS_UNDEFINED"}

因为我可以Environment从传递的ApplicationContext

springEnvironment = applicationContext.getEnvironment();

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

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

encoder.setCustomFields(fixedCustomFields);

logback-spring.xml有了这个初始化器,我可以在或包含的文件中完全配置我的 appender 和 LogstashEncoder 。


推荐阅读