Migre o registo para runtimes Java de segunda geração

Alguns aspetos do início de sessão nos tempos de execução de segunda geração (Java 11 ou superior) são diferentes do tempo de execução de primeira geração (Java 8). Ao contrário do tempo de execução de primeira geração, nos tempos de execução de segunda geração, os registos da app não são agrupados em registos de pedidos no Explorador de registos. Além disso, nos runtimes de segunda geração, o App Engine escreve cada registo de app associado a um pedido como uma entrada de registo separada no Cloud Logging.

Este guia descreve como pode implementar os mesmos métodos de registo que usou nas apps de tempo de execução de primeira geração e alcançar resultados de filtragem e correlação de registos quase idênticos quando migrar a sua app para o Java 11 ou superior.

Principais diferenças

A tabela seguinte aborda as diferenças no registo entre os runtimes de primeira e segunda geração:

Tempo de execução de primeira geração (Java 8) Tempos de execução de segunda geração (Java 11 ou superior)
Registos de pedidos e apps (também denominados registos de aplicações) O App Engine incorpora todos os registos de apps no registo de pedidos. O App Engine não incorpora registos de apps no registo de pedidos.
stdout e stderr O App Engine incorpora registos escritos em stdout e stderr no registo de pedidos. O App Engine não incorpora registos escritos em stdout e stderr.
Registos da plataforma do App Engine O App Engine não emite registos internos da plataforma. O App Engine emite registos internos da plataforma durante o arranque ou o encerramento de uma instância com o nome do registo /var/log/google_init.log.
Quota da Cloud Logging API Cada pedido corresponde a uma gravação do Cloud Logging. Cada entrada de registo da app associada a um pedido corresponde a uma gravação do Cloud Logging. A utilização da API Cloud Logging aumenta nos tempos de execução de segunda geração.

Solicite registos e registos de apps

O comportamento de registo nos runtimes de primeira e segunda geração difere das seguintes formas:

  • No tempo de execução de primeira geração, o App Engine incorpora os registos da app no campo protoPayload.line dos registos de pedidos. Pode ver os registos da app expandindo um pedido no Explorador de registos.

    A imagem seguinte mostra os registos de pedidos e de apps correlacionados no tempo de execução de primeira geração:

    Registos correlacionados em Java 8

  • Nos tempos de execução de segunda geração, os registos de pedidos não contêm entradas de registo da app porque o campo protoPayload.line está ausente no registo de pedidos. Em alternativa, o App Engine regista cada registo da app como uma entrada separada. O nome do registo depende da sua configuração de registo. var/log/app contém registos emitidos usando frameworks de registo padrão, como java.util.logging ou a Simple Logging Facade for Java (SLF4J). Os registos stderr e stdout contêm registos de apps que são registados através de System.err.print() ou System.out.print().

    A imagem seguinte mostra registos de pedidos e de apps separados nos runtimes de segunda geração:

    Separe os registos no Java 11

stdout e stderr

No tempo de execução de primeira geração, o App Engine considera os registos emitidos para stdout e stderr como registos da app e agrupa automaticamente estas entradas de registos da app no registo de pedidos associado.

Nos runtimes de segunda geração, o App Engine não correlaciona os registos emitidos para stdout e stderr por predefinição. Para agrupar entidades de registo de apps com o registo de pedidos usando stdout e stderr, siga as instruções em Escreva registos estruturados em stdout e stderr.

Não recomendamos o registo em stdout e stderr, uma vez que determinados registos da plataforma do App Engine (JVM, Jetty e registos de infraestrutura interna) também são emitidos para stderr. Os registos da app e os registos da plataforma aparecem juntamente com o nome do registo stderr, o que causa ambiguidade. Isto é exagerado nos tempos de execução de segunda geração, uma vez que o App Engine tem um volume mais elevado de registos da plataforma.

Registos da plataforma do App Engine

No tempo de execução de primeira geração, o App Engine não emite registos da plataforma.

Nos runtimes de segunda geração, o App Engine emite registos da plataforma durante o arranque ou o encerramento da instância com o nome do registo /var/log/google_init.log.

Pode ignorar com segurança os registos da plataforma. Para evitar ver estes registos, adicione um filtro ao Explorador de registos com a consulta logName="/var/log/google_init.log".

A imagem seguinte apresenta os registos da plataforma nos runtimes de segunda geração:

Registos da plataforma

Quota da Cloud Logging API

No tempo de execução de primeira geração, o App Engine incorpora todos os registos de apps emitidos durante um pedido num único registo de pedidos e envia o pedido incorporado para o Cloud Logging. Cada pedido corresponde a uma gravação do Cloud Logging.

Nos runtimes de segunda geração, o App Engine envia cada registo da app para o Cloud Logging em entradas de registo separadas, o que provoca um aumento no número total de escritas do Cloud Logging por pedido.

Google Cloud determina a faturação com base no armazenamento geral usado pelo Cloud Logging. Mesmo que o armazenamento geral necessário para os registos não aumente significativamente, o número de gravações por minuto aumenta, consoante o número de registos de apps que o App Engine escreve por pedido. Se a sua app exceder a quota de gravação do Cloud Logging, pode pedir um aumento na sua quota de utilização.

Para mais informações, consulte os preços do Cloud Logging.

Vista geral do processo de migração

Mesmo que os registos da app não estejam incorporados nos registos de pedidos nos runtimes de segunda geração, é possível manter a experiência de visualização de registos, como nas apps de primeira geração.

Pode escolher uma das seguintes opções para configurar o registo nos runtimes de segunda geração:

Use o pacote java.util.logging (JUL)

Se as suas apps que usam o tempo de execução de primeira geração implementarem o pacote java.util.logging para todos os requisitos de registo, a migração para tempos de execução de segunda geração não requer alterações ao código.

O exemplo seguinte mostra como pode usar o pacote java.util.logging para registar nos runtimes de segunda geração:

    package com.example.appengine.my_app;
    import java.io.IOException;
    import javax.servlet.annotation.WebServlet;
    import javax.servlet.http.*;
    import java.util.logging.Logger;

    @WebServlet(name = "HelloAppEngine", value = "/")
    public class HelloAppEngine extends HttpServlet {

      // Use the java.util.logging.Logger to log messages
      private static final Logger logger = Logger.getLogger(HelloAppEngine.class.getName());

      @Override
      public void doGet(HttpServletRequest request, HttpServletResponse response)
          throws IOException {
        // Sample log messages
        logger.info("Info message");
        logger.warning("Warning message");
        logger.severe("Severe message");

        response.setContentType("text/plain");
        response.getWriter().println("Hello App Engine");
      }
    }

Agrupe os registos da app com o registo de pedidos

Nos tempos de execução de segunda geração, o campo protoPayload.line no registo de pedidos não contém registos de apps. O Explorador de registos usa o campo trace para agrupar os registos de pedidos e os registos de apps. O pacote java.util.logging adiciona automaticamente o ID de rastreio a todos os registos de pedidos e apps. Para ver registos correlacionados no Explorador de registos, consulte o artigo Ver registos correlacionados.

Use a Simple Logging Facade for Java (SLF4J)

O SLF4J é a interface de registo mais popular usada em aplicações Java. Sendo uma fachada, a interface SLF4J é independente da plataforma do respetivo back-end de registo, o que lhe permite escolher qualquer back-end adequado para as suas apps.

A imagem seguinte mostra as opções de integração para dois backends SLF4J, incluindo a biblioteca java.util.logging e o appender Logback:

Vista geral do SLF4J

SLF4J com o pacote java.util.logging

O SLF4J permite-lhe integrar a sua app com o Cloud Logging quando usa o SLF4J com o java.util.logging como o back-end de registo. Por predefinição, o App Engine adiciona um ID de rastreio a todos os registos de pedidos e apps. Este mecanismo permite o agrupamento de registos de pedidos e de apps no Explorador de registos.

Para implementar o SLF4J com o java.util.logging, siga estes passos:

  1. Adicione a dependência slf4j-jdk14.jar ao ficheiro pom.xml. O ficheiro slf4j-jdk14.jar fornece a integração de back-end para a biblioteca java.util.logging:

    <!-- SLF4J interface -->
    <dependency>
      <groupId>org.slf4j</groupId>
      <artifactId>slf4j-api</artifactId>
      <version>2.0.4</version>
    </dependency>
    <!-- JUL implementation for SLF4J -->
    <dependency>
      <groupId>org.slf4j</groupId>
      <artifactId>slf4j-jdk14</artifactId>
      <version>2.0.9</version>
    </dependency>
    
  2. Crie um ficheiro WEB-INF/logging.properties para adicionar configurações personalizadas:

    com.example.appengine.java8.HelloAppEngine.level = INFO
    
  3. Atualize o ficheiro appengine-web.xml para incluir o valor <property> para WEB-INF/logging.properties:

    <system-properties>
      <property name="java.util.logging.config.file" value="WEB-INF/logging.properties"/>
    </system-properties>
    

A imagem seguinte mostra como o SLF4J com java.util.logging adiciona automaticamente o ID de rastreio a um registo de apps:

Agrupe os registos da app por pedido com o ID de rastreio

Para ajustar a vista do Explorador de registos a uma vista centrada nos pedidos, como o tempo de execução de primeira geração, consulte o artigo Veja registos correlacionados.

Use SLF4J com o anexo Logback

Se as suas apps de tempo de execução de primeira geração usarem a implementação incorporada do SLF4J com o Logback, tem de atualizar o código fonte e implementar passos adicionais para agrupar os registos de pedidos e de apps.

Para integrar a sua app com o Cloud Logging, siga estes passos:

  1. Adicione o anexo google-cloud-logging-logback ao seu ficheiro pom.xml para instalar o anexo de registo para o Logback:

     <!-- SLF4J interface -->
     <dependency>
           <groupId>org.slf4j</groupId>
           <artifactId>slf4j-api</artifactId>
           <version>2.0.4</version>
     </dependency>
    
     <!-- Logback JARs -->
     <dependency>
           <groupId>ch.qos.logback</groupId>
           <artifactId>logback-classic</artifactId>
           <version>1.3.6</version>
     </dependency>
     <dependency>
           <groupId>ch.qos.logback</groupId>
           <artifactId>logback-core</artifactId>
           <version>1.3.5</version>
     </dependency>
    
     <!-- Google Cloud logging appender for Logback -->
     <dependency>
       <groupId>com.google.cloud</groupId>
       <artifactId>google-cloud-logging-logback</artifactId>
     </dependency>
    
  2. Crie um melhoramento do registo para adicionar um ID de rastreio a cada campo LogEntry. A seguinte classe TraceIdLoggingEnhancer usa a API ApiProxy para obter o ID de rastreio associado a um pedido:

      import com.google.appengine.api.utils.SystemProperty;
      import com.google.cloud.logging.LogEntry;
      import com.google.cloud.logging.LoggingEnhancer;
    
      import com.google.apphosting.api.ApiProxy;
      import com.google.apphosting.api.ApiProxy.Environment;
    
      // Add trace ID to the log entry
      public class TraceIdLoggingEnhancer implements LoggingEnhancer {
    
        @Override
        public void enhanceLogEntry(LogEntry.Builder logEntry) {
          final String PROJECT_ID = SystemProperty.applicationId.get();
    
          Environment environment = ApiProxy.getCurrentEnvironment();
    
          if (environment instanceof ApiProxy.EnvironmentWithTrace) {
            ApiProxy.EnvironmentWithTrace environmentWithTrace = (ApiProxy.EnvironmentWithTrace) environment;
            environmentWithTrace
                .getTraceId()
                .ifPresent(
                    id ->
                      logEntry.setTrace(String.format("projects/%s/traces/%s", PROJECT_ID, id)));
          }
        }
      }
      // [END logging_enhancer]
    
  3. Adicione a configuração do anexador do Cloud Logging no ficheiro logback.xml para configurar o Logback. A framework Logback gere a configuração através do ficheiro logback.xml no WEB-INF/classes:

    <configuration>
      <appender name="CLOUD" class="com.google.cloud.logging.logback.LoggingAppender">
          <!-- This should be set to the new Logging Enhancer in the app code. -->
          <enhancer>com.example.appengine.my_app.enhancers.TraceIdLoggingEnhancer</enhancer>
          <resourceType>gae_app</resourceType>
      </appender>
      <root level="info">
          <appender-ref ref="CLOUD" />
      </root>
    </configuration>
    

    A imagem seguinte mostra a estrutura final do diretório de apps:

    Estrutura do diretório

Veja registos correlacionados

Pode ver os registos correlacionados no Explorador de registos através do campo ID de rastreio em cada entrada de registo. Para ver registos correlacionados no Explorador de registos:

  1. No painel de navegação da Google Cloud consola, selecione Registo e, de seguida, Explorador de registos:

    Aceda ao Explorador de registos

  2. Em Tipo de recurso, selecione Aplicação GAE.

  3. Para ver e correlacionar registos de pedidos, em Nome do registo, selecione request_log. Em alternativa, para estabelecer a correlação por registos de pedidos, clique em Estabelecer correlação por e selecione request_log:

    Correlacionar registos

  4. No painel Resultados da consulta, para expandir uma entrada do registo, clique em Expandir. Quando expandido, cada registo de pedidos mostra os registos da app associados.