Logback - вы можете определить имя и класс appender из переменных env? - PullRequest
1 голос
/ 17 февраля 2020

Я хочу иметь динамические c свойства приложения обратного входа, которые можно легко добавить в файл конфигурации обратного входа, однако я пытаюсь установить класс и имя приложения (которые находятся в атрибутах xml вместо элементов под элемент appender).

Итак, вот мой application.yml (жестко закодированные значения для примера, но в реальном случае использования они будут переданы как переменные env из Helm во время развертывания в кластере K8s):

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

И вот как я пытаюсь получить доступ к ним в logback-spring. xml (версия загрузочной пружины - 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>

Это приводит к следующему исключение:

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}

Итак, мой вопрос: возможно ли динамическое определение имени и класса приложения?

Ответы [ 2 ]

2 голосов
/ 17 февраля 2020

Для локального env я хочу иметь простой app log log appender. Для всего остального я буду использовать LayoutWrappingEncoder и JacksonJsonFormatter для добавления пользовательских полей для нашего стека ELK.

Так что вы хотите использовать тег <springProfile> в вашем logback-spring.xml:

Тег <springProfile> позволяет при желании включать или исключать разделы конфигурации на основе активных профилей Spring. Разделы профиля поддерживаются в любом месте элемента <configuration>. Используйте атрибут name, чтобы указать, какой профиль принимает конфигурацию. Тег <springProfile> может содержать простое имя профиля (например, staging) или выражение профиля. Выражение профиля позволяет выразить более сложные логики профиля c, например production & (eu-central | eu-west). Обратитесь к справочному руководству для получения более подробной информации.

См. Пример ниже:

<?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>
0 голосов
/ 20 февраля 2020

В итоге я сделал это в Groovy, так как сопоставление конфигурации с профилями Spring не работает для меня и моей команды, так как мы используем профиль dev как для нашей локальной, так и для нашей общей dev env (размещенной на Кластер K8s).

Я не горжусь этим, но закончил делать это простым 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
        }
    }
}
...
...