Поделиться через


Структурированный журнал приложений для Azure Spring Apps

Note

Планы "Базовый", "Стандартный" и "Корпоративный" вступили в пенсионный период 17 марта 2025 года. Дополнительные сведения см. в объявлении о выходе на пенсию в Azure Spring Apps.

Эта статья относится к:✅ Basic/Standard ✅ Enterprise

В этой статье объясняется, как создавать и собирать структурированные данные журнала приложений в Azure Spring Apps. При правильной настройке Azure Spring Apps предоставляет полезный запрос журнала приложений и анализ с помощью Log Analytics.

Требования к схеме журнала

Чтобы улучшить взаимодействие с запросами к журналам, журнал приложений должен быть в формате JSON и соответствовать схеме. Azure Spring Apps использует эту схему для разбора вашего приложения и передачи в Log Analytics.

Note

Включение формата журнала JSON затрудняет чтение выходных данных потоковой передачи журналов из консоли. Чтобы получить читаемый человеком вывод, добавьте аргумент --format-json в команду az spring app logs CLI. См . раздел "Формат структурированных журналов JSON".

Требования к схеме JSON:

Ключ JSON Тип значения JSON Required Колонка в Log Analytics Description
timestamp string Yes AppTimestamp метка времени в формате UTC
logger string No Logger logger
level string No CustomLevel Уровень журнала
thread string No Thread thread
message string No Message Сообщение журнала
stackTrace string No StackTrace трассировка стека исключений
exceptionClass string No ExceptionClass Имя класса исключений
mdc вложенный JSON No сопоставленный контекст диагностики
mdc.traceId string No TraceId Идентификатор трассировки для дистрибутивного трассирования
mdc.spanId string No SpanId Идентификатор диапазона для распределенной трассировки
  • Поле "метка времени" является обязательным и должно быть в формате UTC, все остальные поля являются необязательными.
  • Для трассировки используются traceId и spanId в поле mdc.
  • Запишите каждую запись JSON в одной строке.

Пример записи журнала

{"timestamp":"2021-01-08T09:23:51.280Z","logger":"com.example.demo.HelloController","level":"ERROR","thread":"http-nio-1456-exec-4","mdc":{"traceId":"c84f8a897041f634","spanId":"c84f8a897041f634"},"stackTrace":"java.lang.RuntimeException: get an exception\r\n\tat com.example.demo.HelloController.throwEx(HelloController.java:54)\r\n\","message":"Got an exception","exceptionClass":"RuntimeException"}

Limitations

Каждая строка журналов JSON имеет не более 16 КБ. Если выходные данные JSON одной записи журнала превышают это ограничение, они разбиваются на несколько строк, и каждая необработанная строка собирается в Log столбец без структурного анализа.

Как правило, эта ситуация возникает при ведении журнала исключений с глубоким стеком вызовов, особенно если агент AppInsights In-Process включен. Примените параметры ограничения к выходным данным stacktrace (см. приведенные ниже примеры конфигурации), чтобы обеспечить правильный анализ окончательных выходных данных.

Создание журнала JSON, совместимого с схемой

Для приложений Spring можно создать ожидаемый формат журнала JSON с помощью общих платформ ведения журнала, таких как Logback иLog4j2.

Логирование с использованием Logback

При использовании стартеров Spring Boot по умолчанию используется Logback. Для приложений Logback используйте логстэш-энкодер для создания журнала в формате JSON. Этот метод поддерживается в Spring Boot версии 2.1 или более поздней.

Процедура:

  1. Добавьте зависимость logstash в файл pom.xml .

    <dependency>
        <groupId>net.logstash.logback</groupId>
        <artifactId>logstash-logback-encoder</artifactId>
        <version>6.5</version>
    </dependency>
    
  2. Обновите logback-spring.xml файл конфигурации, чтобы задать формат JSON.

    <configuration>
        <appender name="stdout" class="ch.qos.logback.core.ConsoleAppender">
            <encoder class="net.logstash.logback.encoder.LoggingEventCompositeJsonEncoder">
                <providers>
                    <timestamp>
                        <fieldName>timestamp</fieldName>
                        <timeZone>UTC</timeZone>
                    </timestamp>
                    <loggerName>
                        <fieldName>logger</fieldName>
                    </loggerName>
                    <logLevel>
                        <fieldName>level</fieldName>
                    </logLevel>
                    <threadName>
                        <fieldName>thread</fieldName>
                    </threadName>
                    <nestedField>
                        <fieldName>mdc</fieldName>
                        <providers>
                            <mdc />
                        </providers>
                    </nestedField>
                    <stackTrace>
                        <fieldName>stackTrace</fieldName>
                        <!-- maxLength - limit the length of the stack trace -->
                        <throwableConverter class="net.logstash.logback.stacktrace.ShortenedThrowableConverter">
                            <maxDepthPerThrowable>200</maxDepthPerThrowable>
                            <maxLength>14000</maxLength>
                            <rootCauseFirst>true</rootCauseFirst>
                        </throwableConverter>
                    </stackTrace>
                    <message />
                    <throwableClassName>
                        <fieldName>exceptionClass</fieldName>
                    </throwableClassName>
                </providers>
            </encoder>
        </appender>
        <root level="info">
            <appender-ref ref="stdout" />
        </root>
    </configuration>
    
  3. При использовании файла конфигурации ведения журнала с суффиксом -spring , например logback-spring.xml, можно задать конфигурацию ведения журнала на основе активного профиля Spring.

    <configuration>
        <springProfile name="dev">
            <!-- JSON appender definitions for local development, in human readable format -->
            <include resource="org/springframework/boot/logging/logback/defaults.xml" />
            <include resource="org/springframework/boot/logging/logback/console-appender.xml" />
            <root level="info">
                <appender-ref ref="CONSOLE" />
            </root>
        </springProfile>
    
        <springProfile name="!dev">
            <!-- JSON appender configuration from previous step, used for staging / production -->
            ...
        </springProfile>
    </configuration>
    

    Для локальной разработки запустите приложение Spring с аргументом -Dspring.profiles.active=dev JVM, и тогда вы сможете видеть человеко-читаемые логи вместо форматированных строк JSON.

Логирование с использованием log4j2

Для приложений log4j2 используйте макет json-template-layout для создания форматированного журнала JSON. Этот метод поддерживается в Spring Boot версии 2.1+.

Процедура:

  1. Исключите spring-boot-starter-logging из spring-boot-starter, добавьте зависимости spring-boot-starter-log4j2, log4j-layout-template-json в ваш файл pom.xml.

    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
        <exclusions>
            <exclusion>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-logging</artifactId>
            </exclusion>
        </exclusions>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-log4j2</artifactId>
    </dependency>
    <dependency>
        <groupId>org.apache.logging.log4j</groupId>
        <artifactId>log4j-layout-template-json</artifactId>
        <version>2.14.0</version>
    </dependency>
    
  2. Подготовьте файл шаблона макета JSON в каталоге вашего класса jsonTemplate.json.

    {
        "mdc": {
            "$resolver": "mdc"
        },
        "exceptionClass": {
            "$resolver": "exception",
            "field": "className"
        },
        "stackTrace": {
            "$resolver": "exception",
            "field": "stackTrace",
            "stringified": true
        },
        "message": {
            "$resolver": "message",
            "stringified": true
        },
        "thread": {
            "$resolver": "thread",
            "field": "name"
        },
        "timestamp": {
            "$resolver": "timestamp",
            "pattern": {
                "format": "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'",
                "timeZone": "UTC"
            }
        },
        "level": {
            "$resolver": "level",
            "field": "name"
        },
        "logger": {
            "$resolver": "logger",
            "field": "name"
        }
    }
    
  3. Используйте этот шаблон макета JSON в log4j2-spring.xml файле конфигурации.

    <configuration>
        <appenders>
            <console name="Console" target="SYSTEM_OUT">
                <!-- maxStringLength - limit the length of the stack trace -->
                <JsonTemplateLayout eventTemplateUri="classpath:jsonTemplate.json" maxStringLength="14000" />
            </console>
        </appenders>
        <loggers>
            <root level="info">
                <appender-ref ref="Console" />
            </root>
        </loggers>
    </configuration>
    

Анализ журналов в Log Analytics

После правильной настройки приложения журнал консоли приложения передается в Log Analytics. Структура обеспечивает эффективный запрос в Log Analytics.

Проверка структуры журнала в Log Analytics

Это можно сделать следующим образом:

  1. Перейдите на обзорную страницу экземпляра вашей службы.

  2. Выберите запись журнала в разделе Мониторинг.

  3. Запустите этот запрос.

    AppPlatformLogsforSpring
    | where TimeGenerated > ago(1h)
    | project AppTimestamp, Logger, CustomLevel, Thread, Message, ExceptionClass, StackTrace, TraceId, SpanId
    
  4. Журналы приложений выводятся, как показано на следующем рисунке.

    Снимок экрана: портал Azure с областью результатов журнала.

Отображение записей журнала, содержащих ошибки

Чтобы просмотреть записи журнала с ошибкой, выполните следующий запрос:

AppPlatformLogsforSpring
| where TimeGenerated > ago(1h) and CustomLevel == "ERROR"
| project AppTimestamp, Logger, ExceptionClass, StackTrace, Message, AppName
| sort by AppTimestamp

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

Отображение записей журнала для определенного идентификатора traceId

Чтобы просмотреть записи журнала для определенного идентификатора трассировки "trace_id", выполните следующий запрос:

AppPlatformLogsforSpring
| where TimeGenerated > ago(1h)
| where TraceId == "trace_id"
| project AppTimestamp, Logger, TraceId, SpanId, StackTrace, Message, AppName
| sort by AppTimestamp

Дальнейшие шаги