Log de aplicativo estruturado para Azure Spring Apps

Nota

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

Este artigo aplica-se a: ✔️ Basic/Standard ✔️ Enterprise

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

Requisitos do esquema de log

Para melhorar a experiência de consulta de log, é necessário que um log de aplicativo esteja no formato JSON e esteja em conformidade com um esquema. O Azure Spring Apps usa esse esquema para analisar seu aplicativo e transmitir para o Log Analytics.

Nota

Habilitar o formato de log JSON dificulta a leitura da saída de streaming de log do console. Para obter uma saída legível por humanos, acrescente o --format-json argumento ao az spring app logs comando da CLI. Consulte Formatar logs estruturados JSON.

Requisitos do esquema JSON:

Json Chave Tipo de valor Json Obrigatório Coluna no Log Analytics Description
carimbo de data/hora string Sim Carimbo de data/hora do aplicativo carimbo de data/hora em formato UTC
Registador string Não Registador Registador
nível string Não Nível Personalizado nível de log
thread string Não Tópico thread
mensagem string Não Mensagem Mensagem de registo
stackTrace string Não StackTrace rastreamento de pilha de exceções
exceçãoClasse string Não Classe de exceção Nome da classe de exceção
MDC JSON aninhado 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 span 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 stacktrace (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.

O procedimento:

  1. Adicione dependência de logstash em seu pom.xml arquivo.

    <dependency>
        <groupId>net.logstash.logback</groupId>
        <artifactId>logstash-logback-encoder</artifactId>
        <version>6.5</version>
    </dependency>
    
  2. Atualize seu logback-spring.xml arquivo de configuração 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 sufixo como logback-spring.xml, você pode definir a configuração de log com -spring 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 desenvolvimento local, execute o aplicativo Spring com argumento -Dspring.profiles.active=devJVM e, em seguida, você pode ver logs legíveis por humanos em vez de linhas formatadas JSON.

Log com log4j2

Para aplicativos log4j2, use json-template-layout para gerar log formatado JSON. Este método é suportado no Spring Boot versão 2.1+.

O procedimento:

  1. Excluir spring-boot-starter-logging do spring-boot-starter, adicionar dependências spring-boot-starter-log4j2, log4j-layout-template-json no seu pom.xml ficheiro.

    <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 jsonTemplate.json de modelo de layout JSON no caminho da 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 log4j2-spring.xml arquivo de configuração.

    <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>
    

Analise os logs no Log Analytics

Depois que o aplicativo estiver 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

Utilize o seguinte procedimento:

  1. Vá para a página de 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 do aplicativo retornam conforme mostrado na imagem a seguir:

    Screenshot of the Azure portal showing the log Results pane.

Mostrar entradas de log contendo erros

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

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

Use esta consulta para localizar erros ou modifique os termos de consulta para localizar uma classe de exceção específica ou código de erro.

Mostrar entradas de log para um traceId específico

Para revisar as entradas de log para uma ID de rastreamento específica "trace_id", 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óximos passos