En este documento, se proporciona una descripción general del registro y la solución de problemas comunes con las bibliotecas cliente de Cloud para Java.
Logging
Existen dos formas de habilitar el registro para las bibliotecas cliente: con java.util.logging o con el registro de depuración de la biblioteca cliente con SLF4J.
Usa java.util.logging
Las bibliotecas cliente de Cloud para Java usan el paquete de la API de registro de Java (java.util.logging). Configurar el nivel de registro revela información que te ayuda a solucionar problemas, como la siguiente:
- Es el tiempo de la comunicación subyacente entre el cliente y el servidor.
- Encabezados de mensajes de solicitud y respuesta
- Mensajes detallados en las bibliotecas de dependencia subyacentes.
Para habilitar rápidamente el registro detallado de las bibliotecas cliente de Cloud para Java, crea un archivo logging.properties con el siguiente contenido:
# run java program pointing to this properties file with the java arg
# -Djava.util.logging.config.file=path/to/logging.properties
handlers=java.util.logging.ConsoleHandler
java.util.logging.SimpleFormatter.format=%1$tF %1$tT,%1$tL %4$-8s %3$-50s - %5$s %6$s%n
# --- ConsoleHandler ---
java.util.logging.ConsoleHandler.level=ALL
java.util.logging.ConsoleHandler.formatter=java.util.logging.SimpleFormatter
.level=INFO
# --- Specify logging level for certain packages ---
# com.google.api is for HTTP 1.1 layer
com.google.api.level=ALL
# io.grpc is for gRPC + Netty layer
io.grpc.level=FINE
# com.google.auth is for authentication
com.google.auth.level=FINE
# Example when you specify the storage library's level. This works when
# the target Cloud library uses the logging API.
com.google.cloud.storage.level=INFO
A continuación, ejecuta tu aplicación con -Djava.util.logging.config.file=path/to/logging.properties como VM argument, no como Program argument.
Si usas IntelliJ, especifica el argumento de VM en Run/Debug Configuration:

Si la JVM de tu programa se ejecuta con la configuración correcta, verás el registro a nivel FINE en tu consola.
Resultado de ejemplo:
2023-04-05 13:03:01,761 FINE com.google.auth.oauth2.DefaultCredentialsProvider - Attempting to load credentials from well known file: /usr/local/google/home/suztomo/.config/gcloud/application_default_credentials.json
2023-04-05 13:03:01,847 FINE io.grpc.ManagedChannelRegistry - Unable to find OkHttpChannelProvider
java.lang.ClassNotFoundException: io.grpc.okhttp.OkHttpChannelProvider
at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:581)
at java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(ClassLoaders.java:178)
at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:522)
at java.base/java.lang.Class.forName0(Native Method)
at java.base/java.lang.Class.forName(Class.java:315)
...
Esta es una forma de configurar el nivel de registro. Para obtener más información sobre el uso de la API de Logging de Java, consulta Descripción general de Logging de Java.
Registro de depuración de la biblioteca cliente (SLF4J)
Las bibliotecas cliente de Cloud incluyen el registro de depuración opcional que puede ayudarte a solucionar problemas relacionados con la integración de tu aplicación en la API. Cuando se activa el registro, los eventos clave, como las solicitudes y las respuestas, junto con las cargas útiles de datos y los metadatos, como los encabezados, se registran en el flujo de error estándar.
ADVERTENCIA: El registro de depuración de la biblioteca cliente incluye las cargas útiles de datos en texto sin formato, lo que podría incluir datos sensibles, como PII para ti o tus clientes, claves privadas o cualquier otro dato de seguridad que podría verse comprometido si se filtra. Siempre practica una buena higiene de datos con los registros de tu aplicación y sigue el principio de privilegio mínimo. Google también recomienda que el registro de depuración de la biblioteca cliente se habilite solo de forma temporal durante la depuración activa y no se use de forma permanente en la producción.
Requisitos
Nuestras bibliotecas admiten el registro de depuración con la interfaz SLF4J.
Las bibliotecas cliente y la BOM de bibliotecas no incluyen la dependencia slf4j-api. Deberás configurar las dependencias de registro, incluidas SLF4J y las implementaciones y configuraciones de registro correspondientes, antes de activar el registro de depuración de la biblioteca cliente.
NOTE: Debes tener SLF4J y los proveedores de registro correspondientes (p.ej., logback, log4j2, etcétera) en tu classpath para usar la función de registro de depuración de la biblioteca cliente. De lo contrario, no habrá registro de depuración, incluso si lo habilitas con la variable de entorno.
Habilita el registro con una variable de entorno
El registro de depuración está desactivado de forma predeterminada. El registro de depuración no se activa, a menos que se haga de forma explícita, incluso si se cumplen los requisitos previos.
Para habilitar el registro de depuración de la biblioteca cliente, establece la variable de entorno GOOGLE_SDK_JAVA_LOGGING en true, sin distinción entre mayúsculas y minúsculas.
Si no se configura o se establece cualquier otro valor, se inhabilita el registro de depuración de la biblioteca cliente.
Ejemplos de configuraciones de registros
En la documentación, se proporciona un ejemplo de registro de depuración con Logback.
Agrega dependencias de Logback a tu aplicación. Esto incorporará la dependencia de slf4j de forma transitiva. Los usuarios deben consultar la configuración de Logback para obtener las versiones más recientes. Puedes omitir este paso si tu aplicación ya tiene dependencias de Logback en la ruta de clase.
Si usas Maven, haz lo siguiente:
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>LATEST_VERSION</version>
</dependency>
Agrega el contenido al archivo de configuración de Logback si deseas ver registros de nivel DEBUG. Puedes omitir este paso si solo necesitas registros de nivel INFO. Para obtener más información, consulta la configuración de Logback.
<!-- set Client Library log level to DEBUG -->
<logger name="com.google.api" level="DEBUG"/>
<!-- set Auth Library log level to DEBUG -->
<logger name="com.google.auth" level="DEBUG"/>
ALPN no está configurado correctamente
Si ves excepciones relacionadas con ALPN is not configured properly, como las siguientes:
Caused by: java.lang.IllegalArgumentException: ALPN is not configured properly. See https://github.com/grpc/grpc-java/blob/master/SECURITY.md#troubleshooting for more information.
Usa el comprobador de compatibilidad para ver si tu entorno es compatible con los clientes basados en gRPC.
La incompatibilidad puede significar una de las siguientes situaciones:
- No estás en una plataforma compatible.
- Hay conflictos de classpath con
netty. - Ves alguno de los conflictos especificados en la guía para solucionar problemas de gRPC.
Soluciona problemas de ClassNotFoundException, NoSuchMethodError y NoClassDefFoundError
Estos errores suelen deberse a que hay varias versiones o versiones conflictivas de la misma dependencia en la ruta de clase. Estos conflictos de dependencia suelen ocurrir con guava o protobuf-java.
Varias fuentes pueden causar conflictos en la ruta de acceso a la clase:
- Hay varias versiones de la misma dependencia transitiva en el árbol de dependencias.
- Tu classpath de tiempo de ejecución tiene versiones de dependencias diferentes de las que especificaste en la compilación.
Por ejemplo, si tienes una dependencia directa o transitiva en la versión 19.0 de Guava y google-cloud-java usa la versión 30.0 de Guava, es posible que google-cloud-java use métodos de Guava que no existen en Guava 19.0 y provoquen NoSuchMethodError.
Del mismo modo, si tu ruta de acceso a la clase tiene una versión anterior de protobuf-java, pero google-cloud-java requiere una versión posterior, es posible que veas NoClassDefFoundError que no puede inicializar las clases de google-cloud-java.
Por ejemplo:
java.lang.NoClassDefFoundError: Could not initialize class com.google.pubsub.v1.PubsubMessage$AttributesDefaultEntryHolder
Valida el conflicto
Verifica el árbol de dependencias para ver si tienes varias versiones de las mismas dependencias:
$ mvn dependency:tree
Busca versiones de dependencias que puedan entrar en conflicto, como guava o protobuf-java.
Si experimentas el error solo durante el tiempo de ejecución, es posible que tu entorno de ejecución esté introduciendo archivos JAR en conflicto en la ruta de acceso de clase del tiempo de ejecución. Un caso típico es que Hadoop, Spark o algún otro software de servidor en el que se ejecuta tu aplicación tengan versiones conflictivas de los archivos JAR netty, guava o protobuf-java en la ruta de clase.
Detecta conflictos durante la compilación
Para detectar errores de vinculación de dependencias en el tiempo de compilación, agrega la regla de aplicación de Linkage Checker en tu pom.xml:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-enforcer-plugin</artifactId>
<version>3.0.0-M3</version>
<dependencies>
<dependency>
<groupId>com.google.cloud.tools</groupId>
<artifactId>linkage-checker-enforcer-rules</artifactId>
<version>1.5.7</version>
</dependency>
</dependencies>
<executions>
<execution>
<id>enforce-linkage-checker</id>
<!-- Important! Should run after compile -->
<phase>verify</phase>
<goals>
<goal>enforce</goal>
</goals>
<configuration>
<rules>
<LinkageCheckerRule
implementation="com.google.cloud.tools.dependencies.enforcer.LinkageCheckerRule"/>
</rules>
</configuration>
</execution>
</executions>
</plugin>
Sin embargo, no hay forma de detectar conflictos de classpath en el tiempo de ejecución. Debes saber perfectamente qué archivos JAR o clases se incluyen en la ruta de acceso de clases del entorno de ejecución, ya que cada entorno de servidor es diferente.
Cómo resolver el conflicto
Existen diferentes estrategias para resolver conflictos, pero debes comprender la causa raíz de los conflictos:
- Si controlas el árbol de dependencias, actualiza las dependencias en conflicto (por ejemplo, actualiza Guava). Este enfoque es el más sólido, pero puede requerir un esfuerzo significativo y varias versiones de la biblioteca para garantizar la compatibilidad.
- Si no puedes modificar ni enviar nuevas versiones de tus dependencias, importa
com.google.cloud:libraries-bom:25.1.0(o una versión más reciente) para seleccionar versiones de dependencias coherentes. Este enfoque simplifica la administración de dependencias. Por ejemplo, así puedes depender de versiones coherentes de Guava ycom.google.cloud:google-cloud-storagesin establecer explícitamente la versión de ninguna de ellas:
...
<dependencyManagement>
<dependencies>
<dependency>
<groupId>com.google.cloud</groupId>
<artifactId>libraries-bom</artifactId>
<version>25.1.0</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
...
<dependencies>
<dependency>
<groupId>com.google.cloud</groupId>
<artifactId>google-cloud-storage</artifactId>
</dependency>
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
</dependency>
...
</dependencies>
...
Las notas de la versión de libraries-bom muestran las bibliotecas de dependencias compatibles. Por ejemplo, https://github.com/googleapis/java-cloud-bom/releases/tag/v26.31.0 muestra lo siguiente:
These client libraries are built with the following Java libraries: - Guava: 32.1.3-jre - Protobuf Java: 3.25.2 - Google Auth Library: 1.22.0 - Google API Client: 2.2.0 - gRPC: 1.61.0 - GAX: 2.41.0 - Google Cloud Core: 2.31.0Si examinas el gráfico de dependencias de tu proyecto (
mvn dependency:tree -Dverbose,gradle dependenciesosbt dependencyTree), es posible que encuentres que algunas dependencias tienen versiones inesperadas, lo que podría causar conflictos de dependencias.Si cambiar las versiones de las dependencias introduce otros errores, considera sombreado de dependencias que entren en conflicto con las bibliotecas de Java. Google Cloud
Por ejemplo, para sombrear
guavayprotobuf-java:<plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-shade-plugin</artifactId> <version>...</version> <executions> <execution> <phase>package</phase> <goals> <goal>shade</goal> </goals> <configuration> <keepDependenciesWithProvidedScope>false</keepDependenciesWithProvidedScope> <relocations> <!-- move protobuf to a shaded package --> <relocation> <pattern>com.google.protobuf</pattern> <shadedPattern>myapp.shaded.com.google.protobuf</shadedPattern> </relocation> <!-- move Guava to a shaded package --> <relocation> <pattern>com.google.common</pattern> <shadedPattern>myapp.shaded.com.google.common</shadedPattern> </relocation> </relocations> </configuration> </execution> </executions> </plugin>