From 03c0d7cf6b29d93582fb2f81eadcff6252bfdb56 Mon Sep 17 00:00:00 2001 From: Neenu1995 Date: Fri, 3 Jul 2026 14:24:29 -0400 Subject: [PATCH 1/7] feat(bigquery-jdbc): add telemetry proto schema definition --- .../jdbc/telemetry/v1/telemetry.proto | 162 ++++++++++++++++++ 1 file changed, 162 insertions(+) create mode 100644 java-bigquery-jdbc/src/main/proto/google/cloud/bigquery/jdbc/telemetry/v1/telemetry.proto diff --git a/java-bigquery-jdbc/src/main/proto/google/cloud/bigquery/jdbc/telemetry/v1/telemetry.proto b/java-bigquery-jdbc/src/main/proto/google/cloud/bigquery/jdbc/telemetry/v1/telemetry.proto new file mode 100644 index 000000000000..149f5aae2d31 --- /dev/null +++ b/java-bigquery-jdbc/src/main/proto/google/cloud/bigquery/jdbc/telemetry/v1/telemetry.proto @@ -0,0 +1,162 @@ +// 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. + +syntax = "proto3"; + +package google.cloud.bigquery.jdbc.telemetry.v1; + +import "google/protobuf/timestamp.proto"; + +option java_multiple_files = true; +option java_package = "com.google.cloud.bigquery.jdbc.telemetry.v1"; +option java_outer_classname = "TelemetryProto"; + +// Aggregated client-side telemetry payload sent to Clearcut analytics backend. +message TelemetryPayload { + DriverEnvironment driver_environment = 1; + google.protobuf.Timestamp timestamp = 2; + repeated ConnectionAttempt connection_attempts = 3; + repeated StatementExecution statement_executions = 4; + repeated ErrorMetric errors = 5; + repeated FeatureUsage feature_usages = 6; +} + +// Client runtime and environment attributes. +message DriverEnvironment { + enum OsType { + OS_TYPE_UNSPECIFIED = 0; + OS_TYPE_LINUX = 1; + OS_TYPE_WINDOWS = 2; + OS_TYPE_MACOS = 3; + OS_TYPE_SOLARIS = 4; + OS_TYPE_FREEBSD = 5; + OS_TYPE_OPENBSD = 6; + OS_TYPE_NETBSD = 7; + OS_TYPE_AIX = 8; + OS_TYPE_UNKNOWN = 9; + } + string driver_name = 1; + string driver_version = 2; + string client_language = 3; + string client_language_version = 4; + OsType os_type = 5; + string os_version = 6; + string telemetry_tag = 7; +} + +// Execution status enum for connection attempts and statement executions. +enum Status { + STATUS_UNSPECIFIED = 0; + STATUS_SUCCESS = 1; + STATUS_ERROR = 2; + STATUS_CANCELLED = 3; +} + +// Authentication types utilized during connection creation. +enum AuthenticationType { + AUTHENTICATION_TYPE_UNSPECIFIED = 0; + AUTHENTICATION_TYPE_SERVICE_ACCOUNT = 1; + AUTHENTICATION_TYPE_USER_AUTHENTICATION = 2; + AUTHENTICATION_TYPE_TOKEN = 3; + AUTHENTICATION_TYPE_APPLICATION_DEFAULT_CREDENTIALS = 4; + AUTHENTICATION_TYPE_EXTERNAL = 5; + AUTHENTICATION_TYPE_CUSTOM = 6; +} + +// Aggregated metrics for connection attempts. +message ConnectionAttempt { + Status status = 1; + string error_code = 2; + AuthenticationType auth_type = 3; + int64 count = 4; +} + +// High-level classification of statement execution types. +enum StatementType { + STATEMENT_TYPE_UNSPECIFIED = 0; + STATEMENT_TYPE_SELECT = 1; + STATEMENT_TYPE_INSERT = 2; + STATEMENT_TYPE_UPDATE = 3; + STATEMENT_TYPE_DELETE = 4; + STATEMENT_TYPE_MERGE = 5; + STATEMENT_TYPE_CREATE_TABLE = 6; + STATEMENT_TYPE_CREATE_MODEL = 7; + STATEMENT_TYPE_CREATE_VIEW = 8; + STATEMENT_TYPE_DROP_TABLE = 9; + STATEMENT_TYPE_DROP_VIEW = 10; + STATEMENT_TYPE_ALTER_TABLE = 11; + STATEMENT_TYPE_ALTER_VIEW = 12; + STATEMENT_TYPE_SCRIPT = 13; + STATEMENT_TYPE_CALL = 14; + STATEMENT_TYPE_EXPLAIN = 15; + STATEMENT_TYPE_OTHER = 16; +} + +// API substrate used during query execution (REST API vs Read API vs Write API vs Jobless Query). +enum QueryApiType { + QUERY_API_TYPE_UNSPECIFIED = 0; + QUERY_API_TYPE_STANDARD_REST_API = 1; + QUERY_API_TYPE_READ_API = 2; + QUERY_API_TYPE_WRITE_API = 3; + QUERY_API_TYPE_JOBLESS_QUERY = 4; +} + +// Aggregated execution metrics for statement executions. +message StatementExecution { + StatementType statement_type = 1; + QueryApiType query_api_type = 2; + Status status = 3; + string error_code = 4; + int64 count = 5; + DurationHistogram duration = 6; +} + +// Duration histogram distribution for execution latency tracking. +message DurationHistogram { + repeated int64 bucket_counts = 1; + repeated double explicit_bounds = 2; + int64 count = 3; + double sum = 4; +} + +// Aggregated error counts grouped by error code, SQL state, and method. +message ErrorMetric { + string error_code = 1; + string error_xdbc_code = 2; + string method_name = 3; + int64 count = 4; +} + +// High-level driver runtime features and capabilities tracked for telemetry. +enum DriverFeature { + DRIVER_FEATURE_UNSPECIFIED = 0; + DRIVER_FEATURE_BATCH_OPERATIONS = 1; + DRIVER_FEATURE_PREPARED_STATEMENT = 2; + DRIVER_FEATURE_CALLABLE_STATEMENT = 3; + DRIVER_FEATURE_AUTOCOMMIT_ENABLED = 4; + DRIVER_FEATURE_AUTOCOMMIT_DISABLED = 5; + DRIVER_FEATURE_TRANSACTIONS = 6; + DRIVER_FEATURE_CONNECTION_POOLING = 7; + DRIVER_FEATURE_STATEMENT_CANCEL = 8; + DRIVER_FEATURE_PARAMETER_BINDING = 9; + DRIVER_FEATURE_METADATA_RETRIEVAL = 10; + DRIVER_FEATURE_CUSTOM = 11; +} + +// Usage metrics for specific features. +message FeatureUsage { + DriverFeature driver_feature = 1; + string custom_feature_name = 2; + int64 count = 3; +} From 359a52e4b4ca9ac4e2f2cb2c25555ff0c21ad48b Mon Sep 17 00:00:00 2001 From: Neenu1995 Date: Fri, 3 Jul 2026 15:05:32 -0400 Subject: [PATCH 2/7] style(telemetry): rename timestamp to event_time per AIP-142 --- .../google/cloud/bigquery/jdbc/telemetry/v1/telemetry.proto | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-bigquery-jdbc/src/main/proto/google/cloud/bigquery/jdbc/telemetry/v1/telemetry.proto b/java-bigquery-jdbc/src/main/proto/google/cloud/bigquery/jdbc/telemetry/v1/telemetry.proto index 149f5aae2d31..305805203f41 100644 --- a/java-bigquery-jdbc/src/main/proto/google/cloud/bigquery/jdbc/telemetry/v1/telemetry.proto +++ b/java-bigquery-jdbc/src/main/proto/google/cloud/bigquery/jdbc/telemetry/v1/telemetry.proto @@ -25,7 +25,7 @@ option java_outer_classname = "TelemetryProto"; // Aggregated client-side telemetry payload sent to Clearcut analytics backend. message TelemetryPayload { DriverEnvironment driver_environment = 1; - google.protobuf.Timestamp timestamp = 2; + google.protobuf.Timestamp event_time = 2; repeated ConnectionAttempt connection_attempts = 3; repeated StatementExecution statement_executions = 4; repeated ErrorMetric errors = 5; From 8bb6b831575ec7b70070e4ccae1c7f612f580955 Mon Sep 17 00:00:00 2001 From: Neenu1995 Date: Fri, 3 Jul 2026 15:07:08 -0400 Subject: [PATCH 3/7] docs(telemetry): document millisecond units for DurationHistogram per AIP-142 --- .../cloud/bigquery/jdbc/telemetry/v1/telemetry.proto | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/java-bigquery-jdbc/src/main/proto/google/cloud/bigquery/jdbc/telemetry/v1/telemetry.proto b/java-bigquery-jdbc/src/main/proto/google/cloud/bigquery/jdbc/telemetry/v1/telemetry.proto index 305805203f41..b4ac091294cc 100644 --- a/java-bigquery-jdbc/src/main/proto/google/cloud/bigquery/jdbc/telemetry/v1/telemetry.proto +++ b/java-bigquery-jdbc/src/main/proto/google/cloud/bigquery/jdbc/telemetry/v1/telemetry.proto @@ -122,11 +122,18 @@ message StatementExecution { DurationHistogram duration = 6; } -// Duration histogram distribution for execution latency tracking. +// Histogram representation for query duration measurements in milliseconds. message DurationHistogram { + // Count of items in each bucket. repeated int64 bucket_counts = 1; + + // Upper bounds for each bucket in milliseconds. repeated double explicit_bounds = 2; + + // Total count of recorded duration events. int64 count = 3; + + // Cumulative sum of recorded durations in milliseconds. double sum = 4; } From c0512bd3ddda4ed5fff8d966a61c7ab9be1ad115 Mon Sep 17 00:00:00 2001 From: Neenu1995 Date: Wed, 8 Jul 2026 17:23:38 -0400 Subject: [PATCH 4/7] feat(bigquery-jdbc): add telemetry configuration class and unit tests --- .../telemetry/v1/TelemetryConfiguration.java | 159 ++++++++++++++++++ .../v1/TelemetryConfigurationTest.java | 84 +++++++++ 2 files changed, 243 insertions(+) create mode 100644 java-bigquery-jdbc/src/main/java/com/google/cloud/bigquery/jdbc/telemetry/v1/TelemetryConfiguration.java create mode 100644 java-bigquery-jdbc/src/test/java/com/google/cloud/bigquery/jdbc/telemetry/v1/TelemetryConfigurationTest.java diff --git a/java-bigquery-jdbc/src/main/java/com/google/cloud/bigquery/jdbc/telemetry/v1/TelemetryConfiguration.java b/java-bigquery-jdbc/src/main/java/com/google/cloud/bigquery/jdbc/telemetry/v1/TelemetryConfiguration.java new file mode 100644 index 000000000000..c7460ace7033 --- /dev/null +++ b/java-bigquery-jdbc/src/main/java/com/google/cloud/bigquery/jdbc/telemetry/v1/TelemetryConfiguration.java @@ -0,0 +1,159 @@ +/* + * 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 + * + * https://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.telemetry.v1; + +import java.util.Objects; + +/** Configuration settings for the BigQuery JDBC driver telemetry client. */ +final class TelemetryConfiguration { + static final boolean DEFAULT_ENABLED = true; + // TODO: change DEFAULT_LOG_SOURCE value once the value is assigned. + static final int DEFAULT_LOG_SOURCE = -1; + static final String DEFAULT_ENDPOINT_URL = "https://play.googleapis.com/log"; + static final long DEFAULT_UPLOAD_INTERVAL_MS = 300_000L; + static final int DEFAULT_BATCH_SIZE_THRESHOLD = 100; + + private final boolean enabled; + private final int logSource; + private final String endpointUrl; + private final long uploadIntervalMs; + private final int batchSizeThreshold; + private final DriverEnvironment driverEnvironment; + + private TelemetryConfiguration(Builder builder) { + this.enabled = builder.enabled; + this.logSource = builder.logSource; + this.endpointUrl = builder.endpointUrl; + this.uploadIntervalMs = builder.uploadIntervalMs; + this.batchSizeThreshold = builder.batchSizeThreshold; + this.driverEnvironment = builder.driverEnvironment; + } + + boolean isEnabled() { + return enabled; + } + + int getLogSource() { + return logSource; + } + + String getEndpointUrl() { + return endpointUrl; + } + + long getUploadIntervalMs() { + return uploadIntervalMs; + } + + int getBatchSizeThreshold() { + return batchSizeThreshold; + } + + DriverEnvironment getDriverEnvironment() { + return driverEnvironment; + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + TelemetryConfiguration that = (TelemetryConfiguration) o; + return enabled == that.enabled + && logSource == that.logSource + && uploadIntervalMs == that.uploadIntervalMs + && batchSizeThreshold == that.batchSizeThreshold + && Objects.equals(endpointUrl, that.endpointUrl) + && Objects.equals(driverEnvironment, that.driverEnvironment); + } + + @Override + public int hashCode() { + return Objects.hash( + enabled, logSource, endpointUrl, uploadIntervalMs, batchSizeThreshold, driverEnvironment); + } + + @Override + public String toString() { + return "TelemetryConfiguration{" + + "enabled=" + + enabled + + ", logSource=" + + logSource + + ", endpointUrl='" + + endpointUrl + + '\'' + + ", uploadIntervalMs=" + + uploadIntervalMs + + ", batchSizeThreshold=" + + batchSizeThreshold + + ", driverEnvironment=" + + driverEnvironment + + '}'; + } + + static Builder newBuilder() { + return new Builder(); + } + + /** Builder for {@link TelemetryConfiguration}. */ + static class Builder { + private boolean enabled = DEFAULT_ENABLED; + private int logSource = DEFAULT_LOG_SOURCE; + private String endpointUrl = DEFAULT_ENDPOINT_URL; + private long uploadIntervalMs = DEFAULT_UPLOAD_INTERVAL_MS; + private int batchSizeThreshold = DEFAULT_BATCH_SIZE_THRESHOLD; + private DriverEnvironment driverEnvironment; + + Builder setEnabled(boolean enabled) { + this.enabled = enabled; + return this; + } + + Builder setLogSource(int logSource) { + this.logSource = logSource; + return this; + } + + Builder setEndpointUrl(String endpointUrl) { + this.endpointUrl = endpointUrl; + return this; + } + + Builder setUploadIntervalMs(long uploadIntervalMs) { + this.uploadIntervalMs = uploadIntervalMs; + return this; + } + + Builder setBatchSizeThreshold(int batchSizeThreshold) { + this.batchSizeThreshold = batchSizeThreshold; + return this; + } + + Builder setDriverEnvironment(DriverEnvironment driverEnvironment) { + this.driverEnvironment = driverEnvironment; + return this; + } + + TelemetryConfiguration build() { + return new TelemetryConfiguration(this); + } + } +} diff --git a/java-bigquery-jdbc/src/test/java/com/google/cloud/bigquery/jdbc/telemetry/v1/TelemetryConfigurationTest.java b/java-bigquery-jdbc/src/test/java/com/google/cloud/bigquery/jdbc/telemetry/v1/TelemetryConfigurationTest.java new file mode 100644 index 000000000000..4f5d0d531a35 --- /dev/null +++ b/java-bigquery-jdbc/src/test/java/com/google/cloud/bigquery/jdbc/telemetry/v1/TelemetryConfigurationTest.java @@ -0,0 +1,84 @@ +/* + * 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 + * + * https://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.telemetry.v1; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotEquals; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertTrue; + +import org.junit.Test; + +public class TelemetryConfigurationTest { + + @Test + public void testDefaultValues() { + TelemetryConfiguration config = TelemetryConfiguration.newBuilder().build(); + + assertTrue(config.isEnabled()); + assertEquals(-1, config.getLogSource()); + assertEquals("https://play.googleapis.com/log", config.getEndpointUrl()); + assertEquals(300_000L, config.getUploadIntervalMs()); + assertEquals(100, config.getBatchSizeThreshold()); + assertNull(config.getDriverEnvironment()); + } + + @Test + public void testCustomValues() { + DriverEnvironment environment = + DriverEnvironment.newBuilder() + .setDriverName("BigQuery JDBC") + .setDriverVersion("1.0.0") + .build(); + + TelemetryConfiguration config = + TelemetryConfiguration.newBuilder() + .setEnabled(false) + .setLogSource(1234) + .setEndpointUrl("https://custom.endpoint.com/log") + .setUploadIntervalMs(60_000L) + .setBatchSizeThreshold(50) + .setDriverEnvironment(environment) + .build(); + + assertFalse(config.isEnabled()); + assertEquals(1234, config.getLogSource()); + assertEquals("https://custom.endpoint.com/log", config.getEndpointUrl()); + assertEquals(60_000L, config.getUploadIntervalMs()); + assertEquals(50, config.getBatchSizeThreshold()); + assertEquals(environment, config.getDriverEnvironment()); + } + + @Test + public void testEqualsAndHashCode() { + TelemetryConfiguration config1 = + TelemetryConfiguration.newBuilder().setEnabled(true).setLogSource(1234).build(); + + TelemetryConfiguration config2 = + TelemetryConfiguration.newBuilder().setEnabled(true).setLogSource(1234).build(); + + TelemetryConfiguration config3 = + TelemetryConfiguration.newBuilder().setEnabled(false).setLogSource(1234).build(); + + assertEquals(config1, config2); + assertEquals(config1.hashCode(), config2.hashCode()); + assertNotEquals(config1, config3); + assertNotEquals(config1, null); + assertNotEquals(config1, "string"); + } +} From d7dec484422053f98517e84de286d08bff0e9f24 Mon Sep 17 00:00:00 2001 From: Neenu1995 Date: Thu, 9 Jul 2026 09:57:16 -0400 Subject: [PATCH 5/7] lint --- .../bigquery/jdbc/telemetry/v1/TelemetryConfiguration.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-bigquery-jdbc/src/main/java/com/google/cloud/bigquery/jdbc/telemetry/v1/TelemetryConfiguration.java b/java-bigquery-jdbc/src/main/java/com/google/cloud/bigquery/jdbc/telemetry/v1/TelemetryConfiguration.java index c7460ace7033..715b51c4003b 100644 --- a/java-bigquery-jdbc/src/main/java/com/google/cloud/bigquery/jdbc/telemetry/v1/TelemetryConfiguration.java +++ b/java-bigquery-jdbc/src/main/java/com/google/cloud/bigquery/jdbc/telemetry/v1/TelemetryConfiguration.java @@ -5,7 +5,7 @@ * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * https://www.apache.org/licenses/LICENSE-2.0 + * https://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, From 3e9c30e7891bd02ea2c03fd1fd8df365e020485f Mon Sep 17 00:00:00 2001 From: Neenu1995 Date: Thu, 9 Jul 2026 10:12:52 -0400 Subject: [PATCH 6/7] refactor(telemetry): migrate TelemetryConfigurationTest to JUnit 5 --- .../telemetry/v1/TelemetryConfigurationTest.java | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/java-bigquery-jdbc/src/test/java/com/google/cloud/bigquery/jdbc/telemetry/v1/TelemetryConfigurationTest.java b/java-bigquery-jdbc/src/test/java/com/google/cloud/bigquery/jdbc/telemetry/v1/TelemetryConfigurationTest.java index 4f5d0d531a35..98011c9bdced 100644 --- a/java-bigquery-jdbc/src/test/java/com/google/cloud/bigquery/jdbc/telemetry/v1/TelemetryConfigurationTest.java +++ b/java-bigquery-jdbc/src/test/java/com/google/cloud/bigquery/jdbc/telemetry/v1/TelemetryConfigurationTest.java @@ -16,13 +16,13 @@ package com.google.cloud.bigquery.jdbc.telemetry.v1; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertNotEquals; -import static org.junit.Assert.assertNull; -import static org.junit.Assert.assertTrue; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertNotEquals; +import static org.junit.jupiter.api.Assertions.assertNull; +import static org.junit.jupiter.api.Assertions.assertTrue; -import org.junit.Test; +import org.junit.jupiter.api.Test; public class TelemetryConfigurationTest { From 34ac88677a2e8a51c36f4207668674065d869ce9 Mon Sep 17 00:00:00 2001 From: Neenu1995 Date: Thu, 9 Jul 2026 10:31:05 -0400 Subject: [PATCH 7/7] license lint --- .../bigquery/jdbc/telemetry/v1/TelemetryConfigurationTest.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-bigquery-jdbc/src/test/java/com/google/cloud/bigquery/jdbc/telemetry/v1/TelemetryConfigurationTest.java b/java-bigquery-jdbc/src/test/java/com/google/cloud/bigquery/jdbc/telemetry/v1/TelemetryConfigurationTest.java index 98011c9bdced..1f55bd0ad87d 100644 --- a/java-bigquery-jdbc/src/test/java/com/google/cloud/bigquery/jdbc/telemetry/v1/TelemetryConfigurationTest.java +++ b/java-bigquery-jdbc/src/test/java/com/google/cloud/bigquery/jdbc/telemetry/v1/TelemetryConfigurationTest.java @@ -5,7 +5,7 @@ * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * https://www.apache.org/licenses/LICENSE-2.0 + * https://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,