Strukturerad programlogg för Azure Spring Apps

Kommentar

Azure Spring Apps är det nya namnet på Azure Spring Cloud-tjänsten. Även om tjänsten har ett nytt namn ser du det gamla namnet på vissa platser ett tag medan vi arbetar med att uppdatera tillgångar som skärmbilder, videor och diagram.

Den här artikeln gäller för: ✔️ Basic/Standard ✔️ Enterprise

Den här artikeln beskriver hur du genererar och samlar in strukturerade programloggdata i Azure Spring Apps. Med rätt konfiguration tillhandahåller Azure Spring Apps användbar programloggfråga och analys via Log Analytics.

Krav för loggschema

För att förbättra loggfrågeupplevelsen måste en programlogg vara i JSON-format och överensstämma med ett schema. Azure Spring Apps använder det här schemat för att parsa ditt program och strömma till Log Analytics.

Kommentar

Om du aktiverar JSON-loggformatet blir det svårt att läsa loggströmningsutdata från konsolen. Lägg till argumentet i --format-jsonaz spring app logs CLI-kommandot för att hämta läsbara utdata för människor. Se Formatera JSON-strukturerade loggar.

JSON-schemakrav:

Json-nyckel Json-värdetyp Obligatoriskt Kolumn i Log Analytics beskrivning
timestamp sträng Ja AppTimestamp tidsstämpel i UTC-format
Logger sträng Nej Logger Logger
nivå sträng Nej CustomLevel loggnivå
tråd sträng Nej Tråd tråd
meddelande sträng Nej Meddelande loggmeddelande
Stacktrace sträng Nej StackTrace undantagsstackspårning
exceptionClass sträng Nej ExceptionClass undantagsklassnamn
Mdc kapslad JSON Nej mappad diagnostikkontext
mdc.traceId sträng Nej TraceId spårnings-ID för distribuerad spårning
mdc.spanId sträng Nej SpanId span-ID för distribuerad spårning
  • Fältet "tidsstämpel" krävs och ska vara i UTC-format. Alla andra fält är valfria.
  • "traceId" och "spanId" i fältet "mdc" används i spårningssyfte.
  • Logga varje JSON-post på en rad.

Exempel på loggpost

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

Begränsningar

Varje rad i JSON-loggarna har högst 16 K byte. Om JSON-utdata för en enskild loggpost överskrider den här gränsen delas den upp i flera rader och varje rårad samlas in i Log kolumnen utan att parsas strukturellt.

I allmänhet sker den här situationen vid undantagsloggning med djup stacktrace, särskilt när AppInsights In-Process Agent är aktiverad. Använd gränsinställningar för stacktrace-utdata (se konfigurationsexemplen nedan) för att säkerställa att de slutliga utdata parsas korrekt.

Generera schemakompatibel JSON-logg

För Spring-program kan du generera förväntat JSON-loggformat med hjälp av vanliga loggningsramverk, till exempel Logback och Log4j2.

Logga med logback

När du använder Spring Boot-starter används Logback som standard. För Logback-appar använder du logstash-encoder för att generera JSON-formaterad logg. Den här metoden stöds i Spring Boot version 2.1 eller senare.

Proceduren:

  1. Lägg till logstash-beroende i pom.xml filen.

    <dependency>
        <groupId>net.logstash.logback</groupId>
        <artifactId>logstash-logback-encoder</artifactId>
        <version>6.5</version>
    </dependency>
    
  2. Uppdatera konfigurationsfilen logback-spring.xml för att ange JSON-formatet.

    <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. När du använder loggningskonfigurationsfilen med -spring suffix som logback-spring.xmlkan du ange loggningskonfigurationen baserat på den springaktiva profilen.

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

    För lokal utveckling kör du Spring-programmet med JVM-argumentet -Dspring.profiles.active=dev. Sedan kan du se loggar som kan läsas av människor i stället för JSON-formaterade rader.

Logga med log4j2

För log4j2-appar använder du json-template-layout för att generera JSON-formaterad logg. Den här metoden stöds i Spring Boot version 2.1+.

Proceduren:

  1. Exkludera spring-boot-starter-logging från spring-boot-starterlägger du till beroenden spring-boot-starter-log4j2log4j-layout-template-json i pom.xml filen.

    <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. Förbered en JSON-layoutmallfil jsonTemplate.json i din klasssökväg.

    {
        "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. Använd den här JSON-layoutmallen i konfigurationsfilen 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>
    

Analysera loggarna i Log Analytics

När programmet har konfigurerats korrekt strömmas programkonsolloggen till Log Analytics. Strukturen möjliggör effektiv fråga i Log Analytics.

Kontrollera loggstrukturen i Log Analytics

Följ dessa steg:

  1. Gå till tjänstöversiktssidan för din tjänstinstans.

  2. Välj posten Loggar i avsnittet Övervakning .

  3. Kör den här frågan.

    AppPlatformLogsforSpring
    | where TimeGenerated > ago(1h)
    | project AppTimestamp, Logger, CustomLevel, Thread, Message, ExceptionClass, StackTrace, TraceId, SpanId
    
  4. Programloggar returneras enligt följande bild:

    Screenshot of the Azure portal showing the log Results pane.

Visa loggposter som innehåller fel

Om du vill granska loggposter som har ett fel kör du följande fråga:

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

Använd den här frågan för att hitta fel eller ändra frågetermerna för att hitta en specifik undantagsklass eller felkod.

Visa loggposter för ett specifikt traceId

Om du vill granska loggposter för ett specifikt spårnings-ID "trace_id" kör du följande fråga:

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

Nästa steg