Migrar el registro a los entornos de ejecución de Java de segunda generación

Algunos aspectos del registro en los entornos de ejecución de segunda generación (Java 11 o versiones posteriores) son diferentes de los del entorno de ejecución de primera generación (Java 8). A diferencia del tiempo de ejecución de primera generación, en los tiempos de ejecución de segunda generación, los registros de aplicaciones no se agrupan en los registros de solicitudes del Explorador de registros. Además, en los tiempos de ejecución de segunda generación, App Engine escribe cada registro de aplicación asociado a una solicitud como una entrada de registro independiente en Cloud Logging.

En esta guía se describe cómo puedes implementar los mismos métodos de registro que usaste en tus aplicaciones de tiempo de ejecución de primera generación y obtener resultados de filtrado y correlación de registros casi idénticos al migrar tu aplicación a Java 11 o versiones posteriores.

Diferencias principales

En la siguiente tabla se muestran las diferencias en el registro entre los runtimes de primera y segunda generación:

Tiempo de ejecución de primera generación (Java 8) Runtimes de segunda generación (Java 11 o versiones posteriores)
Registros de solicitudes y de aplicaciones (también llamados registros de aplicaciones) App Engine inserta todos los registros de la aplicación en el registro de solicitudes. App Engine no inserta registros de aplicaciones en el registro de solicitudes.
stdout y stderr App Engine inserta los registros escritos en stdout y stderr en el registro de solicitudes. App Engine no inserta los registros escritos en stdout y stderr.
Registros de la plataforma App Engine App Engine no emite registros internos de la plataforma. App Engine emite registros internos de la plataforma durante el inicio o el cierre de una instancia con el nombre de registro /var/log/google_init.log.
Cuota de la API Cloud Logging Cada solicitud corresponde a una escritura de Cloud Logging. Cada entrada de registro de aplicación asociada a una solicitud corresponde a una escritura de Cloud Logging. El uso de la API de Cloud Logging aumenta en los tiempos de ejecución de segunda generación.

Registros de solicitudes y de aplicaciones

El comportamiento de registro en los tiempos de ejecución de primera y segunda generación difiere de las siguientes formas:

  • En el tiempo de ejecución de primera generación, App Engine inserta los registros de la aplicación en el campo protoPayload.line de los registros de solicitudes. Para ver los registros de la aplicación, despliega una solicitud en el Explorador de registros.

    En la siguiente imagen se muestran los registros de solicitudes y de aplicaciones correlacionados en el runtime de primera generación:

    Registros correlacionados en Java 8

  • En los tiempos de ejecución de segunda generación, los registros de solicitudes no contienen entradas de registro de aplicaciones porque el campo protoPayload.line no está presente en el registro de solicitudes. En su lugar, App Engine registra cada registro de aplicación como una entrada independiente. El nombre del registro depende de la configuración de registro. var/log/app contiene registros emitidos mediante frameworks de registro estándar, como java.util.logging o Simple Logging Facade for Java (SLF4J). Los registros stderr y stdout contienen registros de aplicaciones que se registran mediante System.err.print() o System.out.print().

    En la siguiente imagen se muestran los registros de solicitudes y de aplicaciones independientes en los runtimes de segunda generación:

    Registros independientes en Java 11

stdout y stderr

En el tiempo de ejecución de primera generación, App Engine considera que los registros emitidos a stdout y stderr son registros de aplicaciones y agrupa automáticamente estas entradas de registro de aplicaciones en el registro de solicitudes asociado.

En los tiempos de ejecución de segunda generación, App Engine no correlaciona los registros emitidos con stdout y stderr de forma predeterminada. Para agrupar las entidades de registro de aplicaciones con el registro de solicitudes mediante stdout y stderr, sigue las instrucciones de Escribir registros estructurados en stdout y stderr.

No recomendamos registrarse en stdout y stderr, ya que algunos registros de la plataforma App Engine (JVM, Jetty y registros de infraestructura interna) también se emiten en stderr. Los registros de la aplicación y de la plataforma aparecen junto con el stderr nombre del registro, lo que genera ambigüedad. Esto se exagera en los tiempos de ejecución de segunda generación, ya que App Engine tiene un mayor volumen de registros de plataforma.

Registros de la plataforma App Engine

En el tiempo de ejecución de primera generación, App Engine no emite registros de plataforma.

En los tiempos de ejecución de segunda generación, App Engine emite registros de plataforma durante el inicio o el cierre de instancias con el nombre de registro /var/log/google_init.log.

Puedes ignorar los registros de la plataforma sin problema. Para que no se muestren estos registros, añade un filtro a Explorador de registros con la consulta logName="/var/log/google_init.log".

En la siguiente imagen se muestran los registros de la plataforma en los tiempos de ejecución de segunda generación:

Registros de la plataforma

Cuota de la API de Cloud Logging

En el tiempo de ejecución de primera generación, App Engine inserta todos los registros de la aplicación emitidos durante una solicitud en un único registro de solicitud y envía la solicitud insertada a Cloud Logging. Cada solicitud corresponde a una escritura de Cloud Logging.

En los tiempos de ejecución de segunda generación, App Engine envía cada registro de aplicación a Cloud Logging en entradas de registro independientes, lo que provoca un aumento del número total de escrituras de Cloud Logging por solicitud.

Google Cloud determina la facturación en función del almacenamiento general que usa Cloud Logging. Aunque el almacenamiento total necesario para los registros no aumente de forma significativa, las escrituras por minuto sí lo harán, en función de cuántos registros de aplicaciones escriba App Engine por solicitud. Si tu aplicación supera la cuota de escritura de Cloud Logging, puedes solicitar un aumento de tu cuota de uso.

Para obtener más información, consulta los precios de Cloud Logging.

Visión general del proceso de migración

Aunque los registros de aplicaciones no estén insertados en los registros de solicitudes de los runtimes de segunda generación, es posible mantener la experiencia de visualización de registros como en las aplicaciones de primera generación.

Puedes elegir una de las siguientes opciones para configurar el registro en los tiempos de ejecución de segunda generación:

Usa el paquete java.util.logging (JUL).

Si tus aplicaciones que usan el tiempo de ejecución de primera generación implementan el java.util.logging paquete para todos los requisitos de registro, no será necesario hacer cambios en el código para migrar a los tiempos de ejecución de segunda generación.

En el siguiente ejemplo se muestra cómo puedes usar el paquete java.util.logging para registrarte en los tiempos de ejecución de segunda generación:

    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");
      }
    }

Agrupar los registros de aplicaciones con el registro de solicitudes

En los tiempos de ejecución de segunda generación, el campo protoPayload.line del registro de solicitudes no contiene registros de aplicaciones. El Explorador de registros usa el campo trace para agrupar los registros de solicitudes y de aplicaciones. El paquete java.util.logging añade automáticamente el ID de seguimiento a todos los registros de solicitudes y de aplicaciones. Para ver los registros correlacionados en el Explorador de registros, consulta Ver registros correlacionados.

Usar Simple Logging Facade for Java (SLF4J)

SLF4J es la interfaz de registro más popular que se usa en aplicaciones Java. Al ser una fachada, la interfaz SLF4J es independiente de la plataforma de su backend de registro, lo que te permite elegir cualquier backend adecuado para tus aplicaciones.

En la siguiente imagen se muestran las opciones de integración de dos back-ends de SLF4J, incluida la biblioteca java.util.logging y el appender Logback:

Información general sobre SLF4J

SLF4J con el paquete java.util.logging

SLF4J te permite integrar tu aplicación con Cloud Logging cuando usas SLF4J con java.util.logging como backend de registro. De forma predeterminada, App Engine añade un ID de rastreo a todos los registros de solicitudes y de aplicaciones. Este mecanismo permite agrupar los registros de solicitudes y de aplicaciones en el explorador de registros.

Para implementar SLF4J con java.util.logging, sigue estos pasos:

  1. Añade la dependencia slf4j-jdk14.jar a tu archivo pom.xml. El archivo slf4j-jdk14.jar proporciona la integración del backend para la 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. Crea un archivo WEB-INF/logging.properties para añadir configuraciones personalizadas:

    com.example.appengine.java8.HelloAppEngine.level = INFO
    
  3. Actualiza el archivo appengine-web.xml para incluir el valor <property> de WEB-INF/logging.properties:

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

En la siguiente imagen se muestra cómo SLF4J con java.util.logging añade automáticamente el ID de rastreo a un registro de aplicación:

Agrupar los registros de aplicaciones por solicitud con ID de seguimiento

Para ajustar la vista del Explorador de registros a una vista centrada en las solicitudes, como la del tiempo de ejecución de primera generación, consulta Ver registros correlacionados.

Usar SLF4J con el appender Logback

Si tus aplicaciones de tiempo de ejecución de primera generación usan la implementación integrada de SLF4J con Logback, debes actualizar tu código fuente e implementar pasos adicionales para agrupar los registros de solicitudes y de aplicaciones.

Para integrar tu aplicación con Cloud Logging, sigue estos pasos:

  1. Añade el appender google-cloud-logging-logback a tu archivo pom.xml para instalar el appender de registro de 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. Crea un elemento para mejorar el registro que añada un ID de seguimiento a cada campo LogEntry. La siguiente clase TraceIdLoggingEnhancer usa la API ApiProxy para obtener el ID de seguimiento asociado a una solicitud:

      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. Añade la configuración del appender de Cloud Logging en el archivo logback.xml para configurar Logback. El framework Logback gestiona la configuración a través del archivo logback.xml en 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>
    

    En la siguiente imagen se muestra la estructura final del directorio de la aplicación:

    Estructura de directorios

Ver registros correlacionados

Puedes ver los registros correlacionados en el Explorador de registros mediante el campo ID de traza de cada entrada de registro. Para ver los registros correlacionados en el explorador de registros, sigue estos pasos:

  1. En el panel de navegación de la Google Cloud consola, selecciona Logging y, a continuación, Explorador de registros:

    Ir a Explorador de registros

  2. En Resource Type (Tipo de recurso), selecciona GAE Application (Aplicación de GAE).

  3. Para ver y correlacionar los registros de solicitudes, en Nombre de registro, selecciona request_log. También puede correlacionar por registros de solicitudes. Para ello, haga clic en Correlacionar por y seleccione request_log:

    Correlacionar registros

  4. En el panel Resultados de la consulta, para desplegar una entrada de registro, haz clic en Desplegar. Al desplegarlo, cada registro de solicitudes mostrará los registros de aplicaciones asociados.