Подключение и конфигурирование logger в прикладном приложении#

Подключение logback для Java приложений#

Для интеграции с сервисом Журналирования рекомендуем использовать slf4j, его реализацию logback. В файл pom.xml проекта необходимо добавить следующие зависимости на logback.

Подключить зависимости#

<dependency>
    <groupId>org.slf4j</groupId>
    <artifactId>slf4j-api</artifactId>
</dependency>

<dependency>
    <groupId>ch.qos.logback</groupId>
    <artifactId>logback-classic</artifactId>
</dependency>

<dependency>
    <groupId>net.logstash.logback</groupId>
    <artifactId>logstash-logback-encoder</artifactId>
</dependency>

Сконфигурировать logback#

В проекте с конфигурациями дистрибутива по пути k8s/base/configmaps/ необходимо добавить конфигурацию logback, в виде configMap (пример logback-xml.yaml) со следующим содержимым:

apiVersion: "v1"
kind: "ConfigMap"
metadata:
  name: "logback-xml"
data:
  logback.xml: |-
    <configuration debug="true" scan="true" scanPeriod="30 seconds">
        <property scope="context" resource="env.properties"/>
        <appender name="JSON" class="ch.qos.logback.core.rolling.RollingFileAppender">
            <encoder class="net.logstash.logback.encoder.LoggingEventCompositeJsonEncoder">
            <providers>
                <timestamp>
                    <fieldName>serverEventDatetime</fieldName>
                    <pattern>[UNIX_TIMESTAMP_AS_NUMBER]</pattern>
                </timestamp>
                <logLevel>
                    <fieldName>level</fieldName>
                </logLevel>
                <loggerName>
                    <fieldName>logger</fieldName>
                </loggerName>
                <threadName>
                    <fieldName>threadName</fieldName>
                </threadName>
                <message/>
                <stackTrace>
                    <fieldName>stackTrace</fieldName>
                    <throwableConverter class="net.logstash.logback.stacktrace.ShortenedThrowableConverter">
                        <maxDepthPerThrowable>30</maxDepthPerThrowable>
                        <maxLength>4096</maxLength>
                        <rootCauseFirst>true</rootCauseFirst>
                    </throwableConverter>
                </stackTrace>
                <pattern>
                    <omitEmptyFields>true</omitEmptyFields>
                    <pattern>
                        {
                        "application": "${spring.application.name}"
                        }
                    </pattern>
                </pattern>
                <mdc>
                    <excludeMdcKeyName>serverEventDatetime</excludeMdcKeyName>
                    <excludeMdcKeyName>level</excludeMdcKeyName>
                    <excludeMdcKeyName>logger</excludeMdcKeyName>
                    <excludeMdcKeyName>threadName</excludeMdcKeyName>
                </mdc>
            </providers>
            </encoder>
            <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
                <fileNamePattern>/fluent-bit/etc/logs/log_%d{yyyy-MM-dd}_%i.json</fileNamePattern>
                <maxFileSize>5MB</maxFileSize>
                <maxHistory>5</maxHistory>
                <totalSizeCap>50MB</totalSizeCap>
            </rollingPolicy>
        </appender>

        <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
            <encoder>
                <pattern>%date %level [%thread] %logger{5} - %msg %n %xEx</pattern>
                <charset>UTF-8</charset>
            </encoder>
        </appender>

        <root level="INFO">
            <appender-ref ref="STDOUT"/>
            <appender-ref ref="JSON"/>
        </root>
    </configuration>

Здесь Logback сконфигурирован с двумя appender - STDOUT и JSON.
STDOUT – позволяет увидеть логи в консоли Kuberbetes или терминале разработчика, при отладке локально.
JSON – это файловый appender, который пишет логи в формате JSON, что удобно для дальнейшей обработки и записи в различные системы (Kafka, Elasticsearch, etc.).

В качестве json-encoder в appender используется реализация от Logstash - <encoder class="net.logstash.logback.encoder.LoggingEventCompositeJsonEncoder">. Его задача - сформировать записи логов в формате JSON.

Добавить дополнительную информацию#

По желанию, в записи логов можно добавить дополнительные атрибуты, для упрощения процедуры поиска, для этого надо изменить или дополнить конфигурацию LoggingEventCompositeJsonEncoder.

Пример добавления статичного атрибута приложения, для идентификации его логов. Данные атрибуты указываются в секции pattern в файле logback-xml.yaml:

<pattern>
    <omitEmptyFields>true</omitEmptyFields>
    <pattern>
        {
        "application": "${spring.application.name}"
        }
    </pattern>
</pattern>

В файле application.properties из папки проекта src/main/resources для этого можно задать значение:

spring.application.name=DemoApplication

В таком случае все записи логов будут содержать атрибут application со значением "DemoApplication" Аналогичным способом можно добавлять и другие атрибуты, например, версию приложения и т.п.

Настроить ротацию логов#

Рекомендуется придерживаться следующих ограничений:

  • ограничить размеры файлов логов, чтобы избежать ситуаций с переполнением дискового пространства.

  • выполнять запись логов в разные файлы последовательно, что обеспечивает их плавную обработку fluent-bit и снизит риск потери логов при высокой интенсивности записи.

  • ограничить количество файлов для записи логов, таким образом, по мере заполнения, старые файлы будут постепенно удаляться, логи будут писаться в новые, по принципу очереди. Такая политика ротации настраивается следующим образом в файле logback-xml.yaml:

<rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
    <fileNamePattern>logs/log_%d{yyyy-MM-dd}_%i.json</fileNamePattern>
    <maxFileSize>50MB</maxFileSize>
    <maxHistory>5</maxHistory>
    <totalSizeCap>250MB</totalSizeCap>
</rollingPolicy>

где:

  • maxFileSize - максимальный размер файла, по достижению которого создается новый файл, а старый в последствии удалится, по мере накопления общего объема всех файлов логов, установленного в totalSizeCap.

В этом примере будет создано и все время поддерживаться не более 5 файлов размером до 50 MB.

При гибкой настройке этих параметров, можно минимально нивелировать потерю их fluent-bit-ом.

Настроить диагностику#

Перечень параметров для диагностики проблем в logback.xml :

configuration debug="true" - включает OnConsoleStatusListener для вывода данных о состоянии logger, что бывает нужно при диагностике проблем logback-а.

Включение данного режима не оказывает влияния на уровень логов Java.

Данный режим позволяет выводить в STDOUT информацию о работе logger logback в приложении, такую как:

  • конфигурация logger и ее изменения

  • факты ротации файлов с логами

  • ошибки в работе logger

Данная информация позволяет диагностировать проблемы, которые могут возникать в промышленной эксплуатации в части логирования.

Настроить runtime обновление конфигурации#

scan="true" - позволяет включить перечитывание конфигурации logback.xml и автоматической реконфигурации logback в runtime, что позволит без перезагрузки приложения изменить конфигурацию (например, понизить или повысить уровень логов по какому-либо пакету)
По умолчанию конфигурационный файл будет сканироваться с интервалом 1 минута. Параметром
scanPeriod="30 seconds" меняется временной интервал перечитывания конфигурации logger.

В разделе <providers/> LoggingEventCompositeJsonEncoder в элементе <timestamp/> задается имя поля для времени события лога - servertEventDatetime в формате [UNIX_TIMESTAMP_AS_NUMBER] - миллисекундах с unix epoch.

Для приложений на других языках программирования#

Для приложений на других языках программирования рекомендуется использовать следующие библиотеки:

  • python: python-json-logger

  • go: simplejson