Log do aplicativo estruturado para o Azure Spring Apps

Observação

Azure Spring Apps é o novo nome do serviço Azure Spring Cloud. Embora o serviço tenha um novo nome, você verá o nome antigo em alguns locais por um tempo enquanto trabalhamos para atualizar ativos como capturas de tela, vídeos e diagramas.

Este artigo se aplica ao: ✔️ nível Básico/Standard ✔️ nível Enterprise

Este artigo explica como gerar e coletar dados do log do aplicativo estruturado no Azure Spring Apps. Com a configuração adequada, o Azure Spring Apps fornece consulta e análise úteis de log do aplicativo por meio do Log Analytics.

Requisitos do esquema do log

Para melhorar a experiência de consulta de log, um log de aplicativo precisa estar no formato JSON e em conformidade com um esquema. O Azure Spring Apps usa esse esquema para analisar o aplicativo e transmitir para o Log Analytics.

Observação

A habilitação do formato de log JSON dificulta a leitura da saída de streaming de log no console. Para obter uma saída legível, acrescente o argumento --format-json no comando az spring app logs da CLI. Consulte Formatar logs JSON estruturados.

Requisitos do esquema do JSON:

Chave Json Tipo de valor Json Obrigatório Coluna no Log Analytics Descrição
timestamp string Sim AppTimestamp carimbo de data/hora no formato UTC
agente string Não Agente agente
level string Não CustomLevel nível de log
thread string Não Thread thread
message string No Mensagem mensagem de log
stackTrace string Não StackTrace rastreamento de pilha de exceção
exceptionClass string Não ExceptionClass nome da classe de exceção
mdc aninhado JSON Não contexto de diagnóstico mapeado
mdc.traceId string Não TraceId ID de rastreamento para rastreamento distribuído
mdc.spanId string Não SpanID ID de intervalo para rastreamento distribuído
  • O campo "carimbo de data/hora" é obrigatório e deve estar no formato UTC, todos os outros campos são opcionais.
  • "traceId" e "spanId" no campo "mdc" são usados para fins de rastreamento.
  • Registre cada registro JSON em uma linha.

Exemplo de registro de log

{"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"}

Limitações

Cada linha dos logs JSON tem no máximo 16 K bytes. Se a saída JSON de um único registro de log exceder esse limite, ela será dividida em várias linhas e cada linha bruta será coletada na coluna sem ser analisada Log estruturalmente.

Geralmente, essa situação acontece no log de exceções com deep stacktrace, especialmente quando o AppInsights In-Process Agent está habilitado. Aplique as configurações de limite à saída do rastreamento de pilha (consulte os exemplos de configuração abaixo) para garantir que a saída final seja analisada corretamente.

Gerar log JSON compatível com esquema

Para aplicativos Spring, você pode gerar o formato de log JSON esperado usando estruturas de log comuns, como Logback e Log4j2.

Log com logback

Ao usar os iniciadores do Spring Boot, o Logback é usado por padrão. Para aplicativos Logback, use logstash-encoder para gerar log formatado JSON. Este método é suportado no Spring Boot versão 2.1 ou posterior.

Procedimento:

  1. Adicione a dependência logstash no arquivo pom.xml.

    <dependency>
        <groupId>net.logstash.logback</groupId>
        <artifactId>logstash-logback-encoder</artifactId>
        <version>6.5</version>
    </dependency>
    
  2. Atualize o arquivo de configuração logback-spring.xml para definir o formato 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. Ao usar o arquivo de configuração de log com um sufixo -spring, como logback-spring.xml, defina a configuração de log com base no perfil ativo do 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>
    

    Para o desenvolvimento local, execute o aplicativo Spring com o argumento JVM -Dspring.profiles.active=dev e você verá logs legíveis em vez de linhas formatadas em JSON.

Registrar com log4j2

Para aplicativos log4j2, use json-template-layout para gerar o log formatado em JSON. Esse método é compatível com o Spring Boot versão 2.1+.

Procedimento:

  1. Exclua spring-boot-starter-logging de spring-boot-starter e adicione as dependências spring-boot-starter-log4j2 e log4j-layout-template-json no arquivo 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. Prepare um arquivo de modelo de layout JSON jsonTemplate.json em seu caminho de classe.

    {
        "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. Use este modelo de layout JSON em seu arquivo de configuração 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>
    

Analisar os logs no Log Analytics

Depois que o aplicativo for configurado corretamente, o log do console do aplicativo será transmitido para o Log Analytics. A estrutura permite uma consulta eficiente no Log Analytics.

Verificar a estrutura do log no Log Analytics

Use este procedimento:

  1. Vá para a página Visão geral do serviço da sua instância de serviço.

  2. Selecione a entrada Logs na seção Monitoramento.

  3. Execute esta consulta.

    AppPlatformLogsforSpring
    | where TimeGenerated > ago(1h)
    | project AppTimestamp, Logger, CustomLevel, Thread, Message, ExceptionClass, StackTrace, TraceId, SpanId
    
  4. Os logs de aplicativo retornam conforme mostrado na imagem a seguir:

    Screenshot of the Azure portal showing the log Results pane.

Mostrar as entradas de log contendo erros

Para analisar as entradas de log que têm erro, execute a seguinte consulta:

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

Use essa consulta para localizar erros ou modificar os termos da consulta para localizar uma classe de exceção ou um código de erro específicos.

Mostrar as entradas de log para uma traceId específica

Para analisar as entradas de log de uma "trace_id" (ID de rastreamento) específica, execute a seguinte consulta:

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

Próximas etapas