From 2b0ebc060ec7c9789e5586cdf8198d6ff59ceab4 Mon Sep 17 00:00:00 2001 From: Neenu1995 Date: Tue, 21 Apr 2026 13:14:51 -0400 Subject: [PATCH 1/5] optimize logger formatter --- .../bigquery/jdbc/BigQueryJdbcRootLogger.java | 89 +++++++++++-------- 1 file changed, 52 insertions(+), 37 deletions(-) diff --git a/java-bigquery/google-cloud-bigquery-jdbc/src/main/java/com/google/cloud/bigquery/jdbc/BigQueryJdbcRootLogger.java b/java-bigquery/google-cloud-bigquery-jdbc/src/main/java/com/google/cloud/bigquery/jdbc/BigQueryJdbcRootLogger.java index a6723441550e..9f7c075d0755 100644 --- a/java-bigquery/google-cloud-bigquery-jdbc/src/main/java/com/google/cloud/bigquery/jdbc/BigQueryJdbcRootLogger.java +++ b/java-bigquery/google-cloud-bigquery-jdbc/src/main/java/com/google/cloud/bigquery/jdbc/BigQueryJdbcRootLogger.java @@ -16,8 +16,12 @@ package com.google.cloud.bigquery.jdbc; +import com.google.common.base.Strings; import java.io.IOException; import java.lang.management.ManagementFactory; +import java.time.Instant; +import java.time.ZoneId; +import java.time.format.DateTimeFormatter; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; @@ -49,6 +53,25 @@ class BigQueryJdbcRootLogger { private static Path currentLogPath = null; private static int fileCounter = 0; + private static final long PROCESS_ID = + Long.parseLong(ManagementFactory.getRuntimeMXBean().getName().split("@")[0]); + + private static String getThreadName(long threadId) { + Thread current = Thread.currentThread(); + if (current.getId() == threadId) { + return current.getName(); + } + int count = Thread.activeCount(); + Thread[] threads = new Thread[count * 2]; + int actualCount = Thread.enumerate(threads); + for (int i = 0; i < actualCount; i++) { + if (threads[i].getId() == threadId) { + return threads[i].getName(); + } + } + return ""; + } + static { logger.setUseParentHandlers(false); storageLogger.setUseParentHandlers(true); @@ -62,49 +85,41 @@ class BigQueryJdbcRootLogger { public static Formatter getFormatter() { return new Formatter() { - private static final String PATTERN = "yyyy-MM-dd HH:mm:ss.SSS"; - private static final String FORMAT = - "%1$s %2$5s %3$d --- [%4$-7.15s] %5$-50s %6$-20s: %7$s%8$s"; + private final ThreadLocal dateFormatter = + ThreadLocal.withInitial(() -> new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS")); private static final int MAX_THREAD_NAME_LENGTH = 15; - /** - * Returns the thread for the given thread id. - * - * @param threadId ID for the thread being logged. - * @return returns the thread - */ - Optional getThread(long threadId) { - return Thread.getAllStackTraces().keySet().stream() - .filter(thread -> thread.getId() == threadId) - .findFirst(); - } - @Override public String format(LogRecord record) { - String date = new SimpleDateFormat(PATTERN).format(new Date(record.getMillis())); - String threadName = - getThread(record.getThreadID()) - .map(Thread::getName) - .map( - name -> - name.length() > MAX_THREAD_NAME_LENGTH - ? name.substring(name.length() - MAX_THREAD_NAME_LENGTH) - : name) - .orElse(""); - long processId = - Long.parseLong(ManagementFactory.getRuntimeMXBean().getName().split("@")[0]); + String date = dateFormatter.get().format(new Date(record.getMillis())); + + long threadId = record.getThreadID(); + String threadName = getThreadName(threadId); + + if (threadName.length() > MAX_THREAD_NAME_LENGTH) { + threadName = threadName.substring(threadName.length() - MAX_THREAD_NAME_LENGTH); + } + String sourceClassName = record.getLoggerName(); String sourceMethodName = record.getSourceMethodName(); - return String.format( - FORMAT, - date, - record.getLevel().getName(), - processId, - threadName, - sourceClassName, - sourceMethodName, - record.getMessage(), - System.lineSeparator()); + + StringBuilder sb = new StringBuilder(256); + sb.append(date) + .append(" ") + .append(Strings.padStart(record.getLevel().getName(), 5, ' ')) + .append(" ") + .append(PROCESS_ID) + .append(" --- [") + .append(Strings.padEnd(threadName, 7, ' ')) + .append("] ") + .append(Strings.padEnd(sourceClassName != null ? sourceClassName : "", 50, ' ')) + .append(" ") + .append(Strings.padEnd(sourceMethodName != null ? sourceMethodName : "", 20, ' ')) + .append(": ") + .append(record.getMessage()) + .append(System.lineSeparator()); + + return sb.toString(); } }; } From 53e23536038fc867d643a8f8b8271ceb841c23ba Mon Sep 17 00:00:00 2001 From: Neenu1995 Date: Tue, 21 Apr 2026 13:16:16 -0400 Subject: [PATCH 2/5] add tests --- .../bigquery/jdbc/BigQueryJdbcRootLogger.java | 4 +- .../jdbc/BigQueryJdbcRootLoggerTest.java | 74 +++++++++++++++++++ 2 files changed, 76 insertions(+), 2 deletions(-) create mode 100644 java-bigquery/google-cloud-bigquery-jdbc/src/test/java/com/google/cloud/bigquery/jdbc/BigQueryJdbcRootLoggerTest.java diff --git a/java-bigquery/google-cloud-bigquery-jdbc/src/main/java/com/google/cloud/bigquery/jdbc/BigQueryJdbcRootLogger.java b/java-bigquery/google-cloud-bigquery-jdbc/src/main/java/com/google/cloud/bigquery/jdbc/BigQueryJdbcRootLogger.java index 9f7c075d0755..e60286d36018 100644 --- a/java-bigquery/google-cloud-bigquery-jdbc/src/main/java/com/google/cloud/bigquery/jdbc/BigQueryJdbcRootLogger.java +++ b/java-bigquery/google-cloud-bigquery-jdbc/src/main/java/com/google/cloud/bigquery/jdbc/BigQueryJdbcRootLogger.java @@ -53,10 +53,10 @@ class BigQueryJdbcRootLogger { private static Path currentLogPath = null; private static int fileCounter = 0; - private static final long PROCESS_ID = + static final long PROCESS_ID = Long.parseLong(ManagementFactory.getRuntimeMXBean().getName().split("@")[0]); - private static String getThreadName(long threadId) { + static String getThreadName(long threadId) { Thread current = Thread.currentThread(); if (current.getId() == threadId) { return current.getName(); diff --git a/java-bigquery/google-cloud-bigquery-jdbc/src/test/java/com/google/cloud/bigquery/jdbc/BigQueryJdbcRootLoggerTest.java b/java-bigquery/google-cloud-bigquery-jdbc/src/test/java/com/google/cloud/bigquery/jdbc/BigQueryJdbcRootLoggerTest.java new file mode 100644 index 000000000000..19a25903f15c --- /dev/null +++ b/java-bigquery/google-cloud-bigquery-jdbc/src/test/java/com/google/cloud/bigquery/jdbc/BigQueryJdbcRootLoggerTest.java @@ -0,0 +1,74 @@ +/* + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.google.cloud.bigquery.jdbc; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertTrue; + +import java.util.logging.Formatter; +import java.util.logging.Level; +import java.util.logging.LogRecord; +import org.junit.jupiter.api.Test; + +public class BigQueryJdbcRootLoggerTest { + + @Test + public void testGetFormatterFormat() { + Formatter formatter = BigQueryJdbcRootLogger.getFormatter(); + assertNotNull(formatter); + + LogRecord record = new LogRecord(Level.INFO, "Test message"); + record.setMillis(1713715200000L); + record.setLoggerName("TestLogger"); + record.setSourceMethodName("testMethod"); + + String formatted = formatter.format(record); + + assertTrue(formatted.contains("INFO")); + assertTrue(formatted.contains("Test message")); + assertTrue(formatted.contains("TestLogger")); + assertTrue(formatted.contains("testMethod")); + assertTrue(formatted.contains("---")); + } + + @Test + public void testThreadNameTruncation() { + Formatter formatter = BigQueryJdbcRootLogger.getFormatter(); + LogRecord record = new LogRecord(Level.INFO, "Test message"); + + String formatted = formatter.format(record); + int startIndex = formatted.indexOf("--- [") + 5; + int endIndex = formatted.indexOf("]", startIndex); + String threadPart = formatted.substring(startIndex, endIndex).trim(); + + assertTrue(threadPart.length() <= 15); + } + + @Test + public void testGetThreadName() { + Thread current = Thread.currentThread(); + String name = BigQueryJdbcRootLogger.getThreadName(current.getId()); + assertEquals(current.getName(), name); + } + + @Test + public void testGetThreadNameNotFound() { + String name = BigQueryJdbcRootLogger.getThreadName(-1); + assertEquals("", name); + } +} From 11483bbd57030531eece9ab70bbd6c5e4a719ba8 Mon Sep 17 00:00:00 2001 From: Neenu1995 Date: Tue, 21 Apr 2026 13:22:27 -0400 Subject: [PATCH 3/5] fix(bqjdbc): optimize formatter in BigQueryJdbcRootLogger --- .../bigquery/jdbc/BigQueryJdbcRootLogger.java | 38 +++++++++---------- .../jdbc/BigQueryJdbcRootLoggerTest.java | 4 +- 2 files changed, 19 insertions(+), 23 deletions(-) diff --git a/java-bigquery/google-cloud-bigquery-jdbc/src/main/java/com/google/cloud/bigquery/jdbc/BigQueryJdbcRootLogger.java b/java-bigquery/google-cloud-bigquery-jdbc/src/main/java/com/google/cloud/bigquery/jdbc/BigQueryJdbcRootLogger.java index e60286d36018..945cbe0712db 100644 --- a/java-bigquery/google-cloud-bigquery-jdbc/src/main/java/com/google/cloud/bigquery/jdbc/BigQueryJdbcRootLogger.java +++ b/java-bigquery/google-cloud-bigquery-jdbc/src/main/java/com/google/cloud/bigquery/jdbc/BigQueryJdbcRootLogger.java @@ -19,16 +19,12 @@ import com.google.common.base.Strings; import java.io.IOException; import java.lang.management.ManagementFactory; -import java.time.Instant; -import java.time.ZoneId; -import java.time.format.DateTimeFormatter; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; import java.nio.file.StandardCopyOption; import java.text.SimpleDateFormat; import java.util.Date; -import java.util.Optional; import java.util.logging.ConsoleHandler; import java.util.logging.FileHandler; import java.util.logging.Formatter; @@ -92,33 +88,33 @@ public static Formatter getFormatter() { @Override public String format(LogRecord record) { String date = dateFormatter.get().format(new Date(record.getMillis())); - + long threadId = record.getThreadID(); String threadName = getThreadName(threadId); if (threadName.length() > MAX_THREAD_NAME_LENGTH) { threadName = threadName.substring(threadName.length() - MAX_THREAD_NAME_LENGTH); } - + String sourceClassName = record.getLoggerName(); String sourceMethodName = record.getSourceMethodName(); - + StringBuilder sb = new StringBuilder(256); sb.append(date) - .append(" ") - .append(Strings.padStart(record.getLevel().getName(), 5, ' ')) - .append(" ") - .append(PROCESS_ID) - .append(" --- [") - .append(Strings.padEnd(threadName, 7, ' ')) - .append("] ") - .append(Strings.padEnd(sourceClassName != null ? sourceClassName : "", 50, ' ')) - .append(" ") - .append(Strings.padEnd(sourceMethodName != null ? sourceMethodName : "", 20, ' ')) - .append(": ") - .append(record.getMessage()) - .append(System.lineSeparator()); - + .append(" ") + .append(Strings.padStart(record.getLevel().getName(), 5, ' ')) + .append(" ") + .append(PROCESS_ID) + .append(" --- [") + .append(Strings.padEnd(threadName, 7, ' ')) + .append("] ") + .append(Strings.padEnd(sourceClassName != null ? sourceClassName : "", 50, ' ')) + .append(" ") + .append(Strings.padEnd(sourceMethodName != null ? sourceMethodName : "", 20, ' ')) + .append(": ") + .append(record.getMessage()) + .append(System.lineSeparator()); + return sb.toString(); } }; diff --git a/java-bigquery/google-cloud-bigquery-jdbc/src/test/java/com/google/cloud/bigquery/jdbc/BigQueryJdbcRootLoggerTest.java b/java-bigquery/google-cloud-bigquery-jdbc/src/test/java/com/google/cloud/bigquery/jdbc/BigQueryJdbcRootLoggerTest.java index 19a25903f15c..addae7b907bc 100644 --- a/java-bigquery/google-cloud-bigquery-jdbc/src/test/java/com/google/cloud/bigquery/jdbc/BigQueryJdbcRootLoggerTest.java +++ b/java-bigquery/google-cloud-bigquery-jdbc/src/test/java/com/google/cloud/bigquery/jdbc/BigQueryJdbcRootLoggerTest.java @@ -50,12 +50,12 @@ public void testGetFormatterFormat() { public void testThreadNameTruncation() { Formatter formatter = BigQueryJdbcRootLogger.getFormatter(); LogRecord record = new LogRecord(Level.INFO, "Test message"); - + String formatted = formatter.format(record); int startIndex = formatted.indexOf("--- [") + 5; int endIndex = formatted.indexOf("]", startIndex); String threadPart = formatted.substring(startIndex, endIndex).trim(); - + assertTrue(threadPart.length() <= 15); } From 8fb5e7e812c8d8521a93d5eb1028aa93f3a11b81 Mon Sep 17 00:00:00 2001 From: Neenu1995 Date: Tue, 21 Apr 2026 13:36:10 -0400 Subject: [PATCH 4/5] minor optimizations --- .../bigquery/jdbc/BigQueryJdbcRootLogger.java | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/java-bigquery/google-cloud-bigquery-jdbc/src/main/java/com/google/cloud/bigquery/jdbc/BigQueryJdbcRootLogger.java b/java-bigquery/google-cloud-bigquery-jdbc/src/main/java/com/google/cloud/bigquery/jdbc/BigQueryJdbcRootLogger.java index 945cbe0712db..ec2c5b4cdcb7 100644 --- a/java-bigquery/google-cloud-bigquery-jdbc/src/main/java/com/google/cloud/bigquery/jdbc/BigQueryJdbcRootLogger.java +++ b/java-bigquery/google-cloud-bigquery-jdbc/src/main/java/com/google/cloud/bigquery/jdbc/BigQueryJdbcRootLogger.java @@ -49,17 +49,24 @@ class BigQueryJdbcRootLogger { private static Path currentLogPath = null; private static int fileCounter = 0; - static final long PROCESS_ID = - Long.parseLong(ManagementFactory.getRuntimeMXBean().getName().split("@")[0]); + static final String PROCESS_ID = ManagementFactory.getRuntimeMXBean().getName().split("@")[0]; + + private static final ThreadLocal DATE_FORMATTER = + ThreadLocal.withInitial(() -> new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS")); static String getThreadName(long threadId) { Thread current = Thread.currentThread(); if (current.getId() == threadId) { return current.getName(); } - int count = Thread.activeCount(); + ThreadGroup rootGroup = current.getThreadGroup(); + while (rootGroup.getParent() != null) { + rootGroup = rootGroup.getParent(); + } + + int count = rootGroup.activeCount(); Thread[] threads = new Thread[count * 2]; - int actualCount = Thread.enumerate(threads); + int actualCount = rootGroup.enumerate(threads); for (int i = 0; i < actualCount; i++) { if (threads[i].getId() == threadId) { return threads[i].getName(); @@ -81,13 +88,11 @@ static String getThreadName(long threadId) { public static Formatter getFormatter() { return new Formatter() { - private final ThreadLocal dateFormatter = - ThreadLocal.withInitial(() -> new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS")); private static final int MAX_THREAD_NAME_LENGTH = 15; @Override public String format(LogRecord record) { - String date = dateFormatter.get().format(new Date(record.getMillis())); + String date = DATE_FORMATTER.get().format(new Date(record.getMillis())); long threadId = record.getThreadID(); String threadName = getThreadName(threadId); From 6142d6e15f8f33300e21ca785cc445db87e2c7dc Mon Sep 17 00:00:00 2001 From: Neenu1995 Date: Wed, 22 Apr 2026 10:37:57 -0400 Subject: [PATCH 5/5] add comment --- .../google/cloud/bigquery/jdbc/BigQueryJdbcRootLogger.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/java-bigquery/google-cloud-bigquery-jdbc/src/main/java/com/google/cloud/bigquery/jdbc/BigQueryJdbcRootLogger.java b/java-bigquery/google-cloud-bigquery-jdbc/src/main/java/com/google/cloud/bigquery/jdbc/BigQueryJdbcRootLogger.java index ec2c5b4cdcb7..8c213ae8c4a0 100644 --- a/java-bigquery/google-cloud-bigquery-jdbc/src/main/java/com/google/cloud/bigquery/jdbc/BigQueryJdbcRootLogger.java +++ b/java-bigquery/google-cloud-bigquery-jdbc/src/main/java/com/google/cloud/bigquery/jdbc/BigQueryJdbcRootLogger.java @@ -104,6 +104,10 @@ public String format(LogRecord record) { String sourceClassName = record.getLoggerName(); String sourceMethodName = record.getSourceMethodName(); + // Expected log format: yyyy-MM-dd HH:mm:ss.SSS LEVEL PID --- [THREAD] CLASS METHOD: MESSAGE + // Example: 2026-04-22 10:16:00.123 INFO 12345 --- [main ] + // com.google.cloud.bigquery.jdbc.BigQueryConnection connect : Connection + // successful StringBuilder sb = new StringBuilder(256); sb.append(date) .append(" ")