简体   繁体   English

Logback - 你能从 env 变量中定义 appender 名称和类吗?

[英]Logback - can you define appender name and class from env variables?

I want to have dynamic logback appender properties which can easily be added to the logback config file, however trying to set the class and name of the appender(which are in a xml attributes instead of elements under the appender element).我想要动态 logback appender 属性,可以轻松地将其添加到 logback 配置文件中,但是尝试设置 appender 的类和名称(它们位于 xml 属性中,而不是 appender 元素下的元素中)。

So here is my application.yml(hardcoded the values for the example, but in the real world use case those will be passed as env variables from Helm, during the deploy to K8s cluster):所以这是我的 application.yml(对示例的值进行硬编码,但在实际用例中,在部署到 K8s 集群期间,这些值将作为来自 Helm 的环境变量传递):

log:
  config:
    appender:
      name: CONSOLE
      class: ch.qos.logback.core.ConsoleAppender

And here is how I try to access those in logback-spring.xml(spring boot version - 2.2.4.RELEASE这是我尝试访问 logback-spring.xml(spring boot version - 2.2.4.RELEASE

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
    <!-- use Spring default values like patterns -->
    <include resource="org/springframework/boot/logging/logback/defaults.xml"/>
    <!-- declaration of ENV properties:   -->
    <springProperty name="LOG_CONFIG_APPENDER_NAME" source="log.config.appender.name"/>
    <springProperty name="LOG_CONFIG_APPENDER_CLASS" source="log.config.appender.class"/>

    <appender name="${LOG_CONFIG_APPENDER_NAME}" class="${LOG_CONFIG_APPENDER_CLASS}">
        <encoder>
            <pattern>${CONSOLE_LOG_PATTERN}</pattern>
            <charset>utf8</charset>
        </encoder>
    </appender>

    <root level="INFO">
        <appender-ref ref="${LOG_CONFIG_APPENDER_NAME}"/>
    </root>
</configuration>

This leads to the following exception:这会导致以下异常:

ERROR in ch.qos.logback.core.joran.action.AppenderAction - Could not create an Appender of type [${LOG_CONFIG_APPENDER_CLASS}]. ch.qos.logback.core.util.DynamicClassLoadingException: Failed to instantiate type ${LOG_CONFIG_APPENDER_CLASS}

So my question is: is it possible to define the appender name and class dynamically ?所以我的问题是:是否可以动态定义附加程序名称和类?

For the local env I want to have simple console log appender.对于本地环境,我想要简单的控制台日志附加程序。 For anything else I will use the LayoutWrappingEncoder and JacksonJsonFormatter to add custom fields for our ELK stack.对于其他任何事情,我将使用LayoutWrappingEncoderJacksonJsonFormatter为我们的 ELK 堆栈添加自定义字段。

So you want to use the <springProfile> tag in your logback-spring.xml :所以你想在你的logback-spring.xml使用<springProfile>标签:

The <springProfile> tag lets you optionally include or exclude sections of configuration based on the active Spring profiles. <springProfile>标记允许您根据活动的 Spring 配置文件选择性地包含或排除配置部分。 Profile sections are supported anywhere within the <configuration> element. <configuration>元素中的任何地方都支持<configuration>文件部分。 Use the name attribute to specify which profile accepts the configuration.使用name属性指定哪个配置文件接受配置。 The <springProfile> tag can contain a simple profile name (for example staging ) or a profile expression. <springProfile>标签可以包含一个简单的配置文件名称(例如staging )或配置文件表达式。 A profile expression allows for more complicated profile logic to be expressed, for example production & (eu-central | eu-west) .配置文件表达式允许表达更复杂的配置文件逻辑,例如production & (eu-central | eu-west) Check the reference guide for more details.查看参考指南了解更多详情。

See the example below:请参阅下面的示例:

<?xml version="1.0" encoding="UTF-8"?>
<configuration>

    <include resource="org/springframework/boot/logging/logback/defaults.xml"/>

    <springProfile name="staging">
        <!-- configuration to be enabled when the "staging" profile is active -->
    </springProfile>

    <springProfile name="dev | staging">
        <!-- configuration to be enabled when the "dev" or "staging" profiles are active -->
    </springProfile>

    <springProfile name="!production">
        <!-- configuration to be enabled when the "production" profile is not active -->
    </springProfile>

</configuration>

I have ended up doing it in Groovy, as mapping the config to the Spring profiles does not work for me and my team, as we are using the dev profile for both our local and our shared dev env(hosted on K8s cluster).我最终在 Groovy 中完成了这项工作,因为将配置映射到 Spring 配置文件对我和我的团队不起作用,因为我们将开发配置文件用于本地和共享开发环境(托管在 K8s 集群上)。

I am not proud of it, but ended doing it with a simple if:我并不为此感到自豪,但以一个简单的 if 结束了它:

def loggingType = System.getenv('LOGGING_TYPE')
def loggingLevelEnvVar = System.getenv('CUSTOM_LOGGING_LEVEL')
def loggingLevel = loggingLevelEnvVar == null ? INFO : Level.valueOf(loggingLevelEnvVar)
// please do not use a coloured pattern for consoles that will be scrapped
def loggingPattern = System.getenv('LOGGING_LEVEL_PATTERN')
...
if ('JSON'.equalsIgnoreCase(loggingType)) {
    appender('CONSOLE', ConsoleAppender) {
        encoder(LayoutWrappingEncoder) {
            layout(JsonLayout) {
                timestampFormat = "yyyy-MM-dd'T'HH:mm:ss.SSS"
                timestampFormatTimezoneId = 'Etc/UTC'
                appendLineSeparator = true
                jsonFormatter(JacksonJsonFormatter) {
                    prettyPrint = false
                }
            }
        }
    }
} else {
    appender('CONSOLE', ConsoleAppender) {
        encoder(PatternLayoutEncoder) {
            pattern = loggingPattern
        }
    }
}
...

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM