From c2d096c3c2c7b9964f7641c2e4f0727b2f1e848f Mon Sep 17 00:00:00 2001 From: Tatiane Tosta <91583351+ttosta-google@users.noreply.github.com> Date: Wed, 10 Apr 2024 13:23:08 -0400 Subject: [PATCH] feat: add support for debug logging (#501) --- README.md | 10 ++++++++++ .../com/google/cloud/alloydb/ConnectionSocket.java | 12 +++++++++++- .../java/com/google/cloud/alloydb/Connector.java | 8 ++++++++ .../java/com/google/cloud/alloydb/Refresher.java | 8 ++++++-- 4 files changed, 35 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 2e0afbe6..eee3072e 100644 --- a/README.md +++ b/README.md @@ -54,6 +54,16 @@ for more information. [set-adc]: https://cloud.google.com/docs/authentication/provide-credentials-adc [iam-docs]: https://cloud.google.com/alloydb/docs/reference/iam-roles-permissions#roles +### Debug Logging + +The Java Connector supports optional debug logging to help diagnose problems with +the background certificate refresh. To enable it, add the following to the file +`/src/main/resources/application.yml`: + +``` +logging.level.root=DEBUG +``` + ## Support policy ### Major version lifecycle diff --git a/alloydb-jdbc-connector/src/main/java/com/google/cloud/alloydb/ConnectionSocket.java b/alloydb-jdbc-connector/src/main/java/com/google/cloud/alloydb/ConnectionSocket.java index a5c83575..bb53c944 100644 --- a/alloydb-jdbc-connector/src/main/java/com/google/cloud/alloydb/ConnectionSocket.java +++ b/alloydb-jdbc-connector/src/main/java/com/google/cloud/alloydb/ConnectionSocket.java @@ -115,6 +115,8 @@ Socket connect() throws IOException { serverName = connectionInfo.getIpAddress(); } + logger.debug(String.format("[%s] Connecting to instance.", address)); + SSLParameters sslParameters = socket.getSSLParameters(); // Set HTTPS as the the endpoint identification algorithm // in order to verify the identity of the certificate as @@ -126,12 +128,20 @@ Socket connect() throws IOException { socket.setKeepAlive(true); socket.setTcpNoDelay(true); socket.connect(new InetSocketAddress(address, SERVER_SIDE_PROXY_PORT)); - socket.startHandshake(); + + try { + socket.startHandshake(); + } catch (IOException e) { + logger.debug("TLS handshake failed!"); + throw e; + } // The metadata exchange must occur after the TLS connection is established // to avoid leaking sensitive information. metadataExchange(socket); + logger.debug(String.format("[%s] Connected to instance successfully.", address)); + return socket; } diff --git a/alloydb-jdbc-connector/src/main/java/com/google/cloud/alloydb/Connector.java b/alloydb-jdbc-connector/src/main/java/com/google/cloud/alloydb/Connector.java index 2dcc684c..8cceb5b4 100644 --- a/alloydb-jdbc-connector/src/main/java/com/google/cloud/alloydb/Connector.java +++ b/alloydb-jdbc-connector/src/main/java/com/google/cloud/alloydb/Connector.java @@ -21,9 +21,12 @@ import java.net.Socket; import java.security.KeyPair; import java.util.concurrent.ConcurrentHashMap; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; class Connector { + private static final Logger logger = LoggerFactory.getLogger(Connector.class); private static final long MIN_RATE_LIMIT_MS = 30000; private final ListeningScheduledExecutorService executor; @@ -56,6 +59,7 @@ public ConnectorConfig getConfig() { } public void close() { + logger.debug("Close all connections and remove them from cache."); this.instances.forEach((key, c) -> c.close()); this.instances.clear(); } @@ -69,6 +73,9 @@ Socket connect(ConnectionConfig config) throws IOException { new ConnectionSocket(connectionInfo, config, clientConnectorKeyPair, accessTokenSupplier); return socket.connect(); } catch (IOException e) { + logger.debug( + String.format( + "[%s] Socket connection failed! Trigger a refresh.", config.getInstanceName())); connectionInfoCache.forceRefresh(); // The Socket methods above will throw an IOException or a SocketException (subclass of // IOException). Catch that exception, trigger a refresh, and then throw it again so @@ -93,6 +100,7 @@ ConnectionInfoCache getConnection(ConnectionConfig config) { } private ConnectionInfoCache createConnectionInfo(ConnectionConfig config) { + logger.debug(String.format("[%s] Connection info added to cache.", config.getInstanceName())); return connectionInfoCacheFactory.create( this.executor, this.connectionInfoRepo, diff --git a/alloydb-jdbc-connector/src/main/java/com/google/cloud/alloydb/Refresher.java b/alloydb-jdbc-connector/src/main/java/com/google/cloud/alloydb/Refresher.java index a0dd8c40..8fd0bbda 100644 --- a/alloydb-jdbc-connector/src/main/java/com/google/cloud/alloydb/Refresher.java +++ b/alloydb-jdbc-connector/src/main/java/com/google/cloud/alloydb/Refresher.java @@ -177,6 +177,10 @@ void forceRefresh() { /** Force a new refresh of the instance data if the client certificate has expired. */ void refreshIfExpired() { ConnectionInfo info = getConnectionInfo(DEFAULT_CONNECT_TIMEOUT_MS); + logger.debug( + String.format( + "[%s] Now = %s, Current client certificate expiration = %s", + name, Instant.now().toString(), info.getExpiration())); if (Instant.now().isAfter(info.getExpiration())) { logger.debug( String.format( @@ -261,11 +265,11 @@ private ListenableFuture handleRefreshResult( // No refresh retry when the TerminalException is raised. final Throwable cause = e.getCause(); if (cause instanceof TerminalException) { - logger.info(String.format("[%s] Refresh Operation: Failed! No retry.", name), e); + logger.debug(String.format("[%s] Refresh Operation: Failed! No retry.", name), e); throw (TerminalException) cause; } - logger.info( + logger.debug( String.format( "[%s] Refresh Operation: Failed! Starting next refresh operation immediately.", name), e);