diff --git a/.github/release-please.yml b/.github/release-please.yml index 48231f76e4..f87ac1ecca 100644 --- a/.github/release-please.yml +++ b/.github/release-please.yml @@ -31,6 +31,14 @@ branches: handleGHRelease: true releaseType: java-backport branch: 2.48.x + - bumpMinorPreMajor: true + handleGHRelease: true + releaseType: java-backport + branch: 2.52.x + - bumpMinorPreMajor: true + handleGHRelease: true + releaseType: java-backport + branch: 2.51.x bumpMinorPreMajor: true handleGHRelease: true releaseType: java-yoshi diff --git a/.github/sync-repo-settings.yaml b/.github/sync-repo-settings.yaml index c3a3263dd7..8a7fa3e302 100644 --- a/.github/sync-repo-settings.yaml +++ b/.github/sync-repo-settings.yaml @@ -132,6 +132,36 @@ branchProtectionRules: - cla/google - javadoc - unmanaged_dependency_check + - pattern: 2.52.x + isAdminEnforced: true + requiredApprovingReviewCount: 1 + requiresCodeOwnerReviews: true + requiresStrictStatusChecks: false + requiredStatusCheckContexts: + - dependencies (17) + - lint + - clirr + - units (8) + - units (11) + - 'Kokoro - Test: Integration' + - cla/google + - javadoc + - unmanaged_dependency_check + - pattern: 2.51.x + isAdminEnforced: true + requiredApprovingReviewCount: 1 + requiresCodeOwnerReviews: true + requiresStrictStatusChecks: false + requiredStatusCheckContexts: + - dependencies (17) + - lint + - clirr + - units (8) + - units (11) + - 'Kokoro - Test: Integration' + - cla/google + - javadoc + - unmanaged_dependency_check permissionRules: - team: api-bigquery permission: admin diff --git a/.github/workflows/unmanaged_dependency_check.yaml b/.github/workflows/unmanaged_dependency_check.yaml index 63543a40fa..161d8328df 100644 --- a/.github/workflows/unmanaged_dependency_check.yaml +++ b/.github/workflows/unmanaged_dependency_check.yaml @@ -17,7 +17,7 @@ jobs: # repository .kokoro/build.sh - name: Unmanaged dependency check - uses: googleapis/sdk-platform-java/java-shared-dependencies/unmanaged-dependency-check@google-cloud-shared-dependencies/v3.50.0 + uses: googleapis/sdk-platform-java/java-shared-dependencies/unmanaged-dependency-check@google-cloud-shared-dependencies/v3.52.1 with: # java-bigquery does not produce a BOM. Fortunately the root pom.xml # defines google-cloud-bigquery in dependencyManagement section. So diff --git a/.kokoro/continuous/graalvm-native-a.cfg b/.kokoro/continuous/graalvm-native-a.cfg index dfa34060bc..849d5dcf13 100644 --- a/.kokoro/continuous/graalvm-native-a.cfg +++ b/.kokoro/continuous/graalvm-native-a.cfg @@ -3,7 +3,7 @@ # Configure the docker image for kokoro-trampoline. env_vars: { key: "TRAMPOLINE_IMAGE" - value: "gcr.io/cloud-devrel-public-resources/graalvm_sdk_platform_a:3.50.0" + value: "gcr.io/cloud-devrel-public-resources/graalvm_sdk_platform_a:3.52.1" } env_vars: { diff --git a/.kokoro/continuous/graalvm-native-b.cfg b/.kokoro/continuous/graalvm-native-b.cfg index 37dda4ab5a..c6bb73143f 100644 --- a/.kokoro/continuous/graalvm-native-b.cfg +++ b/.kokoro/continuous/graalvm-native-b.cfg @@ -3,7 +3,7 @@ # Configure the docker image for kokoro-trampoline. env_vars: { key: "TRAMPOLINE_IMAGE" - value: "gcr.io/cloud-devrel-public-resources/graalvm_sdk_platform_b:3.50.0" + value: "gcr.io/cloud-devrel-public-resources/graalvm_sdk_platform_b:3.52.1" } env_vars: { diff --git a/.kokoro/continuous/graalvm-native-c.cfg b/.kokoro/continuous/graalvm-native-c.cfg index a8ab977848..62182e63f1 100644 --- a/.kokoro/continuous/graalvm-native-c.cfg +++ b/.kokoro/continuous/graalvm-native-c.cfg @@ -3,7 +3,7 @@ # Configure the docker image for kokoro-trampoline. env_vars: { key: "TRAMPOLINE_IMAGE" - value: "gcr.io/cloud-devrel-public-resources/graalvm_sdk_platform_c:3.50.0" + value: "gcr.io/cloud-devrel-public-resources/graalvm_sdk_platform_c:3.52.1" } env_vars: { diff --git a/.kokoro/presubmit/graalvm-native-a.cfg b/.kokoro/presubmit/graalvm-native-a.cfg index dfa34060bc..849d5dcf13 100644 --- a/.kokoro/presubmit/graalvm-native-a.cfg +++ b/.kokoro/presubmit/graalvm-native-a.cfg @@ -3,7 +3,7 @@ # Configure the docker image for kokoro-trampoline. env_vars: { key: "TRAMPOLINE_IMAGE" - value: "gcr.io/cloud-devrel-public-resources/graalvm_sdk_platform_a:3.50.0" + value: "gcr.io/cloud-devrel-public-resources/graalvm_sdk_platform_a:3.52.1" } env_vars: { diff --git a/.kokoro/presubmit/graalvm-native-b.cfg b/.kokoro/presubmit/graalvm-native-b.cfg index 37dda4ab5a..c6bb73143f 100644 --- a/.kokoro/presubmit/graalvm-native-b.cfg +++ b/.kokoro/presubmit/graalvm-native-b.cfg @@ -3,7 +3,7 @@ # Configure the docker image for kokoro-trampoline. env_vars: { key: "TRAMPOLINE_IMAGE" - value: "gcr.io/cloud-devrel-public-resources/graalvm_sdk_platform_b:3.50.0" + value: "gcr.io/cloud-devrel-public-resources/graalvm_sdk_platform_b:3.52.1" } env_vars: { diff --git a/.kokoro/presubmit/graalvm-native-c.cfg b/.kokoro/presubmit/graalvm-native-c.cfg index a8ab977848..62182e63f1 100644 --- a/.kokoro/presubmit/graalvm-native-c.cfg +++ b/.kokoro/presubmit/graalvm-native-c.cfg @@ -3,7 +3,7 @@ # Configure the docker image for kokoro-trampoline. env_vars: { key: "TRAMPOLINE_IMAGE" - value: "gcr.io/cloud-devrel-public-resources/graalvm_sdk_platform_c:3.50.0" + value: "gcr.io/cloud-devrel-public-resources/graalvm_sdk_platform_c:3.52.1" } env_vars: { diff --git a/CHANGELOG.md b/CHANGELOG.md index 71577758bd..be6007f631 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,82 @@ # Changelog +## [2.55.0](https://github.com/googleapis/java-bigquery/compare/v2.54.2...v2.55.0) (2025-09-12) + + +### Features + +* **bigquery:** Add custom ExceptionHandler to BigQueryOptions ([#3937](https://github.com/googleapis/java-bigquery/issues/3937)) ([de0914d](https://github.com/googleapis/java-bigquery/commit/de0914ddbccf988294d50faf56a515e58ab3505d)) + + +### Dependencies + +* Update dependency com.google.cloud:google-cloud-bigquerystorage-bom to v3.17.0 ([#3954](https://github.com/googleapis/java-bigquery/issues/3954)) ([e73deed](https://github.com/googleapis/java-bigquery/commit/e73deed9c68a45023d02b40144c304329d6b5829)) +* Update dependency com.google.cloud:sdk-platform-java-config to v3.52.1 ([#3952](https://github.com/googleapis/java-bigquery/issues/3952)) ([79b7557](https://github.com/googleapis/java-bigquery/commit/79b7557501d318fd92b90a681036fe6a1aa1bac4)) + +## [2.54.2](https://github.com/googleapis/java-bigquery/compare/v2.54.1...v2.54.2) (2025-08-26) + + +### Dependencies + +* Update dependency com.google.cloud:sdk-platform-java-config to v3.52.0 ([#3939](https://github.com/googleapis/java-bigquery/issues/3939)) ([794bf83](https://github.com/googleapis/java-bigquery/commit/794bf83e84efc0712638bebde5158777b9c89397)) + +## [2.54.1](https://github.com/googleapis/java-bigquery/compare/v2.54.0...v2.54.1) (2025-08-13) + + +### Bug Fixes + +* Adapt graalvm config to arrow update ([#3928](https://github.com/googleapis/java-bigquery/issues/3928)) ([ecfabc4](https://github.com/googleapis/java-bigquery/commit/ecfabc4b70922d0e697699ec5508a7328cadacf8)) + + +### Dependencies + +* Update dependency com.google.cloud:sdk-platform-java-config to v3.51.0 ([#3924](https://github.com/googleapis/java-bigquery/issues/3924)) ([cb66be5](https://github.com/googleapis/java-bigquery/commit/cb66be596d1bfd0a5aed75f5a0e36d80269c7f6a)) + +## [2.54.0](https://github.com/googleapis/java-bigquery/compare/v2.53.0...v2.54.0) (2025-07-31) + + +### Features + +* **bigquery:** Add OpenTelemetry Samples ([#3899](https://github.com/googleapis/java-bigquery/issues/3899)) ([e3d9ed9](https://github.com/googleapis/java-bigquery/commit/e3d9ed92ca5d9b58b5747960d74f895ed8733ebf)) +* **bigquery:** Add otel metrics to request headers ([#3900](https://github.com/googleapis/java-bigquery/issues/3900)) ([4071e4c](https://github.com/googleapis/java-bigquery/commit/4071e4cb2547b236183fd4fbb92c73f074cf2fa0)) + + +### Dependencies + +* Update dependency com.google.api.grpc:proto-google-cloud-bigqueryconnection-v1 to v2.70.0 ([#3890](https://github.com/googleapis/java-bigquery/issues/3890)) ([84207e2](https://github.com/googleapis/java-bigquery/commit/84207e297eec75bcb4f1cc1b64423d7c2ddd6c30)) +* Update dependency com.google.apis:google-api-services-bigquery to v2-rev20250706-2.0.0 ([#3910](https://github.com/googleapis/java-bigquery/issues/3910)) ([ae5c971](https://github.com/googleapis/java-bigquery/commit/ae5c97146c7076e90c000fd98b797ec8e08a9cd8)) +* Update dependency com.google.cloud:sdk-platform-java-config to v3.50.2 ([#3901](https://github.com/googleapis/java-bigquery/issues/3901)) ([8205623](https://github.com/googleapis/java-bigquery/commit/82056237f194a6c99ec4fb3a4315023efdedff1b)) +* Update dependency io.opentelemetry:opentelemetry-api to v1.52.0 ([#3902](https://github.com/googleapis/java-bigquery/issues/3902)) ([772407b](https://github.com/googleapis/java-bigquery/commit/772407b12f4da005f79eafc944d4c53f0eec5c27)) +* Update dependency io.opentelemetry:opentelemetry-bom to v1.52.0 ([#3903](https://github.com/googleapis/java-bigquery/issues/3903)) ([509a6fc](https://github.com/googleapis/java-bigquery/commit/509a6fc0bb7e7a101bf0d4334a3ff1adde2cab09)) +* Update dependency io.opentelemetry:opentelemetry-context to v1.52.0 ([#3904](https://github.com/googleapis/java-bigquery/issues/3904)) ([96c1bae](https://github.com/googleapis/java-bigquery/commit/96c1bae0fcdfdfc2dbb25dcae5007c5d02111a8c)) +* Update dependency io.opentelemetry:opentelemetry-exporter-logging to v1.52.0 ([#3905](https://github.com/googleapis/java-bigquery/issues/3905)) ([28ee4c9](https://github.com/googleapis/java-bigquery/commit/28ee4c941b99b1fe3803aefbe7a8ae57100d76cb)) + +## [2.53.0](https://github.com/googleapis/java-bigquery/compare/v2.52.0...v2.53.0) (2025-07-14) + + +### Features + +* **bigquery:** Add OpenTelemetry support to BQ rpcs ([#3860](https://github.com/googleapis/java-bigquery/issues/3860)) ([e2d23c1](https://github.com/googleapis/java-bigquery/commit/e2d23c1b15f2c48a4113f82b920f5c29c4b5dfea)) +* **bigquery:** Add support for custom timezones and timestamps ([#3859](https://github.com/googleapis/java-bigquery/issues/3859)) ([e5467c9](https://github.com/googleapis/java-bigquery/commit/e5467c917c63ac066edcbcd902cc2093a39971a3)) +* Next release from main branch is 2.53.0 ([#3879](https://github.com/googleapis/java-bigquery/issues/3879)) ([c47a062](https://github.com/googleapis/java-bigquery/commit/c47a062136fea4de91190cafb1f11bac6abbbe3a)) + + +### Bug Fixes + +* Load jobs preserve ascii control characters configuration ([#3876](https://github.com/googleapis/java-bigquery/issues/3876)) ([5cfdf85](https://github.com/googleapis/java-bigquery/commit/5cfdf855fa0cf206660fd89743cbaabf3afa75a3)) + + +### Dependencies + +* Update dependency com.google.api.grpc:proto-google-cloud-bigqueryconnection-v1 to v2.69.0 ([#3870](https://github.com/googleapis/java-bigquery/issues/3870)) ([a7f1007](https://github.com/googleapis/java-bigquery/commit/a7f1007b5242da2c0adebbb309a908d7d4db5974)) +* Update dependency com.google.apis:google-api-services-bigquery to v2-rev20250615-2.0.0 ([#3872](https://github.com/googleapis/java-bigquery/issues/3872)) ([f081589](https://github.com/googleapis/java-bigquery/commit/f08158955b7fec3c2ced6332b6e4d76cc13f2e90)) +* Update dependency com.google.cloud:sdk-platform-java-config to v3.50.1 ([#3878](https://github.com/googleapis/java-bigquery/issues/3878)) ([0e971b8](https://github.com/googleapis/java-bigquery/commit/0e971b8ace013caa31b8a02a21038e94bebae2a5)) + + +### Documentation + +* Update maven format command ([#3877](https://github.com/googleapis/java-bigquery/issues/3877)) ([d2918da](https://github.com/googleapis/java-bigquery/commit/d2918da844cd20ca1602c6fcf9fa1df685f261fc)) + ## [2.52.0](https://github.com/googleapis/java-bigquery/compare/v2.51.0...v2.52.0) (2025-06-25) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 0599033d79..5456fad053 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -88,7 +88,7 @@ Code in this repo is formatted with [google-java-format](https://github.com/google/google-java-format). To run formatting on your project, you can run: ``` -mvn com.coveo:fmt-maven-plugin:format +mvn com.spotify.fmt:fmt-maven-plugin:format ``` [1]: https://cloud.google.com/docs/authentication/getting-started#creating_a_service_account diff --git a/benchmark/pom.xml b/benchmark/pom.xml index bb58ca1e1c..688debd416 100644 --- a/benchmark/pom.xml +++ b/benchmark/pom.xml @@ -6,7 +6,7 @@ google-cloud-bigquery-parent com.google.cloud - 2.52.0 + 2.55.0 diff --git a/google-cloud-bigquery-bom/pom.xml b/google-cloud-bigquery-bom/pom.xml index 836073eb4c..be30269f71 100644 --- a/google-cloud-bigquery-bom/pom.xml +++ b/google-cloud-bigquery-bom/pom.xml @@ -3,12 +3,12 @@ 4.0.0 com.google.cloud google-cloud-bigquery-bom - 2.52.0 + 2.55.0 pom com.google.cloud sdk-platform-java-config - 3.50.0 + 3.52.1 @@ -54,7 +54,7 @@ com.google.cloud google-cloud-bigquery - 2.52.0 + 2.55.0 diff --git a/google-cloud-bigquery/clirr-ignored-differences.xml b/google-cloud-bigquery/clirr-ignored-differences.xml index e048f4ce82..bd455d2d4f 100644 --- a/google-cloud-bigquery/clirr-ignored-differences.xml +++ b/google-cloud-bigquery/clirr-ignored-differences.xml @@ -2,6 +2,76 @@ + + 7013 + com/google/cloud/bigquery/ExternalTableDefinition* + *TimeZone(*) + + + 7013 + com/google/cloud/bigquery/ExternalTableDefinition* + *DateFormat(*) + + + 7013 + com/google/cloud/bigquery/ExternalTableDefinition* + *DatetimeFormat(*) + + + 7013 + com/google/cloud/bigquery/ExternalTableDefinition* + *TimeFormat(*) + + + 7013 + com/google/cloud/bigquery/ExternalTableDefinition* + *TimestampFormat(*) + + + 7013 + com/google/cloud/bigquery/ExternalTableDefinition* + *SourceColumnMatch(*) + + + 7013 + com/google/cloud/bigquery/ExternalTableDefinition* + *NullMarkers(*) + + + 7013 + com/google/cloud/bigquery/LoadJobConfiguration* + *TimeZone(*) + + + 7013 + com/google/cloud/bigquery/LoadJobConfiguration* + *DateFormat(*) + + + 7013 + com/google/cloud/bigquery/LoadJobConfiguration* + *DatetimeFormat(*) + + + 7013 + com/google/cloud/bigquery/LoadJobConfiguration* + *TimeFormat(*) + + + 7013 + com/google/cloud/bigquery/LoadJobConfiguration* + *TimestampFormat(*) + + + 7013 + com/google/cloud/bigquery/LoadJobConfiguration* + *SourceColumnMatch(*) + + + 7013 + com/google/cloud/bigquery/LoadJobConfiguration* + *NullMarkers(*) + 7004 com/google/cloud/bigquery/BigQueryRetryHelper diff --git a/google-cloud-bigquery/pom.xml b/google-cloud-bigquery/pom.xml index 644fe0ef5b..2cae0f6f11 100644 --- a/google-cloud-bigquery/pom.xml +++ b/google-cloud-bigquery/pom.xml @@ -3,7 +3,7 @@ 4.0.0 com.google.cloud google-cloud-bigquery - 2.52.0 + 2.55.0 jar BigQuery https://github.com/googleapis/java-bigquery @@ -11,11 +11,10 @@ com.google.cloud google-cloud-bigquery-parent - 2.52.0 + 2.55.0 google-cloud-bigquery - 4.1.119.Final @@ -117,37 +116,6 @@ org.apache.arrow arrow-memory-netty - - - - io.netty - netty-common - - - io.netty - netty-buffer - - - runtime - - - - io.netty - netty-common - ${netty.version} - runtime - - - io.netty - netty-buffer - ${netty.version} - runtime @@ -290,6 +258,7 @@ true -J--add-opens=java.base/java.nio=org.apache.arrow.memory.core,ALL-UNNAMED + -J--add-opens=java.base/java.nio=java-base,ALL-UNNAMED diff --git a/google-cloud-bigquery/src/main/java/com/google/cloud/bigquery/BigQueryBaseService.java b/google-cloud-bigquery/src/main/java/com/google/cloud/bigquery/BigQueryBaseService.java index 9760158735..bdcefb3d96 100644 --- a/google-cloud-bigquery/src/main/java/com/google/cloud/bigquery/BigQueryBaseService.java +++ b/google-cloud-bigquery/src/main/java/com/google/cloud/bigquery/BigQueryBaseService.java @@ -26,7 +26,7 @@ protected BigQueryBaseService(ServiceOptions options) { super(options); } - public static final ExceptionHandler BIGQUERY_EXCEPTION_HANDLER = + public static final ExceptionHandler DEFAULT_BIGQUERY_EXCEPTION_HANDLER = ExceptionHandler.newBuilder() .abortOn(RuntimeException.class) .retryOn(java.net.ConnectException.class) // retry on Connection Exception diff --git a/google-cloud-bigquery/src/main/java/com/google/cloud/bigquery/BigQueryImpl.java b/google-cloud-bigquery/src/main/java/com/google/cloud/bigquery/BigQueryImpl.java index a32a600c3f..088d15c09c 100644 --- a/google-cloud-bigquery/src/main/java/com/google/cloud/bigquery/BigQueryImpl.java +++ b/google-cloud-bigquery/src/main/java/com/google/cloud/bigquery/BigQueryImpl.java @@ -293,7 +293,7 @@ public com.google.api.services.bigquery.model.Dataset call() throws IOException } }, getOptions().getRetrySettings(), - BigQueryBaseService.BIGQUERY_EXCEPTION_HANDLER, + getOptions().getResultRetryAlgorithm(), getOptions().getClock(), EMPTY_RETRY_CONFIG, getOptions().isOpenTelemetryTracingEnabled(), @@ -340,7 +340,7 @@ public com.google.api.services.bigquery.model.Table call() throws IOException { } }, getOptions().getRetrySettings(), - BigQueryBaseService.BIGQUERY_EXCEPTION_HANDLER, + getOptions().getResultRetryAlgorithm(), getOptions().getClock(), EMPTY_RETRY_CONFIG, getOptions().isOpenTelemetryTracingEnabled(), @@ -396,7 +396,7 @@ public com.google.api.services.bigquery.model.Routine call() throws IOException } }, getOptions().getRetrySettings(), - BigQueryBaseService.BIGQUERY_EXCEPTION_HANDLER, + getOptions().getResultRetryAlgorithm(), getOptions().getClock(), EMPTY_RETRY_CONFIG, getOptions().isOpenTelemetryTracingEnabled(), @@ -490,7 +490,7 @@ public com.google.api.services.bigquery.model.Job call() throws IOException { ? RetryOption.mergeToSettings( getOptions().getRetrySettings(), getRetryOptions(optionsMap)) : getOptions().getRetrySettings(), - BigQueryBaseService.BIGQUERY_EXCEPTION_HANDLER, + getOptions().getResultRetryAlgorithm(), getOptions().getClock(), getBigQueryRetryConfig(optionsMap) != null ? getBigQueryRetryConfig(optionsMap) @@ -586,7 +586,7 @@ public com.google.api.services.bigquery.model.Dataset call() throws IOException } }, getOptions().getRetrySettings(), - BigQueryBaseService.BIGQUERY_EXCEPTION_HANDLER, + getOptions().getResultRetryAlgorithm(), getOptions().getClock(), EMPTY_RETRY_CONFIG, getOptions().isOpenTelemetryTracingEnabled(), @@ -652,7 +652,7 @@ private static Page listDatasets( } }, serviceOptions.getRetrySettings(), - BigQueryBaseService.BIGQUERY_EXCEPTION_HANDLER, + serviceOptions.getResultRetryAlgorithm(), serviceOptions.getClock(), EMPTY_RETRY_CONFIG, serviceOptions.isOpenTelemetryTracingEnabled(), @@ -704,7 +704,7 @@ public Boolean call() throws IOException { } }, getOptions().getRetrySettings(), - BigQueryBaseService.BIGQUERY_EXCEPTION_HANDLER, + getOptions().getResultRetryAlgorithm(), getOptions().getClock(), EMPTY_RETRY_CONFIG, getOptions().isOpenTelemetryTracingEnabled(), @@ -755,7 +755,7 @@ public Boolean call() throws IOException { } }, getOptions().getRetrySettings(), - BigQueryBaseService.BIGQUERY_EXCEPTION_HANDLER, + getOptions().getResultRetryAlgorithm(), getOptions().getClock(), EMPTY_RETRY_CONFIG, getOptions().isOpenTelemetryTracingEnabled(), @@ -801,7 +801,7 @@ public Boolean call() throws IOException { } }, getOptions().getRetrySettings(), - BigQueryBaseService.BIGQUERY_EXCEPTION_HANDLER, + getOptions().getResultRetryAlgorithm(), getOptions().getClock(), EMPTY_RETRY_CONFIG, getOptions().isOpenTelemetryTracingEnabled(), @@ -847,7 +847,7 @@ public Boolean call() throws IOException { } }, getOptions().getRetrySettings(), - BigQueryBaseService.BIGQUERY_EXCEPTION_HANDLER, + getOptions().getResultRetryAlgorithm(), getOptions().getClock(), EMPTY_RETRY_CONFIG, getOptions().isOpenTelemetryTracingEnabled(), @@ -891,7 +891,7 @@ public Boolean call() throws IOException { } }, getOptions().getRetrySettings(), - BigQueryBaseService.BIGQUERY_EXCEPTION_HANDLER, + getOptions().getResultRetryAlgorithm(), getOptions().getClock(), EMPTY_RETRY_CONFIG, getOptions().isOpenTelemetryTracingEnabled(), @@ -932,7 +932,7 @@ public com.google.api.services.bigquery.model.Dataset call() throws IOException } }, getOptions().getRetrySettings(), - BigQueryBaseService.BIGQUERY_EXCEPTION_HANDLER, + getOptions().getResultRetryAlgorithm(), getOptions().getClock(), EMPTY_RETRY_CONFIG, getOptions().isOpenTelemetryTracingEnabled(), @@ -979,7 +979,7 @@ public com.google.api.services.bigquery.model.Table call() throws IOException { } }, getOptions().getRetrySettings(), - BigQueryBaseService.BIGQUERY_EXCEPTION_HANDLER, + getOptions().getResultRetryAlgorithm(), getOptions().getClock(), EMPTY_RETRY_CONFIG, getOptions().isOpenTelemetryTracingEnabled(), @@ -1025,7 +1025,7 @@ public com.google.api.services.bigquery.model.Model call() throws IOException { } }, getOptions().getRetrySettings(), - BigQueryBaseService.BIGQUERY_EXCEPTION_HANDLER, + getOptions().getResultRetryAlgorithm(), getOptions().getClock(), EMPTY_RETRY_CONFIG, getOptions().isOpenTelemetryTracingEnabled(), @@ -1071,7 +1071,7 @@ public com.google.api.services.bigquery.model.Routine call() throws IOException } }, getOptions().getRetrySettings(), - BigQueryBaseService.BIGQUERY_EXCEPTION_HANDLER, + getOptions().getResultRetryAlgorithm(), getOptions().getClock(), EMPTY_RETRY_CONFIG, getOptions().isOpenTelemetryTracingEnabled(), @@ -1125,7 +1125,7 @@ public com.google.api.services.bigquery.model.Table call() throws IOException { } }, getOptions().getRetrySettings(), - BigQueryBaseService.BIGQUERY_EXCEPTION_HANDLER, + getOptions().getResultRetryAlgorithm(), getOptions().getClock(), EMPTY_RETRY_CONFIG, getOptions().isOpenTelemetryTracingEnabled(), @@ -1184,7 +1184,7 @@ public com.google.api.services.bigquery.model.Model call() throws IOException { } }, getOptions().getRetrySettings(), - BigQueryBaseService.BIGQUERY_EXCEPTION_HANDLER, + getOptions().getResultRetryAlgorithm(), getOptions().getClock(), EMPTY_RETRY_CONFIG, getOptions().isOpenTelemetryTracingEnabled(), @@ -1243,7 +1243,7 @@ public com.google.api.services.bigquery.model.Routine call() throws IOException } }, getOptions().getRetrySettings(), - BigQueryBaseService.BIGQUERY_EXCEPTION_HANDLER, + getOptions().getResultRetryAlgorithm(), getOptions().getClock(), EMPTY_RETRY_CONFIG, getOptions().isOpenTelemetryTracingEnabled(), @@ -1461,7 +1461,7 @@ public Tuple> cal } }, serviceOptions.getRetrySettings(), - BigQueryBaseService.BIGQUERY_EXCEPTION_HANDLER, + serviceOptions.getResultRetryAlgorithm(), serviceOptions.getClock(), EMPTY_RETRY_CONFIG, serviceOptions.isOpenTelemetryTracingEnabled(), @@ -1502,7 +1502,7 @@ public Tuple> cal } }, serviceOptions.getRetrySettings(), - BigQueryBaseService.BIGQUERY_EXCEPTION_HANDLER, + serviceOptions.getResultRetryAlgorithm(), serviceOptions.getClock(), EMPTY_RETRY_CONFIG, serviceOptions.isOpenTelemetryTracingEnabled(), @@ -1543,7 +1543,7 @@ private static Page listRoutines( } }, serviceOptions.getRetrySettings(), - BigQueryBaseService.BIGQUERY_EXCEPTION_HANDLER, + serviceOptions.getResultRetryAlgorithm(), serviceOptions.getClock(), EMPTY_RETRY_CONFIG, serviceOptions.isOpenTelemetryTracingEnabled(), @@ -1625,7 +1625,7 @@ public TableDataInsertAllResponse call() throws Exception { } }, getOptions().getRetrySettings(), - BigQueryBaseService.BIGQUERY_EXCEPTION_HANDLER, + getOptions().getResultRetryAlgorithm(), getOptions().getClock(), EMPTY_RETRY_CONFIG, getOptions().isOpenTelemetryTracingEnabled(), @@ -1719,7 +1719,7 @@ public TableDataList call() throws IOException { } }, serviceOptions.getRetrySettings(), - BigQueryBaseService.BIGQUERY_EXCEPTION_HANDLER, + serviceOptions.getResultRetryAlgorithm(), serviceOptions.getClock(), EMPTY_RETRY_CONFIG, serviceOptions.isOpenTelemetryTracingEnabled(), @@ -1793,7 +1793,7 @@ public com.google.api.services.bigquery.model.Job call() throws IOException { } }, getOptions().getRetrySettings(), - BigQueryBaseService.BIGQUERY_EXCEPTION_HANDLER, + getOptions().getResultRetryAlgorithm(), getOptions().getClock(), EMPTY_RETRY_CONFIG, getOptions().isOpenTelemetryTracingEnabled(), @@ -1850,7 +1850,7 @@ public Tuple> call( } }, serviceOptions.getRetrySettings(), - BigQueryBaseService.BIGQUERY_EXCEPTION_HANDLER, + serviceOptions.getResultRetryAlgorithm(), serviceOptions.getClock(), EMPTY_RETRY_CONFIG, serviceOptions.isOpenTelemetryTracingEnabled(), @@ -1905,7 +1905,7 @@ public Boolean call() throws IOException { } }, getOptions().getRetrySettings(), - BigQueryBaseService.BIGQUERY_EXCEPTION_HANDLER, + getOptions().getResultRetryAlgorithm(), getOptions().getClock(), EMPTY_RETRY_CONFIG, getOptions().isOpenTelemetryTracingEnabled(), @@ -1992,7 +1992,7 @@ public com.google.api.services.bigquery.model.QueryResponse call() } }, getOptions().getRetrySettings(), - BigQueryBaseService.BIGQUERY_EXCEPTION_HANDLER, + getOptions().getResultRetryAlgorithm(), getOptions().getClock(), DEFAULT_RETRY_CONFIG, getOptions().isOpenTelemetryTracingEnabled(), @@ -2169,7 +2169,7 @@ public GetQueryResultsResponse call() throws IOException { } }, serviceOptions.getRetrySettings(), - BigQueryBaseService.BIGQUERY_EXCEPTION_HANDLER, + serviceOptions.getResultRetryAlgorithm(), serviceOptions.getClock(), DEFAULT_RETRY_CONFIG, serviceOptions.isOpenTelemetryTracingEnabled(), @@ -2240,7 +2240,7 @@ public com.google.api.services.bigquery.model.Policy call() throws IOException { } }, getOptions().getRetrySettings(), - BigQueryBaseService.BIGQUERY_EXCEPTION_HANDLER, + getOptions().getResultRetryAlgorithm(), getOptions().getClock(), EMPTY_RETRY_CONFIG, getOptions().isOpenTelemetryTracingEnabled(), @@ -2286,7 +2286,7 @@ public com.google.api.services.bigquery.model.Policy call() throws IOException { } }, getOptions().getRetrySettings(), - BigQueryBaseService.BIGQUERY_EXCEPTION_HANDLER, + getOptions().getResultRetryAlgorithm(), getOptions().getClock(), EMPTY_RETRY_CONFIG, getOptions().isOpenTelemetryTracingEnabled(), @@ -2334,7 +2334,7 @@ public com.google.api.services.bigquery.model.TestIamPermissionsResponse call() } }, getOptions().getRetrySettings(), - BigQueryBaseService.BIGQUERY_EXCEPTION_HANDLER, + getOptions().getResultRetryAlgorithm(), getOptions().getClock(), EMPTY_RETRY_CONFIG, getOptions().isOpenTelemetryTracingEnabled(), diff --git a/google-cloud-bigquery/src/main/java/com/google/cloud/bigquery/BigQueryOptions.java b/google-cloud-bigquery/src/main/java/com/google/cloud/bigquery/BigQueryOptions.java index 36eeb20869..7adb58d3a2 100644 --- a/google-cloud-bigquery/src/main/java/com/google/cloud/bigquery/BigQueryOptions.java +++ b/google-cloud-bigquery/src/main/java/com/google/cloud/bigquery/BigQueryOptions.java @@ -17,6 +17,7 @@ package com.google.cloud.bigquery; import com.google.api.core.BetaApi; +import com.google.api.gax.retrying.ResultRetryAlgorithm; import com.google.cloud.ServiceDefaults; import com.google.cloud.ServiceOptions; import com.google.cloud.ServiceRpc; @@ -43,6 +44,7 @@ public class BigQueryOptions extends ServiceOptions { private JobCreationMode defaultJobCreationMode = JobCreationMode.JOB_CREATION_MODE_UNSPECIFIED; private boolean enableOpenTelemetryTracing; private Tracer openTelemetryTracer; + private ResultRetryAlgorithm resultRetryAlgorithm; public static class DefaultBigQueryFactory implements BigQueryFactory { @@ -70,6 +72,7 @@ public static class Builder extends ServiceOptions.Builder resultRetryAlgorithm; private Builder() {} @@ -118,6 +121,11 @@ public Builder setOpenTelemetryTracer(Tracer tracer) { return this; } + public Builder setResultRetryAlgorithm(ResultRetryAlgorithm resultRetryAlgorithm) { + this.resultRetryAlgorithm = resultRetryAlgorithm; + return this; + } + @Override public BigQueryOptions build() { return new BigQueryOptions(this); @@ -130,6 +138,11 @@ private BigQueryOptions(Builder builder) { this.useInt64Timestamps = builder.useInt64Timestamps; this.enableOpenTelemetryTracing = builder.enableOpenTelemetryTracing; this.openTelemetryTracer = builder.openTelemetryTracer; + if (builder.resultRetryAlgorithm != null) { + this.resultRetryAlgorithm = builder.resultRetryAlgorithm; + } else { + this.resultRetryAlgorithm = BigQueryBaseService.DEFAULT_BIGQUERY_EXCEPTION_HANDLER; + } } private static class BigQueryDefaults implements ServiceDefaults { @@ -221,6 +234,10 @@ public Tracer getOpenTelemetryTracer() { return openTelemetryTracer; } + public ResultRetryAlgorithm getResultRetryAlgorithm() { + return resultRetryAlgorithm; + } + @SuppressWarnings("unchecked") @Override public Builder toBuilder() { diff --git a/google-cloud-bigquery/src/main/java/com/google/cloud/bigquery/ConnectionImpl.java b/google-cloud-bigquery/src/main/java/com/google/cloud/bigquery/ConnectionImpl.java index b12ad85564..c3465c33a8 100644 --- a/google-cloud-bigquery/src/main/java/com/google/cloud/bigquery/ConnectionImpl.java +++ b/google-cloud-bigquery/src/main/java/com/google/cloud/bigquery/ConnectionImpl.java @@ -474,7 +474,7 @@ private BigQueryResult queryRpc( .getBigQueryRpcV2() .queryRpcSkipExceptionTranslation(projectId, queryRequest), bigQueryOptions.getRetrySettings(), - BigQueryBaseService.BIGQUERY_EXCEPTION_HANDLER, + bigQueryOptions.getResultRetryAlgorithm(), bigQueryOptions.getClock(), retryConfig, false, @@ -932,7 +932,7 @@ private Job getQueryJobRpc(JobId jobId) { completeJobId.getJob(), completeJobId.getLocation()), bigQueryOptions.getRetrySettings(), - BigQueryBaseService.BIGQUERY_EXCEPTION_HANDLER, + bigQueryOptions.getResultRetryAlgorithm(), bigQueryOptions.getClock(), EMPTY_RETRY_CONFIG, false, @@ -979,7 +979,7 @@ TableDataList tableDataListRpc(TableId destinationTable, String pageToken) { connectionSettings.getMaxResultPerPage(), pageToken), bigQueryOptions.getRetrySettings(), - BigQueryBaseService.BIGQUERY_EXCEPTION_HANDLER, + bigQueryOptions.getResultRetryAlgorithm(), bigQueryOptions.getClock(), EMPTY_RETRY_CONFIG, false, @@ -1212,7 +1212,7 @@ GetQueryResultsResponse getQueryResultsFirstPage(JobId jobId) { connectionSettings.getMaxResultPerPage(), timeoutMs), bigQueryOptions.getRetrySettings(), - BigQueryBaseService.BIGQUERY_EXCEPTION_HANDLER, + bigQueryOptions.getResultRetryAlgorithm(), bigQueryOptions.getClock(), retryConfig, false, @@ -1477,7 +1477,7 @@ com.google.api.services.bigquery.model.Job createQueryJob( .getBigQueryRpcV2() .createJobForQuerySkipExceptionTranslation(jobPb), bigQueryOptions.getRetrySettings(), - BigQueryBaseService.BIGQUERY_EXCEPTION_HANDLER, + bigQueryOptions.getResultRetryAlgorithm(), bigQueryOptions.getClock(), retryConfig, false, @@ -1522,7 +1522,7 @@ com.google.api.services.bigquery.model.Job createDryRunJob(String sql) { .getBigQueryRpcV2() .createJobForQuerySkipExceptionTranslation(jobPb), bigQueryOptions.getRetrySettings(), - BigQueryBaseService.BIGQUERY_EXCEPTION_HANDLER, + bigQueryOptions.getResultRetryAlgorithm(), bigQueryOptions.getClock(), retryConfig, false, diff --git a/google-cloud-bigquery/src/main/java/com/google/cloud/bigquery/ExternalTableDefinition.java b/google-cloud-bigquery/src/main/java/com/google/cloud/bigquery/ExternalTableDefinition.java index ea4cceeade..c1859c3f9f 100644 --- a/google-cloud-bigquery/src/main/java/com/google/cloud/bigquery/ExternalTableDefinition.java +++ b/google-cloud-bigquery/src/main/java/com/google/cloud/bigquery/ExternalTableDefinition.java @@ -19,9 +19,12 @@ import static com.google.common.base.Preconditions.checkArgument; import static com.google.common.base.Strings.isNullOrEmpty; +import com.google.api.core.ApiFunction; import com.google.api.services.bigquery.model.ExternalDataConfiguration; import com.google.api.services.bigquery.model.Table; import com.google.auto.value.AutoValue; +import com.google.cloud.StringEnumType; +import com.google.cloud.StringEnumValue; import com.google.common.base.Function; import com.google.common.collect.ImmutableList; import java.util.List; @@ -57,6 +60,46 @@ public ExternalDataConfiguration apply(ExternalTableDefinition tableInfo) { private static final long serialVersionUID = -5951580238459622025L; + public static final class SourceColumnMatch extends StringEnumValue { + private static final long serialVersionUID = 818920627219751207L; + private static final ApiFunction CONSTRUCTOR = + new ApiFunction() { + @Override + public SourceColumnMatch apply(String constant) { + return new SourceColumnMatch(constant); + } + }; + + private static final StringEnumType type = + new StringEnumType(SourceColumnMatch.class, CONSTRUCTOR); + + public static final SourceColumnMatch POSITION = type.createAndRegister("POSITION"); + + public static final SourceColumnMatch NAME = type.createAndRegister("NAME"); + + private SourceColumnMatch(String constant) { + super(constant); + } + + /** + * Get the SourceColumnMatch for the given String constant, and throw an exception if the + * constant is not recognized. + */ + public static SourceColumnMatch valueOfStrict(String constant) { + return type.valueOfStrict(constant); + } + + /** Get the SourceColumnMatch for the given String constant, and allow unrecognized values. */ + public static SourceColumnMatch valueOf(String constant) { + return type.valueOf(constant); + } + + /** Return the known values for SourceColumnMatch. */ + public static SourceColumnMatch[] values() { + return type.values(); + } + } + @AutoValue.Builder public abstract static class Builder extends TableDefinition.Builder { @@ -215,6 +258,45 @@ public Builder setMaxStaleness(String maxStaleness) { abstract Builder setMaxStalenessInner(String maxStaleness); + /** + * Time zone used when parsing timestamp values that do not have specific time zone information + * (e.g. 2024-04-20 12:34:56). The expected format is a IANA timezone string (e.g. + * America/Los_Angeles). + */ + public abstract Builder setTimeZone(String timeZone); + + /** Format used to parse DATE values. Supports C-style and SQL-style values. */ + public abstract Builder setDateFormat(String dateFormat); + + /** Format used to parse DATETIME values. Supports C-style and SQL-style values. */ + public abstract Builder setDatetimeFormat(String datetimeFormat); + + /** Format used to parse TIME values. Supports C-style and SQL-style values. */ + public abstract Builder setTimeFormat(String timeFormat); + + /** Format used to parse TIMESTAMP values. Supports C-style and SQL-style values. */ + public abstract Builder setTimestampFormat(String timestampFormat); + + /** + * Controls the strategy used to match loaded columns to the schema. If not set, a sensible + * default is chosen based on how the schema is provided. If autodetect is used, then columns + * are matched by name. Otherwise, columns are matched by position. This is done to keep the + * behavior backward-compatible. Acceptable values are: POSITION - matches by position. This + * assumes that the columns are ordered the same way as the schema. NAME - matches by name. This + * reads the header row as column names and reorders columns to match the field names in the + * schema. + */ + public abstract Builder setSourceColumnMatch(SourceColumnMatch sourceColumnMatch); + + /** + * A list of strings represented as SQL NULL value in a CSV file. null_marker and null_markers + * can't be set at the same time. If null_marker is set, null_markers has to be not set. If + * null_markers is set, null_marker has to be not set. If both null_marker and null_markers are + * set at the same time, a user error would be thrown. Any strings listed in null_markers, + * including empty string would be interpreted as SQL NULL. This applies to all column types. + */ + public abstract Builder setNullMarkers(List nullMarkers); + /** Creates an {@code ExternalTableDefinition} object. */ @Override public abstract ExternalTableDefinition build(); @@ -373,6 +455,37 @@ public HivePartitioningOptions getHivePartitioningOptions() { return getHivePartitioningOptionsInner(); } + /** + * Returns the time zone used when parsing timestamp values that don't have specific time zone + * information. + */ + @Nullable + public abstract String getTimeZone(); + + /** Returns the format used to parse DATE values. */ + @Nullable + public abstract String getDateFormat(); + + /** Returns the format used to parse DATETIME values. */ + @Nullable + public abstract String getDatetimeFormat(); + + /** Returns the format used to parse TIME values. */ + @Nullable + public abstract String getTimeFormat(); + + /** Returns the format used to parse TIMESTAMP values. */ + @Nullable + public abstract String getTimestampFormat(); + + /** Returns the strategy used to match loaded columns to the schema, either POSITION or NAME. */ + @Nullable + public abstract SourceColumnMatch getSourceColumnMatch(); + + /** Returns a list of strings represented as SQL NULL value in a CSV file. */ + @Nullable + public abstract List getNullMarkers(); + @Nullable abstract HivePartitioningOptions getHivePartitioningOptionsInner(); @@ -454,6 +567,29 @@ com.google.api.services.bigquery.model.ExternalDataConfiguration toExternalDataC if (getMetadataCacheMode() != null) { externalConfigurationPb.setMetadataCacheMode(getMetadataCacheMode()); } + if (getTimeZone() != null) { + externalConfigurationPb.setTimeZone(getTimeZone()); + } + if (getDateFormat() != null) { + externalConfigurationPb.setDateFormat(getDateFormat()); + } + if (getDatetimeFormat() != null) { + externalConfigurationPb.setDatetimeFormat(getDatetimeFormat()); + } + if (getTimeFormat() != null) { + externalConfigurationPb.setTimeFormat(getTimeFormat()); + } + if (getTimestampFormat() != null) { + externalConfigurationPb.setTimestampFormat(getTimestampFormat()); + } + if (getSourceColumnMatch() != null) { + externalConfigurationPb + .getCsvOptions() + .setSourceColumnMatch(getSourceColumnMatch().toString()); + } + if (getNullMarkers() != null) { + externalConfigurationPb.getCsvOptions().setNullMarkers(getNullMarkers()); + } return externalConfigurationPb; } @@ -654,6 +790,31 @@ static ExternalTableDefinition fromPb(Table tablePb) { if (tablePb.getMaxStaleness() != null) { builder.setMaxStaleness(tablePb.getMaxStaleness()); } + if (externalDataConfiguration.getTimeZone() != null) { + builder.setTimeZone(externalDataConfiguration.getTimeZone()); + } + if (externalDataConfiguration.getDateFormat() != null) { + builder.setDateFormat(externalDataConfiguration.getDateFormat()); + } + if (externalDataConfiguration.getDatetimeFormat() != null) { + builder.setDatetimeFormat(externalDataConfiguration.getDatetimeFormat()); + } + if (externalDataConfiguration.getTimeFormat() != null) { + builder.setTimeFormat(externalDataConfiguration.getTimeFormat()); + } + if (externalDataConfiguration.getTimestampFormat() != null) { + builder.setTimestampFormat(externalDataConfiguration.getTimestampFormat()); + } + if (externalDataConfiguration.getCsvOptions() != null) { + if (externalDataConfiguration.getCsvOptions().getSourceColumnMatch() != null) { + builder.setSourceColumnMatch( + SourceColumnMatch.valueOf( + externalDataConfiguration.getCsvOptions().getSourceColumnMatch())); + } + if (externalDataConfiguration.getCsvOptions().getNullMarkers() != null) { + builder.setNullMarkers(externalDataConfiguration.getCsvOptions().getNullMarkers()); + } + } } return builder.build(); } @@ -724,6 +885,31 @@ static ExternalTableDefinition fromExternalDataConfiguration( if (externalDataConfiguration.getMetadataCacheMode() != null) { builder.setMetadataCacheMode(externalDataConfiguration.getMetadataCacheMode()); } + if (externalDataConfiguration.getTimeZone() != null) { + builder.setTimeZone(externalDataConfiguration.getTimeZone()); + } + if (externalDataConfiguration.getDateFormat() != null) { + builder.setDateFormat(externalDataConfiguration.getDateFormat()); + } + if (externalDataConfiguration.getDatetimeFormat() != null) { + builder.setDatetimeFormat(externalDataConfiguration.getDatetimeFormat()); + } + if (externalDataConfiguration.getTimeFormat() != null) { + builder.setTimeFormat(externalDataConfiguration.getTimeFormat()); + } + if (externalDataConfiguration.getTimestampFormat() != null) { + builder.setTimestampFormat(externalDataConfiguration.getTimeFormat()); + } + if (externalDataConfiguration.getCsvOptions() != null) { + if (externalDataConfiguration.getCsvOptions().getSourceColumnMatch() != null) { + builder.setSourceColumnMatch( + SourceColumnMatch.valueOf( + externalDataConfiguration.getCsvOptions().getSourceColumnMatch())); + } + if (externalDataConfiguration.getCsvOptions().getNullMarkers() != null) { + builder.setNullMarkers(externalDataConfiguration.getCsvOptions().getNullMarkers()); + } + } return builder.build(); } diff --git a/google-cloud-bigquery/src/main/java/com/google/cloud/bigquery/LoadJobConfiguration.java b/google-cloud-bigquery/src/main/java/com/google/cloud/bigquery/LoadJobConfiguration.java index 5d17554597..381942cd0b 100644 --- a/google-cloud-bigquery/src/main/java/com/google/cloud/bigquery/LoadJobConfiguration.java +++ b/google-cloud-bigquery/src/main/java/com/google/cloud/bigquery/LoadJobConfiguration.java @@ -18,7 +18,10 @@ import static com.google.common.base.Preconditions.checkNotNull; +import com.google.api.core.ApiFunction; import com.google.api.services.bigquery.model.JobConfigurationLoad; +import com.google.cloud.StringEnumType; +import com.google.cloud.StringEnumValue; import com.google.common.base.MoreObjects.ToStringHelper; import com.google.common.base.Strings; import com.google.common.collect.ImmutableList; @@ -63,6 +66,55 @@ public final class LoadJobConfiguration extends JobConfiguration implements Load private final List connectionProperties; private final Boolean createSession; private final String reservation; + private final String timeZone; + private final String dateFormat; + private final String datetimeFormat; + private final String timeFormat; + private final String timestampFormat; + private final SourceColumnMatch sourceColumnMatch; + private final List nullMarkers; + + public static final class SourceColumnMatch extends StringEnumValue { + private static final long serialVersionUID = 818920627219751207L; + private static final ApiFunction CONSTRUCTOR = + new ApiFunction() { + @Override + public SourceColumnMatch apply(String constant) { + return new SourceColumnMatch(constant); + } + }; + + private static final StringEnumType type = + new StringEnumType(SourceColumnMatch.class, CONSTRUCTOR); + + public static final SourceColumnMatch SOURCE_COLUMN_MATCH_UNSPECIFIED = + type.createAndRegister("SOURCE_COLUMN_MATCH_UNSPECIFIED"); + public static final SourceColumnMatch POSITION = type.createAndRegister("POSITION"); + + public static final SourceColumnMatch NAME = type.createAndRegister("NAME"); + + private SourceColumnMatch(String constant) { + super(constant); + } + + /** + * Get the SourceColumnMatch for the given String constant, and throw an exception if the + * constant is not recognized. + */ + public static SourceColumnMatch valueOfStrict(String constant) { + return type.valueOfStrict(constant); + } + + /** Get the SourceColumnMatch for the given String constant, and allow unrecognized values. */ + public static SourceColumnMatch valueOf(String constant) { + return type.valueOf(constant); + } + + /** Return the known values for SourceColumnMatch. */ + public static SourceColumnMatch[] values() { + return type.values(); + } + } public static final class Builder extends JobConfiguration.Builder implements LoadConfiguration.Builder { @@ -95,6 +147,13 @@ public static final class Builder extends JobConfiguration.Builder connectionProperties; private Boolean createSession; private String reservation; + private String timeZone; + private String dateFormat; + private String datetimeFormat; + private String timeFormat; + private String timestampFormat; + private SourceColumnMatch sourceColumnMatch; + private List nullMarkers; private Builder() { super(Type.LOAD); @@ -129,6 +188,13 @@ private Builder(LoadJobConfiguration loadConfiguration) { this.connectionProperties = loadConfiguration.connectionProperties; this.createSession = loadConfiguration.createSession; this.reservation = loadConfiguration.reservation; + this.timeZone = loadConfiguration.timeZone; + this.dateFormat = loadConfiguration.dateFormat; + this.datetimeFormat = loadConfiguration.datetimeFormat; + this.timeFormat = loadConfiguration.timeFormat; + this.timestampFormat = loadConfiguration.timestampFormat; + this.sourceColumnMatch = loadConfiguration.sourceColumnMatch; + this.nullMarkers = loadConfiguration.nullMarkers; } private Builder(com.google.api.services.bigquery.model.JobConfiguration configurationPb) { @@ -153,6 +219,7 @@ private Builder(com.google.api.services.bigquery.model.JobConfiguration configur this.nullMarker = loadConfigurationPb.getNullMarker(); } if (loadConfigurationPb.getAllowJaggedRows() != null + || loadConfigurationPb.getPreserveAsciiControlCharacters() != null || loadConfigurationPb.getAllowQuotedNewlines() != null || loadConfigurationPb.getEncoding() != null || loadConfigurationPb.getFieldDelimiter() != null @@ -163,6 +230,10 @@ private Builder(com.google.api.services.bigquery.model.JobConfiguration configur .setEncoding(loadConfigurationPb.getEncoding()) .setFieldDelimiter(loadConfigurationPb.getFieldDelimiter()) .setQuote(loadConfigurationPb.getQuote()); + if (loadConfigurationPb.getPreserveAsciiControlCharacters() != null) { + builder.setPreserveAsciiControlCharacters( + loadConfigurationPb.getPreserveAsciiControlCharacters()); + } if (loadConfigurationPb.getAllowJaggedRows() != null) { builder.setAllowJaggedRows(loadConfigurationPb.getAllowJaggedRows()); } @@ -238,6 +309,28 @@ private Builder(com.google.api.services.bigquery.model.JobConfiguration configur if (configurationPb.getReservation() != null) { this.reservation = configurationPb.getReservation(); } + if (loadConfigurationPb.getTimeZone() != null) { + this.timeZone = loadConfigurationPb.getTimeZone(); + } + if (loadConfigurationPb.getDateFormat() != null) { + this.dateFormat = loadConfigurationPb.getDateFormat(); + } + if (loadConfigurationPb.getDatetimeFormat() != null) { + this.datetimeFormat = loadConfigurationPb.getDatetimeFormat(); + } + if (loadConfigurationPb.getTimeFormat() != null) { + this.timeFormat = loadConfigurationPb.getTimeFormat(); + } + if (loadConfigurationPb.getTimestampFormat() != null) { + this.timestampFormat = loadConfigurationPb.getTimestampFormat(); + } + if (loadConfigurationPb.getSourceColumnMatch() != null) { + this.sourceColumnMatch = + SourceColumnMatch.valueOf(loadConfigurationPb.getSourceColumnMatch()); + } + if (loadConfigurationPb.getNullMarkers() != null) { + this.nullMarkers = loadConfigurationPb.getNullMarkers(); + } } @Override @@ -449,6 +542,62 @@ public Builder setReservation(String reservation) { return this; } + /** + * [Experimental] Default time zone that will apply when parsing timestamp values that have no + * specific time zone. + */ + public Builder setTimeZone(String timeZone) { + this.timeZone = timeZone; + return this; + } + + /** Date format used for parsing DATE values. */ + public Builder setDateFormat(String dateFormat) { + this.dateFormat = dateFormat; + return this; + } + + /** Date format used for parsing DATETIME values. */ + public Builder setDatetimeFormat(String datetimeFormat) { + this.datetimeFormat = datetimeFormat; + return this; + } + + /** Date format used for parsing TIME values. */ + public Builder setTimeFormat(String timeFormat) { + this.timeFormat = timeFormat; + return this; + } + + /** Date format used for parsing TIMESTAMP values. */ + public Builder setTimestampFormat(String timestampFormat) { + this.timestampFormat = timestampFormat; + return this; + } + + /** + * Controls the strategy used to match loaded columns to the schema. If not set, a sensible + * default is chosen based on how the schema is provided. If autodetect is used, then columns + * are matched by name. Otherwise, columns are matched by position. This is done to keep the + * behavior backward-compatible. + */ + public Builder setSourceColumnMatch(SourceColumnMatch sourceColumnMatch) { + this.sourceColumnMatch = sourceColumnMatch; + return this; + } + + /** + * A list of strings represented as SQL NULL value in a CSV file. null_marker and null_markers + * can't be set at the same time. If null_marker is set, null_markers has to be not set. If + * null_markers is set, null_marker has to be not set. If both null_marker and null_markers are + * set at the same time, a user error would be thrown. Any strings listed in null_markers, + * including empty string would be interpreted as SQL NULL. This applies to all column types. + */ + public Builder setNullMarkers(List nullMarkers) { + this.nullMarkers = nullMarkers; + return this; + } + @Override public LoadJobConfiguration build() { return new LoadJobConfiguration(this); @@ -483,6 +632,13 @@ private LoadJobConfiguration(Builder builder) { this.connectionProperties = builder.connectionProperties; this.createSession = builder.createSession; this.reservation = builder.reservation; + this.timeZone = builder.timeZone; + this.dateFormat = builder.dateFormat; + this.datetimeFormat = builder.datetimeFormat; + this.timeFormat = builder.timeFormat; + this.timestampFormat = builder.timestampFormat; + this.sourceColumnMatch = builder.sourceColumnMatch; + this.nullMarkers = builder.nullMarkers; } @Override @@ -634,6 +790,44 @@ public String getReservation() { return reservation; } + /** + * Returns the time zone used when parsing timestamp values that don't have specific time zone + * information. + */ + public String getTimeZone() { + return timeZone; + } + + /** Returns the format used to parse DATE values. */ + public String getDateFormat() { + return dateFormat; + } + + /** Returns the format used to parse DATETIME values. */ + public String getDatetimeFormat() { + return datetimeFormat; + } + + /** Returns the format used to parse TIME values. */ + public String getTimeFormat() { + return timeFormat; + } + + /** Returns the format used to parse TIMESTAMP values. */ + public String getTimestampFormat() { + return timestampFormat; + } + + /** Returns the strategy used to match loaded columns to the schema, either POSITION or NAME. */ + public SourceColumnMatch getSourceColumnMatch() { + return sourceColumnMatch; + } + + /** Returns a list of strings represented as SQL NULL value in a CSV file. */ + public List getNullMarkers() { + return nullMarkers; + } + @Override public Builder toBuilder() { return new Builder(this); @@ -667,7 +861,14 @@ ToStringHelper toStringHelper() { .add("referenceFileSchemaUri", referenceFileSchemaUri) .add("connectionProperties", connectionProperties) .add("createSession", createSession) - .add("reservation", reservation); + .add("reservation", reservation) + .add("timeZone", timeZone) + .add("dateFormat", dateFormat) + .add("datetimeFormat", datetimeFormat) + .add("timeFormat", timeFormat) + .add("timestampFormat", timestampFormat) + .add("sourceColumnMatch", sourceColumnMatch) + .add("nullMarkers", nullMarkers); } @Override @@ -711,6 +912,7 @@ com.google.api.services.bigquery.model.JobConfiguration toPb() { .setAllowJaggedRows(csvOptions.allowJaggedRows()) .setAllowQuotedNewlines(csvOptions.allowQuotedNewLines()) .setEncoding(csvOptions.getEncoding()) + .setPreserveAsciiControlCharacters(csvOptions.getPreserveAsciiControlCharacters()) .setQuote(csvOptions.getQuote()); if (csvOptions.getSkipLeadingRows() != null) { // todo(mziccard) remove checked cast or comment when #1044 is closed @@ -789,6 +991,27 @@ com.google.api.services.bigquery.model.JobConfiguration toPb() { if (reservation != null) { jobConfiguration.setReservation(reservation); } + if (timeZone != null) { + loadConfigurationPb.setTimeZone(timeZone); + } + if (dateFormat != null) { + loadConfigurationPb.setDateFormat(dateFormat); + } + if (datetimeFormat != null) { + loadConfigurationPb.setDatetimeFormat(datetimeFormat); + } + if (timeFormat != null) { + loadConfigurationPb.setTimeFormat(timeFormat); + } + if (timestampFormat != null) { + loadConfigurationPb.setTimestampFormat(timestampFormat); + } + if (sourceColumnMatch != null) { + loadConfigurationPb.setSourceColumnMatch(sourceColumnMatch.toString()); + } + if (nullMarkers != null) { + loadConfigurationPb.setNullMarkers(nullMarkers); + } jobConfiguration.setLoad(loadConfigurationPb); return jobConfiguration; diff --git a/google-cloud-bigquery/src/main/java/com/google/cloud/bigquery/TableDataWriteChannel.java b/google-cloud-bigquery/src/main/java/com/google/cloud/bigquery/TableDataWriteChannel.java index cc64ec72f5..dde4c08187 100644 --- a/google-cloud-bigquery/src/main/java/com/google/cloud/bigquery/TableDataWriteChannel.java +++ b/google-cloud-bigquery/src/main/java/com/google/cloud/bigquery/TableDataWriteChannel.java @@ -77,7 +77,7 @@ public com.google.api.services.bigquery.model.Job call() throws IOException { } }, getOptions().getRetrySettings(), - BigQueryBaseService.BIGQUERY_EXCEPTION_HANDLER, + getOptions().getResultRetryAlgorithm(), getOptions().getClock(), EMPTY_RETRY_CONFIG, getOptions().isOpenTelemetryTracingEnabled(), @@ -126,7 +126,7 @@ public String call() throws IOException { } }, options.getRetrySettings(), - BigQueryBaseService.BIGQUERY_EXCEPTION_HANDLER, + options.getResultRetryAlgorithm(), options.getClock(), EMPTY_RETRY_CONFIG, options.isOpenTelemetryTracingEnabled(), diff --git a/google-cloud-bigquery/src/main/java/com/google/cloud/bigquery/spi/v2/HttpBigQueryRpc.java b/google-cloud-bigquery/src/main/java/com/google/cloud/bigquery/spi/v2/HttpBigQueryRpc.java index 03e1fb5866..16737dc4b7 100644 --- a/google-cloud-bigquery/src/main/java/com/google/cloud/bigquery/spi/v2/HttpBigQueryRpc.java +++ b/google-cloud-bigquery/src/main/java/com/google/cloud/bigquery/spi/v2/HttpBigQueryRpc.java @@ -69,6 +69,9 @@ import com.google.common.base.Function; import com.google.common.collect.ImmutableList; import com.google.common.collect.Iterables; +import io.opentelemetry.api.common.Attributes; +import io.opentelemetry.api.trace.Span; +import io.opentelemetry.api.trace.SpanKind; import java.io.IOException; import java.math.BigInteger; import java.util.List; @@ -155,7 +158,31 @@ public Dataset getDatasetSkipExceptionTranslation( if (options.containsKey(Option.DATASET_VIEW)) { bqGetRequest.setDatasetView(options.get(Option.DATASET_VIEW).toString()); } - return bqGetRequest.execute(); + bqGetRequest + .getRequestHeaders() + .set("x-goog-otel-enabled", this.options.isOpenTelemetryTracingEnabled()); + + Span getDataset = null; + if (this.options.isOpenTelemetryTracingEnabled() + && this.options.getOpenTelemetryTracer() != null) { + getDataset = + this.options + .getOpenTelemetryTracer() + .spanBuilder("com.google.cloud.bigquery.BigQueryRpc.getDataset") + .setSpanKind(SpanKind.CLIENT) + .setAttribute("bq.rpc.service", "DatasetService") + .setAttribute("bq.rpc.method", "GetDataset") + .setAttribute("bq.rpc.system", "http") + .setAllAttributes(otelAttributesFromOptions(options)) + .startSpan(); + } + + Dataset dataset = bqGetRequest.execute(); + if (getDataset != null) { + getDataset.setAttribute("bq.rpc.response.dataset.id", dataset.getId()); + getDataset.end(); + } + return dataset; } @Override @@ -171,7 +198,7 @@ public Tuple> listDatasets(String projectId, Map> listDatasetsSkipExceptionTranslation( String projectId, Map options) throws IOException { validateRPC(); - DatasetList datasetsList = + Bigquery.Datasets.List datasetsListRequest = bigquery .datasets() .list(projectId) @@ -179,9 +206,34 @@ public Tuple> listDatasetsSkipExceptionTranslation( .setAll(Option.ALL_DATASETS.getBoolean(options)) .setFilter(Option.LABEL_FILTER.getString(options)) .setMaxResults(Option.MAX_RESULTS.getLong(options)) - .setPageToken(Option.PAGE_TOKEN.getString(options)) - .execute(); + .setPageToken(Option.PAGE_TOKEN.getString(options)); + + datasetsListRequest + .getRequestHeaders() + .set("x-goog-otel-enabled", this.options.isOpenTelemetryTracingEnabled()); + + Span listDatasets = null; + if (this.options.isOpenTelemetryTracingEnabled() + && this.options.getOpenTelemetryTracer() != null) { + listDatasets = + this.options + .getOpenTelemetryTracer() + .spanBuilder("com.google.cloud.bigquery.BigQueryRpc.listDatasets") + .setSpanKind(SpanKind.CLIENT) + .setAttribute("bq.rpc.service", "DatasetService") + .setAttribute("bq.rpc.method", "ListDatasets") + .setAttribute("bq.rpc.system", "http") + .setAttribute("bq.rpc.page_token", datasetsListRequest.getPageToken()) + .setAllAttributes(otelAttributesFromOptions(options)) + .startSpan(); + } + + DatasetList datasetsList = datasetsListRequest.execute(); Iterable datasets = datasetsList.getDatasets(); + if (listDatasets != null) { + listDatasets.setAttribute("bq.rpc.next_page_token", datasetsList.getNextPageToken()); + listDatasets.end(); + } return Tuple.of( datasetsList.getNextPageToken(), Iterables.transform( @@ -211,7 +263,30 @@ public Dataset createSkipExceptionTranslation(Dataset dataset, Map op if (options.containsKey(Option.ACCESS_POLICY_VERSION)) { bqCreateRequest.setAccessPolicyVersion((Integer) options.get(Option.ACCESS_POLICY_VERSION)); } - return bqCreateRequest.execute(); + bqCreateRequest + .getRequestHeaders() + .set("x-goog-otel-enabled", this.options.isOpenTelemetryTracingEnabled()); + + Span createDataset = null; + if (this.options.isOpenTelemetryTracingEnabled() + && this.options.getOpenTelemetryTracer() != null) { + createDataset = + this.options + .getOpenTelemetryTracer() + .spanBuilder("com.google.cloud.bigquery.BigQueryRpc.createDataset") + .setSpanKind(SpanKind.CLIENT) + .setAttribute("bq.rpc.service", "DatasetService") + .setAttribute("bq.rpc.method", "InsertDataset") + .setAttribute("bq.rpc.system", "http") + .setAllAttributes(otelAttributesFromOptions(options)) + .startSpan(); + } + Dataset datasetResponse = bqCreateRequest.execute(); + if (createDataset != null) { + createDataset.setAttribute("bq.rpc.response.dataset.id", datasetResponse.getId()); + createDataset.end(); + } + return datasetResponse; } @Override @@ -230,12 +305,37 @@ public Table createSkipExceptionTranslation(Table table, Map options) // unset the type, as it is output only table.setType(null); TableReference reference = table.getTableReference(); - return bigquery - .tables() - .insert(reference.getProjectId(), reference.getDatasetId(), table) - .setPrettyPrint(false) - .setFields(Option.FIELDS.getString(options)) - .execute(); + Bigquery.Tables.Insert bqCreateRequest = + bigquery + .tables() + .insert(reference.getProjectId(), reference.getDatasetId(), table) + .setPrettyPrint(false) + .setFields(Option.FIELDS.getString(options)); + + bqCreateRequest + .getRequestHeaders() + .set("x-goog-otel-enabled", this.options.isOpenTelemetryTracingEnabled()); + + Span createTable = null; + if (this.options.isOpenTelemetryTracingEnabled() + && this.options.getOpenTelemetryTracer() != null) { + createTable = + this.options + .getOpenTelemetryTracer() + .spanBuilder("com.google.cloud.bigquery.BigQueryRpc.createTable") + .setSpanKind(SpanKind.CLIENT) + .setAttribute("bq.rpc.service", "TableService") + .setAttribute("bq.rpc.method", "InsertTable") + .setAttribute("bq.rpc.system", "http") + .setAllAttributes(otelAttributesFromOptions(options)) + .startSpan(); + } + Table tableResponse = bqCreateRequest.execute(); + if (createTable != null) { + createTable.setAttribute("bq.rpc.response.table.id", tableResponse.getId()); + createTable.end(); + } + return tableResponse; } @Override @@ -252,12 +352,38 @@ public Routine createSkipExceptionTranslation(Routine routine, Map op throws IOException { validateRPC(); RoutineReference reference = routine.getRoutineReference(); - return bigquery - .routines() - .insert(reference.getProjectId(), reference.getDatasetId(), routine) - .setPrettyPrint(false) - .setFields(Option.FIELDS.getString(options)) - .execute(); + Bigquery.Routines.Insert bqCreateRequest = + bigquery + .routines() + .insert(reference.getProjectId(), reference.getDatasetId(), routine) + .setPrettyPrint(false) + .setFields(Option.FIELDS.getString(options)); + + bqCreateRequest + .getRequestHeaders() + .set("x-goog-otel-enabled", this.options.isOpenTelemetryTracingEnabled()); + + Span createRoutine = null; + if (this.options.isOpenTelemetryTracingEnabled() + && this.options.getOpenTelemetryTracer() != null) { + createRoutine = + this.options + .getOpenTelemetryTracer() + .spanBuilder("com.google.cloud.bigquery.BigQueryRpc.createRoutine") + .setSpanKind(SpanKind.CLIENT) + .setAttribute("bq.rpc.service", "RoutineService") + .setAttribute("bq.rpc.method", "InsertRoutine") + .setAttribute("bq.rpc.system", "http") + .setAllAttributes(otelAttributesFromOptions(options)) + .startSpan(); + } + Routine routineResponse = bqCreateRequest.execute(); + if (createRoutine != null) { + createRoutine.setAttribute( + "bq.rpc.response.routine.id", routineResponse.getRoutineReference().getRoutineId()); + createRoutine.end(); + } + return routineResponse; } @Override @@ -276,12 +402,39 @@ public Job createSkipExceptionTranslation(Job job, Map options) throw job.getJobReference() != null ? job.getJobReference().getProjectId() : this.options.getProjectId(); - return bigquery - .jobs() - .insert(projectId, job) - .setPrettyPrint(false) - .setFields(Option.FIELDS.getString(options)) - .execute(); + Bigquery.Jobs.Insert bqCreateRequest = + bigquery + .jobs() + .insert(projectId, job) + .setPrettyPrint(false) + .setFields(Option.FIELDS.getString(options)); + + bqCreateRequest + .getRequestHeaders() + .set("x-goog-otel-enabled", this.options.isOpenTelemetryTracingEnabled()); + + Span createJob = null; + if (this.options.isOpenTelemetryTracingEnabled() + && this.options.getOpenTelemetryTracer() != null) { + createJob = + this.options + .getOpenTelemetryTracer() + .spanBuilder("com.google.cloud.bigquery.BigQueryRpc.createJob") + .setSpanKind(SpanKind.CLIENT) + .setAttribute("bq.rpc.service", "JobService") + .setAttribute("bq.rpc.method", "InsertJob") + .setAttribute("bq.rpc.system", "http") + .setAllAttributes(otelAttributesFromOptions(options)) + .startSpan(); + } + Job jobResponse = bqCreateRequest.execute(); + if (createJob != null) { + createJob.setAttribute("bq.rpc.response.job.id", jobResponse.getId()); + createJob.setAttribute( + "bq.rpc.response.job.status.state", jobResponse.getStatus().getState()); + createJob.end(); + } + return jobResponse; } @Override @@ -300,7 +453,34 @@ public Job createJobForQuerySkipExceptionTranslation(Job job) throws IOException job.getJobReference() != null ? job.getJobReference().getProjectId() : this.options.getProjectId(); - return bigquery.jobs().insert(projectId, job).setPrettyPrint(false).execute(); + Bigquery.Jobs.Insert bqCreateRequest = + bigquery.jobs().insert(projectId, job).setPrettyPrint(false); + + bqCreateRequest + .getRequestHeaders() + .set("x-goog-otel-enabled", this.options.isOpenTelemetryTracingEnabled()); + + Span createJob = null; + if (this.options.isOpenTelemetryTracingEnabled() + && this.options.getOpenTelemetryTracer() != null) { + createJob = + this.options + .getOpenTelemetryTracer() + .spanBuilder("com.google.cloud.bigquery.BigQueryRpc.createJobForQuery") + .setSpanKind(SpanKind.CLIENT) + .setAttribute("bq.rpc.service", "JobService") + .setAttribute("bq.rpc.method", "InsertJob") + .setAttribute("bq.rpc.system", "http") + .startSpan(); + } + Job jobResponse = bqCreateRequest.execute(); + if (createJob != null) { + createJob.setAttribute("bq.rpc.response.job.id", jobResponse.getId()); + createJob.setAttribute( + "bq.rpc.response.job.status.state", jobResponse.getStatus().getState()); + createJob.end(); + } + return jobResponse; } @Override @@ -320,12 +500,35 @@ public boolean deleteDataset(String projectId, String datasetId, Map public boolean deleteDatasetSkipExceptionTranslation( String projectId, String datasetId, Map options) throws IOException { validateRPC(); - bigquery - .datasets() - .delete(projectId, datasetId) - .setPrettyPrint(false) - .setDeleteContents(Option.DELETE_CONTENTS.getBoolean(options)) - .execute(); + Bigquery.Datasets.Delete bqDeleteRequest = + bigquery + .datasets() + .delete(projectId, datasetId) + .setPrettyPrint(false) + .setDeleteContents(Option.DELETE_CONTENTS.getBoolean(options)); + + bqDeleteRequest + .getRequestHeaders() + .set("x-goog-otel-enabled", this.options.isOpenTelemetryTracingEnabled()); + + Span deleteDataset = null; + if (this.options.isOpenTelemetryTracingEnabled() + && this.options.getOpenTelemetryTracer() != null) { + deleteDataset = + this.options + .getOpenTelemetryTracer() + .spanBuilder("com.google.cloud.bigquery.BigQueryRpc.deleteDataset") + .setSpanKind(SpanKind.CLIENT) + .setAttribute("bq.rpc.service", "DatasetService") + .setAttribute("bq.rpc.method", "DeleteDataset") + .setAttribute("bq.rpc.system", "http") + .setAllAttributes(otelAttributesFromOptions(options)) + .startSpan(); + } + bqDeleteRequest.execute(); + if (deleteDataset != null) { + deleteDataset.end(); + } return true; } @@ -355,7 +558,30 @@ public Dataset patchSkipExceptionTranslation(Dataset dataset, Map opt if (options.containsKey(Option.DATASET_UPDATE_MODE)) { bqPatchRequest.setUpdateMode(options.get(Option.DATASET_UPDATE_MODE).toString()); } - return bqPatchRequest.execute(); + bqPatchRequest + .getRequestHeaders() + .set("x-goog-otel-enabled", this.options.isOpenTelemetryTracingEnabled()); + + Span patchDataset = null; + if (this.options.isOpenTelemetryTracingEnabled() + && this.options.getOpenTelemetryTracer() != null) { + patchDataset = + this.options + .getOpenTelemetryTracer() + .spanBuilder("com.google.cloud.bigquery.BigQueryRpc.patchDataset") + .setSpanKind(SpanKind.CLIENT) + .setAttribute("bq.rpc.service", "DatasetService") + .setAttribute("bq.rpc.method", "PatchDataset") + .setAttribute("bq.rpc.system", "http") + .setAllAttributes(otelAttributesFromOptions(options)) + .startSpan(); + } + Dataset datasetResponse = bqPatchRequest.execute(); + if (patchDataset != null) { + patchDataset.setAttribute("bq.rpc.response.dataset.id", datasetResponse.getId()); + patchDataset.end(); + } + return datasetResponse; } @Override @@ -374,13 +600,39 @@ public Table patchSkipExceptionTranslation(Table table, Map options) // unset the type, as it is output only table.setType(null); TableReference reference = table.getTableReference(); - return bigquery - .tables() - .patch(reference.getProjectId(), reference.getDatasetId(), reference.getTableId(), table) - .setPrettyPrint(false) - .setFields(Option.FIELDS.getString(options)) - .setAutodetectSchema(BigQueryRpc.Option.AUTODETECT_SCHEMA.getBoolean(options)) - .execute(); + Bigquery.Tables.Patch bqPatchRequest = + bigquery + .tables() + .patch( + reference.getProjectId(), reference.getDatasetId(), reference.getTableId(), table) + .setPrettyPrint(false) + .setFields(Option.FIELDS.getString(options)) + .setAutodetectSchema(BigQueryRpc.Option.AUTODETECT_SCHEMA.getBoolean(options)); + + bqPatchRequest + .getRequestHeaders() + .set("x-goog-otel-enabled", this.options.isOpenTelemetryTracingEnabled()); + + Span patchTable = null; + if (this.options.isOpenTelemetryTracingEnabled() + && this.options.getOpenTelemetryTracer() != null) { + patchTable = + this.options + .getOpenTelemetryTracer() + .spanBuilder("com.google.cloud.bigquery.BigQueryRpc.patchTable") + .setSpanKind(SpanKind.CLIENT) + .setAttribute("bq.rpc.service", "TableService") + .setAttribute("bq.rpc.method", "PatchTable") + .setAttribute("bq.rpc.system", "http") + .setAllAttributes(otelAttributesFromOptions(options)) + .startSpan(); + } + Table tableResponse = bqPatchRequest.execute(); + if (patchTable != null) { + patchTable.setAttribute("bq.rpc.response.table.id", tableResponse.getId()); + patchTable.end(); + } + return tableResponse; } @Override @@ -402,13 +654,38 @@ public Table getTableSkipExceptionTranslation( String projectId, String datasetId, String tableId, Map options) throws IOException { validateRPC(); - return bigquery - .tables() - .get(projectId, datasetId, tableId) - .setPrettyPrint(false) - .setFields(Option.FIELDS.getString(options)) - .setView(getTableMetadataOption(options)) - .execute(); + Bigquery.Tables.Get bqGetRequest = + bigquery + .tables() + .get(projectId, datasetId, tableId) + .setPrettyPrint(false) + .setFields(Option.FIELDS.getString(options)) + .setView(getTableMetadataOption(options)); + + bqGetRequest + .getRequestHeaders() + .set("x-goog-otel-enabled", this.options.isOpenTelemetryTracingEnabled()); + + Span getTable = null; + if (this.options.isOpenTelemetryTracingEnabled() + && this.options.getOpenTelemetryTracer() != null) { + getTable = + this.options + .getOpenTelemetryTracer() + .spanBuilder("com.google.cloud.bigquery.BigQueryRpc.getTable") + .setSpanKind(SpanKind.CLIENT) + .setAttribute("bq.rpc.service", "TableService") + .setAttribute("bq.rpc.method", "GetTable") + .setAttribute("bq.rpc.system", "http") + .setAllAttributes(otelAttributesFromOptions(options)) + .startSpan(); + } + Table tableResponse = bqGetRequest.execute(); + if (getTable != null) { + getTable.setAttribute("bq.rpc.response.table.id", tableResponse.getId()); + getTable.end(); + } + return tableResponse; } private String getTableMetadataOption(Map options) { @@ -432,17 +709,42 @@ public Tuple> listTables( public Tuple> listTablesSkipExceptionTranslation( String projectId, String datasetId, Map options) throws IOException { validateRPC(); - TableList tableList = + Bigquery.Tables.List tableListRequest = bigquery .tables() .list(projectId, datasetId) .setPrettyPrint(false) .setMaxResults(Option.MAX_RESULTS.getLong(options)) - .setPageToken(Option.PAGE_TOKEN.getString(options)) - .execute(); - Iterable tables = tableList.getTables(); + .setPageToken(Option.PAGE_TOKEN.getString(options)); + + tableListRequest + .getRequestHeaders() + .set("x-goog-otel-enabled", this.options.isOpenTelemetryTracingEnabled()); + + Span listTables = null; + if (this.options.isOpenTelemetryTracingEnabled() + && this.options.getOpenTelemetryTracer() != null) { + listTables = + this.options + .getOpenTelemetryTracer() + .spanBuilder("com.google.cloud.bigquery.BigQueryRpc.listTables") + .setSpanKind(SpanKind.CLIENT) + .setAttribute("bq.rpc.service", "TableService") + .setAttribute("bq.rpc.method", "ListTables") + .setAttribute("bq.rpc.system", "http") + .setAttribute("bq.rpc.page_token", tableListRequest.getPageToken()) + .setAllAttributes(otelAttributesFromOptions(options)) + .startSpan(); + } + TableList tableResponse = tableListRequest.execute(); + if (listTables != null) { + listTables.setAttribute("bq.rpc.next_page_token", tableResponse.getNextPageToken()); + listTables.end(); + } + + Iterable tables = tableResponse.getTables(); return Tuple.of( - tableList.getNextPageToken(), + tableResponse.getNextPageToken(), Iterables.transform( tables != null ? tables : ImmutableList.of(), new Function() { @@ -480,7 +782,30 @@ public boolean deleteTable(String projectId, String datasetId, String tableId) { public boolean deleteTableSkipExceptionTranslation( String projectId, String datasetId, String tableId) throws IOException { validateRPC(); - bigquery.tables().delete(projectId, datasetId, tableId).execute(); + Bigquery.Tables.Delete bqDeleteRequest = + bigquery.tables().delete(projectId, datasetId, tableId); + + bqDeleteRequest + .getRequestHeaders() + .set("x-goog-otel-enabled", this.options.isOpenTelemetryTracingEnabled()); + + Span deleteTable = null; + if (this.options.isOpenTelemetryTracingEnabled() + && this.options.getOpenTelemetryTracer() != null) { + deleteTable = + this.options + .getOpenTelemetryTracer() + .spanBuilder("com.google.cloud.bigquery.BigQueryRpc.deleteTable") + .setSpanKind(SpanKind.CLIENT) + .setAttribute("bq.rpc.service", "TableService") + .setAttribute("bq.rpc.method", "DeleteTable") + .setAttribute("bq.rpc.system", "http") + .startSpan(); + } + bqDeleteRequest.execute(); + if (deleteTable != null) { + deleteTable.end(); + } return true; } @@ -499,12 +824,39 @@ public Model patchSkipExceptionTranslation(Model model, Map options) validateRPC(); // unset the type, as it is output only ModelReference reference = model.getModelReference(); - return bigquery - .models() - .patch(reference.getProjectId(), reference.getDatasetId(), reference.getModelId(), model) - .setPrettyPrint(false) - .setFields(Option.FIELDS.getString(options)) - .execute(); + Bigquery.Models.Patch bqPatchRequest = + bigquery + .models() + .patch( + reference.getProjectId(), reference.getDatasetId(), reference.getModelId(), model) + .setPrettyPrint(false) + .setFields(Option.FIELDS.getString(options)); + + bqPatchRequest + .getRequestHeaders() + .set("x-goog-otel-enabled", this.options.isOpenTelemetryTracingEnabled()); + + Span patchModel = null; + if (this.options.isOpenTelemetryTracingEnabled() + && this.options.getOpenTelemetryTracer() != null) { + patchModel = + this.options + .getOpenTelemetryTracer() + .spanBuilder("com.google.cloud.bigquery.BigQueryRpc.patchModel") + .setSpanKind(SpanKind.CLIENT) + .setAttribute("bq.rpc.service", "ModelService") + .setAttribute("bq.rpc.method", "PatchModel") + .setAttribute("bq.rpc.system", "http") + .setAllAttributes(otelAttributesFromOptions(options)) + .startSpan(); + } + Model modelResponse = bqPatchRequest.execute(); + if (patchModel != null) { + patchModel.setAttribute( + "bq.rpc.response.model.id", modelResponse.getModelReference().getModelId()); + patchModel.end(); + } + return modelResponse; } @Override @@ -526,12 +878,38 @@ public Model getModelSkipExceptionTranslation( String projectId, String datasetId, String modelId, Map options) throws IOException { validateRPC(); - return bigquery - .models() - .get(projectId, datasetId, modelId) - .setPrettyPrint(false) - .setFields(Option.FIELDS.getString(options)) - .execute(); + Bigquery.Models.Get bqGetRequest = + bigquery + .models() + .get(projectId, datasetId, modelId) + .setPrettyPrint(false) + .setFields(Option.FIELDS.getString(options)); + + bqGetRequest + .getRequestHeaders() + .set("x-goog-otel-enabled", this.options.isOpenTelemetryTracingEnabled()); + + Span getModel = null; + if (this.options.isOpenTelemetryTracingEnabled() + && this.options.getOpenTelemetryTracer() != null) { + getModel = + this.options + .getOpenTelemetryTracer() + .spanBuilder("com.google.cloud.bigquery.BigQueryRpc.getModel") + .setSpanKind(SpanKind.CLIENT) + .setAttribute("bq.rpc.service", "ModelService") + .setAttribute("bq.rpc.method", "GetModel") + .setAttribute("bq.rpc.system", "http") + .setAllAttributes(otelAttributesFromOptions(options)) + .startSpan(); + } + Model modelResponse = bqGetRequest.execute(); + if (getModel != null) { + getModel.setAttribute( + "bq.rpc.response.model.id", modelResponse.getModelReference().getModelId()); + getModel.end(); + } + return modelResponse; } @Override @@ -548,17 +926,42 @@ public Tuple> listModels( public Tuple> listModelsSkipExceptionTranslation( String projectId, String datasetId, Map options) throws IOException { validateRPC(); - ListModelsResponse modelList = + Bigquery.Models.List modelListRequest = bigquery .models() .list(projectId, datasetId) .setPrettyPrint(false) .setMaxResults(Option.MAX_RESULTS.getLong(options)) - .setPageToken(Option.PAGE_TOKEN.getString(options)) - .execute(); + .setPageToken(Option.PAGE_TOKEN.getString(options)); + + modelListRequest + .getRequestHeaders() + .set("x-goog-otel-enabled", this.options.isOpenTelemetryTracingEnabled()); + + Span listModels = null; + if (this.options.isOpenTelemetryTracingEnabled() + && this.options.getOpenTelemetryTracer() != null) { + listModels = + this.options + .getOpenTelemetryTracer() + .spanBuilder("com.google.cloud.bigquery.BigQueryRpc.listModels") + .setSpanKind(SpanKind.CLIENT) + .setAttribute("bq.rpc.service", "ModelService") + .setAttribute("bq.rpc.method", "ListModels") + .setAttribute("bq.rpc.system", "http") + .setAttribute("bq.rpc.page_token", modelListRequest.getPageToken()) + .setAllAttributes(otelAttributesFromOptions(options)) + .startSpan(); + } + ListModelsResponse modelResponse = modelListRequest.execute(); + if (listModels != null) { + listModels.setAttribute("bq.rpc.next_page_token", modelResponse.getNextPageToken()); + listModels.end(); + } + Iterable models = - modelList.getModels() != null ? modelList.getModels() : ImmutableList.of(); - return Tuple.of(modelList.getNextPageToken(), models); + modelResponse.getModels() != null ? modelResponse.getModels() : ImmutableList.of(); + return Tuple.of(modelResponse.getNextPageToken(), models); } @Override @@ -578,7 +981,30 @@ public boolean deleteModel(String projectId, String datasetId, String modelId) { public boolean deleteModelSkipExceptionTranslation( String projectId, String datasetId, String modelId) throws IOException { validateRPC(); - bigquery.models().delete(projectId, datasetId, modelId).execute(); + Bigquery.Models.Delete bqDeleteRequest = + bigquery.models().delete(projectId, datasetId, modelId); + + bqDeleteRequest + .getRequestHeaders() + .set("x-goog-otel-enabled", this.options.isOpenTelemetryTracingEnabled()); + + Span deleteModels = null; + if (this.options.isOpenTelemetryTracingEnabled() + && this.options.getOpenTelemetryTracer() != null) { + deleteModels = + this.options + .getOpenTelemetryTracer() + .spanBuilder("com.google.cloud.bigquery.BigQueryRpc.deleteModel") + .setSpanKind(SpanKind.CLIENT) + .setAttribute("bq.rpc.service", "ModelService") + .setAttribute("bq.rpc.method", "DeleteModel") + .setAttribute("bq.rpc.system", "http") + .startSpan(); + } + bqDeleteRequest.execute(); + if (deleteModels != null) { + deleteModels.end(); + } return true; } @@ -596,13 +1022,42 @@ public Routine updateSkipExceptionTranslation(Routine routine, Map op throws IOException { validateRPC(); RoutineReference reference = routine.getRoutineReference(); - return bigquery - .routines() - .update( - reference.getProjectId(), reference.getDatasetId(), reference.getRoutineId(), routine) - .setPrettyPrint(false) - .setFields(Option.FIELDS.getString(options)) - .execute(); + Bigquery.Routines.Update bqUpdateRequest = + bigquery + .routines() + .update( + reference.getProjectId(), + reference.getDatasetId(), + reference.getRoutineId(), + routine) + .setPrettyPrint(false) + .setFields(Option.FIELDS.getString(options)); + + bqUpdateRequest + .getRequestHeaders() + .set("x-goog-otel-enabled", this.options.isOpenTelemetryTracingEnabled()); + + Span updateRoutine = null; + if (this.options.isOpenTelemetryTracingEnabled() + && this.options.getOpenTelemetryTracer() != null) { + updateRoutine = + this.options + .getOpenTelemetryTracer() + .spanBuilder("com.google.cloud.bigquery.BigQueryRpc.updateRoutine") + .setSpanKind(SpanKind.CLIENT) + .setAttribute("bq.rpc.service", "RoutineService") + .setAttribute("bq.rpc.method", "UpdateRoutine") + .setAttribute("bq.rpc.system", "http") + .setAllAttributes(otelAttributesFromOptions(options)) + .startSpan(); + } + Routine routineResponse = bqUpdateRequest.execute(); + if (updateRoutine != null) { + updateRoutine.setAttribute( + "bq.rpc.response.routine.id", routineResponse.getRoutineReference().getRoutineId()); + updateRoutine.end(); + } + return routineResponse; } @Override @@ -624,12 +1079,38 @@ public Routine getRoutineSkipExceptionTranslation( String projectId, String datasetId, String routineId, Map options) throws IOException { validateRPC(); - return bigquery - .routines() - .get(projectId, datasetId, routineId) - .setPrettyPrint(false) - .setFields(Option.FIELDS.getString(options)) - .execute(); + Bigquery.Routines.Get bqGetRequest = + bigquery + .routines() + .get(projectId, datasetId, routineId) + .setPrettyPrint(false) + .setFields(Option.FIELDS.getString(options)); + + bqGetRequest + .getRequestHeaders() + .set("x-goog-otel-enabled", this.options.isOpenTelemetryTracingEnabled()); + + Span getRoutine = null; + if (this.options.isOpenTelemetryTracingEnabled() + && this.options.getOpenTelemetryTracer() != null) { + getRoutine = + this.options + .getOpenTelemetryTracer() + .spanBuilder("com.google.cloud.bigquery.BigQueryRpc.getRoutine") + .setSpanKind(SpanKind.CLIENT) + .setAttribute("bq.rpc.service", "RoutineService") + .setAttribute("bq.rpc.method", "GetRoutine") + .setAttribute("bq.rpc.system", "http") + .setAllAttributes(otelAttributesFromOptions(options)) + .startSpan(); + } + Routine routineResponse = bqGetRequest.execute(); + if (getRoutine != null) { + getRoutine.setAttribute( + "bq.rpc.response.routine.id", routineResponse.getRoutineReference().getRoutineId()); + getRoutine.end(); + } + return routineResponse; } @Override @@ -646,17 +1127,43 @@ public Tuple> listRoutines( public Tuple> listRoutinesSkipExceptionTranslation( String projectId, String datasetId, Map options) throws IOException { validateRPC(); - ListRoutinesResponse routineList = + Bigquery.Routines.List routineListRequest = bigquery .routines() .list(projectId, datasetId) .setPrettyPrint(false) .setMaxResults(Option.MAX_RESULTS.getLong(options)) - .setPageToken(Option.PAGE_TOKEN.getString(options)) - .execute(); + .setPageToken(Option.PAGE_TOKEN.getString(options)); + + routineListRequest + .getRequestHeaders() + .set("x-goog-otel-enabled", this.options.isOpenTelemetryTracingEnabled()); + + Span listRoutines = null; + if (this.options.isOpenTelemetryTracingEnabled() + && this.options.getOpenTelemetryTracer() != null) { + listRoutines = + this.options + .getOpenTelemetryTracer() + .spanBuilder("com.google.cloud.bigquery.BigQueryRpc.listRoutines") + .setSpanKind(SpanKind.CLIENT) + .setAttribute("bq.rpc.service", "RoutineService") + .setAttribute("bq.rpc.method", "ListRoutines") + .setAttribute("bq.rpc.system", "http") + .setAttribute("bq.rpc.page_token", routineListRequest.getPageToken()) + .setAllAttributes(otelAttributesFromOptions(options)) + .startSpan(); + } + ListRoutinesResponse routineResponse = routineListRequest.execute(); + if (listRoutines != null) { + listRoutines.setAttribute("bq.rpc.next_page_token", routineResponse.getNextPageToken()); + listRoutines.end(); + } Iterable routines = - routineList.getRoutines() != null ? routineList.getRoutines() : ImmutableList.of(); - return Tuple.of(routineList.getNextPageToken(), routines); + routineResponse.getRoutines() != null + ? routineResponse.getRoutines() + : ImmutableList.of(); + return Tuple.of(routineResponse.getNextPageToken(), routines); } @Override @@ -676,7 +1183,30 @@ public boolean deleteRoutine(String projectId, String datasetId, String routineI public boolean deleteRoutineSkipExceptionTranslation( String projectId, String datasetId, String routineId) throws IOException { validateRPC(); - bigquery.routines().delete(projectId, datasetId, routineId).execute(); + Bigquery.Routines.Delete bqDeleteRequest = + bigquery.routines().delete(projectId, datasetId, routineId); + + bqDeleteRequest + .getRequestHeaders() + .set("x-goog-otel-enabled", this.options.isOpenTelemetryTracingEnabled()); + + Span deleteRoutine = null; + if (this.options.isOpenTelemetryTracingEnabled() + && this.options.getOpenTelemetryTracer() != null) { + deleteRoutine = + this.options + .getOpenTelemetryTracer() + .spanBuilder("com.google.cloud.bigquery.BigQueryRpc.listRoutines") + .setSpanKind(SpanKind.CLIENT) + .setAttribute("bq.rpc.service", "RoutineService") + .setAttribute("bq.rpc.method", "ListRoutines") + .setAttribute("bq.rpc.system", "http") + .startSpan(); + } + bqDeleteRequest.execute(); + if (deleteRoutine != null) { + deleteRoutine.end(); + } return true; } @@ -695,11 +1225,34 @@ public TableDataInsertAllResponse insertAllSkipExceptionTranslation( String projectId, String datasetId, String tableId, TableDataInsertAllRequest request) throws IOException { validateRPC(); - return bigquery - .tabledata() - .insertAll(projectId, datasetId, tableId, request) - .setPrettyPrint(false) - .execute(); + Bigquery.Tabledata.InsertAll insertAllRequest = + bigquery + .tabledata() + .insertAll(projectId, datasetId, tableId, request) + .setPrettyPrint(false); + + insertAllRequest + .getRequestHeaders() + .set("x-goog-otel-enabled", this.options.isOpenTelemetryTracingEnabled()); + + Span insertAll = null; + if (this.options.isOpenTelemetryTracingEnabled() + && this.options.getOpenTelemetryTracer() != null) { + insertAll = + this.options + .getOpenTelemetryTracer() + .spanBuilder("com.google.cloud.bigquery.BigQueryRpc.insertAll") + .setSpanKind(SpanKind.CLIENT) + .setAttribute("bq.rpc.service", "TableDataService") + .setAttribute("bq.rpc.method", "InsertAll") + .setAttribute("bq.rpc.system", "http") + .startSpan(); + } + TableDataInsertAllResponse insertAllResponse = insertAllRequest.execute(); + if (insertAll != null) { + insertAll.end(); + } + return insertAllResponse; } @Override @@ -717,17 +1270,42 @@ public TableDataList listTableDataSkipExceptionTranslation( String projectId, String datasetId, String tableId, Map options) throws IOException { validateRPC(); - return bigquery - .tabledata() - .list(projectId, datasetId, tableId) - .setPrettyPrint(false) - .setMaxResults(Option.MAX_RESULTS.getLong(options)) - .setPageToken(Option.PAGE_TOKEN.getString(options)) - .setStartIndex( - Option.START_INDEX.getLong(options) != null - ? BigInteger.valueOf(Option.START_INDEX.getLong(options)) - : null) - .execute(); + Bigquery.Tabledata.List bqListRequest = + bigquery + .tabledata() + .list(projectId, datasetId, tableId) + .setPrettyPrint(false) + .setMaxResults(Option.MAX_RESULTS.getLong(options)) + .setPageToken(Option.PAGE_TOKEN.getString(options)) + .setStartIndex( + Option.START_INDEX.getLong(options) != null + ? BigInteger.valueOf(Option.START_INDEX.getLong(options)) + : null); + + bqListRequest + .getRequestHeaders() + .set("x-goog-otel-enabled", this.options.isOpenTelemetryTracingEnabled()); + + Span listTableData = null; + if (this.options.isOpenTelemetryTracingEnabled() + && this.options.getOpenTelemetryTracer() != null) { + listTableData = + this.options + .getOpenTelemetryTracer() + .spanBuilder("com.google.cloud.bigquery.BigQueryRpc.listTableData") + .setSpanKind(SpanKind.CLIENT) + .setAttribute("bq.rpc.service", "TableDataService") + .setAttribute("bq.rpc.method", "List") + .setAttribute("bq.rpc.system", "http") + .setAttribute("bq.rpc.page_token", bqListRequest.getPageToken()) + .setAllAttributes(otelAttributesFromOptions(options)) + .startSpan(); + } + TableDataList bqListResponse = bqListRequest.execute(); + if (listTableData != null) { + listTableData.end(); + } + return bqListResponse; } @Override @@ -754,13 +1332,37 @@ public TableDataList listTableDataWithRowLimitSkipExceptionTranslation( String pageToken) throws IOException { validateRPC(); - return bigquery - .tabledata() - .list(projectId, datasetId, tableId) - .setPrettyPrint(false) - .setMaxResults(Long.valueOf(maxResultPerPage)) - .setPageToken(pageToken) - .execute(); + Bigquery.Tabledata.List bqListRequest = + bigquery + .tabledata() + .list(projectId, datasetId, tableId) + .setPrettyPrint(false) + .setMaxResults(Long.valueOf(maxResultPerPage)) + .setPageToken(pageToken); + + bqListRequest + .getRequestHeaders() + .set("x-goog-otel-enabled", this.options.isOpenTelemetryTracingEnabled()); + + Span listTableData = null; + if (this.options.isOpenTelemetryTracingEnabled() + && this.options.getOpenTelemetryTracer() != null) { + listTableData = + this.options + .getOpenTelemetryTracer() + .spanBuilder("com.google.cloud.bigquery.BigQueryRpc.listTableDataWithRowLimit") + .setSpanKind(SpanKind.CLIENT) + .setAttribute("bq.rpc.service", "TableDataService") + .setAttribute("bq.rpc.method", "List") + .setAttribute("bq.rpc.system", "http") + .setAttribute("bq.rpc.page_token", bqListRequest.getPageToken()) + .startSpan(); + } + TableDataList bqListResponse = bqListRequest.execute(); + if (listTableData != null) { + listTableData.end(); + } + return bqListResponse; } @Override @@ -780,13 +1382,39 @@ public Job getJob(String projectId, String jobId, String location, Map options) throws IOException { validateRPC(); - return bigquery - .jobs() - .get(projectId, jobId) - .setPrettyPrint(false) - .setLocation(location) - .setFields(Option.FIELDS.getString(options)) - .execute(); + Bigquery.Jobs.Get bqGetRequest = + bigquery + .jobs() + .get(projectId, jobId) + .setPrettyPrint(false) + .setLocation(location) + .setFields(Option.FIELDS.getString(options)); + + bqGetRequest + .getRequestHeaders() + .set("x-goog-otel-enabled", this.options.isOpenTelemetryTracingEnabled()); + + Span getJob = null; + if (this.options.isOpenTelemetryTracingEnabled() + && this.options.getOpenTelemetryTracer() != null) { + getJob = + this.options + .getOpenTelemetryTracer() + .spanBuilder("com.google.cloud.bigquery.BigQueryRpc.getJob") + .setSpanKind(SpanKind.CLIENT) + .setAttribute("bq.rpc.service", "JobService") + .setAttribute("bq.rpc.method", "GetJob") + .setAttribute("bq.rpc.system", "http") + .setAllAttributes(otelAttributesFromOptions(options)) + .startSpan(); + } + Job jobResponse = bqGetRequest.execute(); + if (getJob != null) { + getJob.setAttribute("bq.rpc.response.job.id", jobResponse.getId()); + getJob.setAttribute("bq.rpc.response.job.status.state", jobResponse.getStatus().getState()); + getJob.end(); + } + return jobResponse; } @Override @@ -806,12 +1434,33 @@ public Job getQueryJob(String projectId, String jobId, String location) { public Job getQueryJobSkipExceptionTranslation(String projectId, String jobId, String location) throws IOException { validateRPC(); - return bigquery - .jobs() - .get(projectId, jobId) - .setPrettyPrint(false) - .setLocation(location) - .execute(); + Bigquery.Jobs.Get bqGetRequest = + bigquery.jobs().get(projectId, jobId).setPrettyPrint(false).setLocation(location); + + bqGetRequest + .getRequestHeaders() + .set("x-goog-otel-enabled", this.options.isOpenTelemetryTracingEnabled()); + + Span getJob = null; + if (this.options.isOpenTelemetryTracingEnabled() + && this.options.getOpenTelemetryTracer() != null) { + getJob = + this.options + .getOpenTelemetryTracer() + .spanBuilder("com.google.cloud.bigquery.BigQueryRpc.getQueryJob") + .setSpanKind(SpanKind.CLIENT) + .setAttribute("bq.rpc.service", "JobService") + .setAttribute("bq.rpc.method", "GetJob") + .setAttribute("bq.rpc.system", "http") + .startSpan(); + } + Job jobResponse = bqGetRequest.execute(); + if (getJob != null) { + getJob.setAttribute("bq.rpc.response.job.id", jobResponse.getId()); + getJob.setAttribute("bq.rpc.response.job.status.state", jobResponse.getStatus().getState()); + getJob.end(); + } + return jobResponse; } @Override @@ -827,7 +1476,7 @@ public Tuple> listJobs(String projectId, Map op public Tuple> listJobsSkipExceptionTranslation( String projectId, Map options) throws IOException { validateRPC(); - Bigquery.Jobs.List request = + Bigquery.Jobs.List listJobsRequest = bigquery .jobs() .list(projectId) @@ -840,12 +1489,37 @@ public Tuple> listJobsSkipExceptionTranslation( .setProjection(DEFAULT_PROJECTION) .setParentJobId(Option.PARENT_JOB_ID.getString(options)); if (Option.MIN_CREATION_TIME.getLong(options) != null) { - request.setMinCreationTime(BigInteger.valueOf(Option.MIN_CREATION_TIME.getLong(options))); + listJobsRequest.setMinCreationTime( + BigInteger.valueOf(Option.MIN_CREATION_TIME.getLong(options))); } if (Option.MAX_CREATION_TIME.getLong(options) != null) { - request.setMaxCreationTime(BigInteger.valueOf(Option.MAX_CREATION_TIME.getLong(options))); + listJobsRequest.setMaxCreationTime( + BigInteger.valueOf(Option.MAX_CREATION_TIME.getLong(options))); + } + listJobsRequest + .getRequestHeaders() + .set("x-goog-otel-enabled", this.options.isOpenTelemetryTracingEnabled()); + + Span listJobs = null; + if (this.options.isOpenTelemetryTracingEnabled() + && this.options.getOpenTelemetryTracer() != null) { + listJobs = + this.options + .getOpenTelemetryTracer() + .spanBuilder("com.google.cloud.bigquery.BigQueryRpc.listJobs") + .setSpanKind(SpanKind.CLIENT) + .setAttribute("bq.rpc.service", "JobService") + .setAttribute("bq.rpc.method", "ListJobs") + .setAttribute("bq.rpc.system", "http") + .setAttribute("bq.rpc.page_token", listJobsRequest.getPageToken()) + .setAllAttributes(otelAttributesFromOptions(options)) + .startSpan(); + } + JobList jobsList = listJobsRequest.execute(); + if (listJobs != null) { + listJobs.setAttribute("bq.rpc.next_page_token", jobsList.getNextPageToken()); + listJobs.end(); } - JobList jobsList = request.execute(); Iterable jobs = jobsList.getJobs(); return Tuple.of( @@ -892,7 +1566,30 @@ public boolean cancel(String projectId, String jobId, String location) { public boolean cancelSkipExceptionTranslation(String projectId, String jobId, String location) throws IOException { validateRPC(); - bigquery.jobs().cancel(projectId, jobId).setLocation(location).setPrettyPrint(false).execute(); + Bigquery.Jobs.Cancel bqCancelRequest = + bigquery.jobs().cancel(projectId, jobId).setLocation(location).setPrettyPrint(false); + + bqCancelRequest + .getRequestHeaders() + .set("x-goog-otel-enabled", this.options.isOpenTelemetryTracingEnabled()); + + Span cancelJob = null; + if (this.options.isOpenTelemetryTracingEnabled() + && this.options.getOpenTelemetryTracer() != null) { + cancelJob = + this.options + .getOpenTelemetryTracer() + .spanBuilder("com.google.cloud.bigquery.BigQueryRpc.cancelJob") + .setSpanKind(SpanKind.CLIENT) + .setAttribute("bq.rpc.service", "JobService") + .setAttribute("bq.rpc.method", "CancelJob") + .setAttribute("bq.rpc.system", "http") + .startSpan(); + } + bqCancelRequest.execute(); + if (cancelJob != null) { + cancelJob.end(); + } return true; } @@ -909,12 +1606,30 @@ public boolean deleteJob(String projectId, String jobName, String location) { public boolean deleteJobSkipExceptionTranslation( String projectId, String jobName, String location) throws IOException { validateRPC(); - bigquery - .jobs() - .delete(projectId, jobName) - .setLocation(location) - .setPrettyPrint(false) - .execute(); + Bigquery.Jobs.Delete bqDeleteRequest = + bigquery.jobs().delete(projectId, jobName).setLocation(location).setPrettyPrint(false); + + bqDeleteRequest + .getRequestHeaders() + .set("x-goog-otel-enabled", this.options.isOpenTelemetryTracingEnabled()); + + Span deleteJob = null; + if (this.options.isOpenTelemetryTracingEnabled() + && this.options.getOpenTelemetryTracer() != null) { + deleteJob = + this.options + .getOpenTelemetryTracer() + .spanBuilder("com.google.cloud.bigquery.BigQueryRpc.deleteJob") + .setSpanKind(SpanKind.CLIENT) + .setAttribute("bq.rpc.service", "JobService") + .setAttribute("bq.rpc.method", "DeleteJob") + .setAttribute("bq.rpc.system", "http") + .startSpan(); + } + bqDeleteRequest.execute(); + if (deleteJob != null) { + deleteJob.end(); + } return true; } @@ -932,19 +1647,45 @@ public GetQueryResultsResponse getQueryResults( public GetQueryResultsResponse getQueryResultsSkipExceptionTranslation( String projectId, String jobId, String location, Map options) throws IOException { validateRPC(); - return bigquery - .jobs() - .getQueryResults(projectId, jobId) - .setPrettyPrint(false) - .setLocation(location) - .setMaxResults(Option.MAX_RESULTS.getLong(options)) - .setPageToken(Option.PAGE_TOKEN.getString(options)) - .setStartIndex( - Option.START_INDEX.getLong(options) != null - ? BigInteger.valueOf(Option.START_INDEX.getLong(options)) - : null) - .setTimeoutMs(Option.TIMEOUT.getLong(options)) - .execute(); + Bigquery.Jobs.GetQueryResults queryRequest = + bigquery + .jobs() + .getQueryResults(projectId, jobId) + .setPrettyPrint(false) + .setLocation(location) + .setMaxResults(Option.MAX_RESULTS.getLong(options)) + .setPageToken(Option.PAGE_TOKEN.getString(options)) + .setStartIndex( + Option.START_INDEX.getLong(options) != null + ? BigInteger.valueOf(Option.START_INDEX.getLong(options)) + : null) + .setTimeoutMs(Option.TIMEOUT.getLong(options)); + + queryRequest + .getRequestHeaders() + .set("x-goog-otel-enabled", this.options.isOpenTelemetryTracingEnabled()); + + Span getQueryResults = null; + if (this.options.isOpenTelemetryTracingEnabled() + && this.options.getOpenTelemetryTracer() != null) { + getQueryResults = + this.options + .getOpenTelemetryTracer() + .spanBuilder("com.google.cloud.bigquery.BigQueryRpc.getQueryResults") + .setSpanKind(SpanKind.CLIENT) + .setAttribute("bq.rpc.service", "JobService") + .setAttribute("bq.rpc.method", "GetQueryResults") + .setAttribute("bq.rpc.system", "http") + .setAttribute("bq.rpc.page_token", queryRequest.getPageToken()) + .setAllAttributes(otelAttributesFromOptions(options)) + .startSpan(); + } + + GetQueryResultsResponse queryResponse = queryRequest.execute(); + if (getQueryResults != null) { + getQueryResults.end(); + } + return queryResponse; } @Override @@ -963,14 +1704,39 @@ public GetQueryResultsResponse getQueryResultsWithRowLimitSkipExceptionTranslati String projectId, String jobId, String location, Integer maxResultPerPage, Long timeoutMs) throws IOException { validateRPC(); - return bigquery - .jobs() - .getQueryResults(projectId, jobId) - .setPrettyPrint(false) - .setLocation(location) - .setMaxResults(Long.valueOf(maxResultPerPage)) - .setTimeoutMs(timeoutMs) - .execute(); + Bigquery.Jobs.GetQueryResults queryRequest = + bigquery + .jobs() + .getQueryResults(projectId, jobId) + .setPrettyPrint(false) + .setLocation(location) + .setMaxResults(Long.valueOf(maxResultPerPage)) + .setTimeoutMs(timeoutMs); + + queryRequest + .getRequestHeaders() + .set("x-goog-otel-enabled", this.options.isOpenTelemetryTracingEnabled()); + + Span getQueryResults = null; + if (this.options.isOpenTelemetryTracingEnabled() + && this.options.getOpenTelemetryTracer() != null) { + getQueryResults = + this.options + .getOpenTelemetryTracer() + .spanBuilder("com.google.cloud.bigquery.BigQueryRpc.getQueryResultsWithRowLimit") + .setSpanKind(SpanKind.CLIENT) + .setAttribute("bq.rpc.service", "JobService") + .setAttribute("bq.rpc.method", "GetQueryResults") + .setAttribute("bq.rpc.system", "http") + .setAttribute("bq.rpc.page_token", queryRequest.getPageToken()) + .startSpan(); + } + + GetQueryResultsResponse queryResponse = queryRequest.execute(); + if (getQueryResults != null) { + getQueryResults.end(); + } + return queryResponse; } @Override @@ -986,7 +1752,30 @@ public QueryResponse queryRpc(String projectId, QueryRequest content) { public QueryResponse queryRpcSkipExceptionTranslation(String projectId, QueryRequest content) throws IOException { validateRPC(); - return bigquery.jobs().query(projectId, content).execute(); + Bigquery.Jobs.Query queryRequest = bigquery.jobs().query(projectId, content); + queryRequest + .getRequestHeaders() + .set("x-goog-otel-enabled", this.options.isOpenTelemetryTracingEnabled()); + + Span getQueryResults = null; + if (this.options.isOpenTelemetryTracingEnabled() + && this.options.getOpenTelemetryTracer() != null) { + getQueryResults = + this.options + .getOpenTelemetryTracer() + .spanBuilder("com.google.cloud.bigquery.BigQueryRpc.queryRpc") + .setSpanKind(SpanKind.CLIENT) + .setAttribute("bq.rpc.service", "JobService") + .setAttribute("bq.rpc.method", "Query") + .setAttribute("bq.rpc.system", "http") + .startSpan(); + } + + QueryResponse queryResponse = queryRequest.execute(); + if (getQueryResults != null) { + getQueryResults.end(); + } + return queryResponse; } @Override @@ -1098,11 +1887,33 @@ public Policy getIamPolicySkipExceptionTranslation(String resourceId, Map @@ -71,7 +71,7 @@ com.google.cloud google-cloud-bigquerystorage-bom - 3.15.3 + 3.17.0 pom import @@ -79,7 +79,7 @@ com.google.cloud google-cloud-datacatalog-bom - 1.72.0 + 1.78.0 pom import @@ -93,7 +93,7 @@ com.google.cloud google-cloud-bigquery - 2.52.0 + 2.55.0 @@ -137,19 +137,19 @@ com.google.cloud google-cloud-storage - 2.53.1 + 2.53.3 test com.google.cloud google-cloud-bigqueryconnection - 2.68.0 + 2.74.0 test com.google.api.grpc proto-google-cloud-bigqueryconnection-v1 - 2.68.0 + 2.70.0 test diff --git a/samples/install-without-bom/pom.xml b/samples/install-without-bom/pom.xml index 4089821fe8..cfcf9c503f 100644 --- a/samples/install-without-bom/pom.xml +++ b/samples/install-without-bom/pom.xml @@ -37,6 +37,7 @@ 1.8 1.8 UTF-8 + 1.52.0 @@ -45,7 +46,7 @@ com.google.cloud google-cloud-bigquery - 2.51.0 + 2.53.0 @@ -59,17 +60,48 @@ google-oauth-client-jetty 1.39.0 + + io.opentelemetry + opentelemetry-api + ${opentelemetry.version} + + + io.opentelemetry + opentelemetry-context + ${opentelemetry.version} + + + io.opentelemetry + opentelemetry-sdk + ${opentelemetry.version} + + + io.opentelemetry + opentelemetry-sdk-common + ${opentelemetry.version} + + + io.opentelemetry + opentelemetry-sdk-trace + ${opentelemetry.version} + + + io.opentelemetry + opentelemetry-exporter-logging + ${opentelemetry.version} + + com.google.cloud google-cloud-bigtable - 2.60.0 + 2.62.0 test com.google.cloud google-cloud-bigqueryconnection - 2.68.0 + 2.74.0 test diff --git a/samples/snapshot/pom.xml b/samples/snapshot/pom.xml index 1a16552343..c0e58826be 100644 --- a/samples/snapshot/pom.xml +++ b/samples/snapshot/pom.xml @@ -39,12 +39,24 @@ UTF-8 + + + + io.opentelemetry + opentelemetry-bom + 1.52.0 + pom + import + + + + com.google.cloud google-cloud-bigquery - 2.52.0 + 2.55.0 @@ -61,13 +73,13 @@ com.google.cloud google-cloud-bigtable - 2.60.0 + 2.62.0 test com.google.cloud google-cloud-bigqueryconnection - 2.68.0 + 2.74.0 test @@ -82,6 +94,30 @@ 1.4.4 test + + io.opentelemetry + opentelemetry-api + + + io.opentelemetry + opentelemetry-context + + + io.opentelemetry + opentelemetry-sdk + + + io.opentelemetry + opentelemetry-sdk-common + + + io.opentelemetry + opentelemetry-sdk-trace + + + io.opentelemetry + opentelemetry-exporter-logging + diff --git a/samples/snippets/pom.xml b/samples/snippets/pom.xml index 160e38cb02..d6cbcca5d1 100644 --- a/samples/snippets/pom.xml +++ b/samples/snippets/pom.xml @@ -47,7 +47,14 @@ com.google.cloud libraries-bom - 26.62.0 + 26.64.0 + pom + import + + + io.opentelemetry + opentelemetry-bom + 1.52.0 pom import @@ -59,6 +66,30 @@ com.google.cloud google-cloud-bigquery + + io.opentelemetry + opentelemetry-api + + + io.opentelemetry + opentelemetry-context + + + io.opentelemetry + opentelemetry-sdk + + + io.opentelemetry + opentelemetry-sdk-common + + + io.opentelemetry + opentelemetry-sdk-trace + + + io.opentelemetry + opentelemetry-exporter-logging + @@ -79,13 +110,13 @@ com.google.cloud google-cloud-bigtable - 2.60.0 + 2.62.0 test com.google.cloud google-cloud-bigqueryconnection - 2.68.0 + 2.74.0 test diff --git a/samples/snippets/src/main/java/com/example/bigquery/EnableOpenTelemetryTracing.java b/samples/snippets/src/main/java/com/example/bigquery/EnableOpenTelemetryTracing.java new file mode 100644 index 0000000000..57ec7eb71d --- /dev/null +++ b/samples/snippets/src/main/java/com/example/bigquery/EnableOpenTelemetryTracing.java @@ -0,0 +1,85 @@ +/* + * Copyright 2025 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.example.bigquery; + +// [START bigquery_enable_otel_tracing] +import com.google.cloud.bigquery.BigQuery; +import com.google.cloud.bigquery.BigQueryOptions; +import com.google.cloud.bigquery.Dataset; +import com.google.cloud.bigquery.DatasetInfo; +import io.opentelemetry.api.OpenTelemetry; +import io.opentelemetry.api.trace.Tracer; +import io.opentelemetry.exporter.logging.LoggingSpanExporter; +import io.opentelemetry.sdk.OpenTelemetrySdk; +import io.opentelemetry.sdk.trace.SdkTracerProvider; +import io.opentelemetry.sdk.trace.export.SimpleSpanProcessor; +import io.opentelemetry.sdk.trace.samplers.Sampler; +import java.util.logging.ConsoleHandler; +import java.util.logging.Logger; + +public class EnableOpenTelemetryTracing { + private static final Logger log = Logger.getLogger(EnableOpenTelemetryTracing.class.getName()); + + public static void main(String[] args) { + // Set logging to System.err. + ConsoleHandler ch = new ConsoleHandler(); + log.addHandler(ch); + + // TODO(developer): Replace values before running the sample. + final String tracerName = "Sample Tracer"; + final String datasetId = "sampleDatasetId"; + + // Create TracerProvider that exports to a logger. + SdkTracerProvider tracerProvider = + SdkTracerProvider.builder() + .addSpanProcessor(SimpleSpanProcessor.builder(LoggingSpanExporter.create()).build()) + .setSampler(Sampler.alwaysOn()) + .build(); + + // Create global OpenTelemetry instance using the TracerProvider. + OpenTelemetry otel = OpenTelemetrySdk.builder().setTracerProvider(tracerProvider).build(); + + // Create Tracer instance from the OpenTelemetry object. Tracers are used to create + // Spans. There can be multiple Tracers in an OpenTelemetry instance. + Tracer tracer = otel.getTracer(tracerName); + + enableOpenTelemetry(tracer, datasetId); + } + + public static void enableOpenTelemetry(Tracer tracer, String datasetId) { + // Create BigQuery client to trace. EnableOpenTelemetryTracing and OpenTelemetryTracer must + // be set to enable tracing. + BigQueryOptions otelOptions = + BigQueryOptions.newBuilder() + .setEnableOpenTelemetryTracing(true) + .setOpenTelemetryTracer(tracer) + .build(); + BigQuery bigquery = otelOptions.getService(); + + try { + // Create dataset. + DatasetInfo info = DatasetInfo.newBuilder(datasetId).build(); + Dataset dataset = bigquery.create(info); + } catch (Exception e) { + System.out.println( + String.format("Failed to create dataset: %s: %s", e.toString(), e.getMessage())); + } finally { + bigquery.delete(datasetId); + } + } +} +// [END bigquery_enable_otel_tracing] diff --git a/samples/snippets/src/main/java/com/example/bigquery/EnableOpenTelemetryTracingWithParentSpan.java b/samples/snippets/src/main/java/com/example/bigquery/EnableOpenTelemetryTracingWithParentSpan.java new file mode 100644 index 0000000000..af69df10ba --- /dev/null +++ b/samples/snippets/src/main/java/com/example/bigquery/EnableOpenTelemetryTracingWithParentSpan.java @@ -0,0 +1,105 @@ +/* + * Copyright 2025 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.example.bigquery; + +// [START bigquery_enable_otel_tracing_with_parent_span] +import com.google.cloud.bigquery.BigQuery; +import com.google.cloud.bigquery.BigQueryOptions; +import com.google.cloud.bigquery.Dataset; +import com.google.cloud.bigquery.DatasetInfo; +import io.opentelemetry.api.OpenTelemetry; +import io.opentelemetry.api.trace.Span; +import io.opentelemetry.api.trace.Tracer; +import io.opentelemetry.context.Scope; +import io.opentelemetry.exporter.logging.LoggingSpanExporter; +import io.opentelemetry.sdk.OpenTelemetrySdk; +import io.opentelemetry.sdk.trace.SdkTracerProvider; +import io.opentelemetry.sdk.trace.export.SimpleSpanProcessor; +import io.opentelemetry.sdk.trace.samplers.Sampler; +import java.time.LocalDate; +import java.util.logging.ConsoleHandler; +import java.util.logging.Logger; + +public class EnableOpenTelemetryTracingWithParentSpan { + private static final Logger log = + Logger.getLogger(EnableOpenTelemetryTracingWithParentSpan.class.getName()); + + public static void main(String[] args) { + // Set logging to System.err. + ConsoleHandler ch = new ConsoleHandler(); + log.addHandler(ch); + + // TODO(developer): Replace values before running the sample. + final String tracerName = "Sample Tracer"; + final String parentSpanName = "Sample Parent Span"; + final String datasetId = "sampleDatasetId"; + + // Create TracerProvider that exports to a logger. + SdkTracerProvider tracerProvider = + SdkTracerProvider.builder() + .addSpanProcessor(SimpleSpanProcessor.builder(LoggingSpanExporter.create()).build()) + .setSampler(Sampler.alwaysOn()) + .build(); + + // Create OpenTelemetry instance using the TracerProvider. + OpenTelemetry otel = OpenTelemetrySdk.builder().setTracerProvider(tracerProvider).build(); + + // Create Tracer instance from the global OpenTelemetry object. Tracers are used to create + // Spans. There can be multiple Tracers in a global OpenTelemetry instance. + final Tracer tracer = otel.getTracer(tracerName); + enableOpenTelemetryWithParentSpan(tracer, parentSpanName, datasetId); + } + + public static void enableOpenTelemetryWithParentSpan( + Tracer tracer, String parentSpanName, String datasetId) { + // Create BigQuery client to trace. EnableOpenTelemetryTracing and OpenTelemetryTracer must + // be set to enable tracing. + BigQueryOptions otelOptions = + BigQueryOptions.newBuilder() + .setEnableOpenTelemetryTracing(true) + .setOpenTelemetryTracer(tracer) + .build(); + BigQuery bigquery = otelOptions.getService(); + + LocalDate currentDate = LocalDate.now(); + + // Create the root parent Span. setNoParent() ensures that it is a parent Span with a Span ID + // of 0. + Span parentSpan = + tracer + .spanBuilder(parentSpanName) + .setNoParent() + .setAttribute("current_date", currentDate.toString()) + .startSpan(); + + // The Span Context is automatically passed on to any functions called within the scope of the + // try block. parentSpan.makeCurrent() sets parentSpan to be the parent of any Spans created in + // this scope, or the scope of any functions called within this scope. + try (Scope parentScope = parentSpan.makeCurrent()) { + DatasetInfo info = DatasetInfo.newBuilder(datasetId).build(); + Dataset dataset = bigquery.create(info); + } catch (Exception e) { + System.out.println( + String.format("Failed to create dataset: %s: %s", e.toString(), e.getMessage())); + } finally { + // finally block ensures that Spans are cleaned up properly. + parentSpan.end(); + bigquery.delete(datasetId); + } + } +} +// [END bigquery_enable_otel_tracing_with_parent_span] diff --git a/samples/snippets/src/test/java/com/example/bigquery/EnableOpenTelemetryTracingIT.java b/samples/snippets/src/test/java/com/example/bigquery/EnableOpenTelemetryTracingIT.java new file mode 100644 index 0000000000..0ad5651018 --- /dev/null +++ b/samples/snippets/src/test/java/com/example/bigquery/EnableOpenTelemetryTracingIT.java @@ -0,0 +1,105 @@ +/* + * Copyright 2025 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.example.bigquery; + +import static com.google.common.truth.Truth.assertThat; + +import com.google.cloud.bigquery.testing.RemoteBigQueryHelper; +import io.opentelemetry.api.OpenTelemetry; +import io.opentelemetry.api.trace.Tracer; +import io.opentelemetry.sdk.OpenTelemetrySdk; +import io.opentelemetry.sdk.common.CompletableResultCode; +import io.opentelemetry.sdk.trace.SdkTracerProvider; +import io.opentelemetry.sdk.trace.data.SpanData; +import io.opentelemetry.sdk.trace.export.SimpleSpanProcessor; +import io.opentelemetry.sdk.trace.samplers.Sampler; +import java.io.ByteArrayOutputStream; +import java.io.PrintStream; +import java.util.Collection; +import java.util.logging.Level; +import java.util.logging.Logger; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; + +public class EnableOpenTelemetryTracingIT { + private final Logger log = Logger.getLogger(this.getClass().getName()); + private ByteArrayOutputStream bout; + private PrintStream out; + private PrintStream originalPrintStream; + + private static class ConsoleSpanExporter + implements io.opentelemetry.sdk.trace.export.SpanExporter { + @Override + public CompletableResultCode export(Collection collection) { + if (collection.isEmpty()) { + return CompletableResultCode.ofFailure(); + } + for (SpanData data : collection) { + System.out.println(data); + } + return CompletableResultCode.ofSuccess(); + } + + @Override + public CompletableResultCode flush() { + return CompletableResultCode.ofSuccess(); + } + + @Override + public CompletableResultCode shutdown() { + return CompletableResultCode.ofSuccess(); + } + } + + @Before + public void setUp() { + bout = new ByteArrayOutputStream(); + out = new PrintStream(bout); + originalPrintStream = System.out; + System.setOut(out); + } + + @After + public void tearDown() { + // restores print statements in the original method + System.out.flush(); + System.setOut(originalPrintStream); + log.log(Level.INFO, "\n" + bout.toString()); + } + + @Test + public void testEnableOpenTelemetryTracing() { + final String tracerName = "testSampleTracer"; + final String datasetId = RemoteBigQueryHelper.generateDatasetName(); + + SdkTracerProvider tracerProvider = + SdkTracerProvider.builder() + .addSpanProcessor(SimpleSpanProcessor.builder(new ConsoleSpanExporter()).build()) + .setSampler(Sampler.alwaysOn()) + .build(); + + OpenTelemetry otel = OpenTelemetrySdk.builder().setTracerProvider(tracerProvider).build(); + + final Tracer tracer = otel.getTracer(tracerName); + + EnableOpenTelemetryTracing.enableOpenTelemetry(tracer, datasetId); + + assertThat(bout.toString()).contains("com.google.cloud.bigquery.BigQuery.createDataset"); + assertThat(bout.toString()).contains("com.google.cloud.bigquery.BigQuery.deleteDataset"); + } +} diff --git a/samples/snippets/src/test/java/com/example/bigquery/EnableOpenTelemetryTracingWithParentSpanIT.java b/samples/snippets/src/test/java/com/example/bigquery/EnableOpenTelemetryTracingWithParentSpanIT.java new file mode 100644 index 0000000000..482915008b --- /dev/null +++ b/samples/snippets/src/test/java/com/example/bigquery/EnableOpenTelemetryTracingWithParentSpanIT.java @@ -0,0 +1,110 @@ +/* + * Copyright 2025 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.example.bigquery; + +import static com.google.common.truth.Truth.assertThat; + +import com.google.cloud.bigquery.testing.RemoteBigQueryHelper; +import io.opentelemetry.api.OpenTelemetry; +import io.opentelemetry.api.trace.Tracer; +import io.opentelemetry.sdk.OpenTelemetrySdk; +import io.opentelemetry.sdk.common.CompletableResultCode; +import io.opentelemetry.sdk.trace.SdkTracerProvider; +import io.opentelemetry.sdk.trace.data.SpanData; +import io.opentelemetry.sdk.trace.export.SimpleSpanProcessor; +import io.opentelemetry.sdk.trace.samplers.Sampler; +import java.io.ByteArrayOutputStream; +import java.io.PrintStream; +import java.time.LocalDate; +import java.util.Collection; +import java.util.logging.Level; +import java.util.logging.Logger; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; + +public class EnableOpenTelemetryTracingWithParentSpanIT { + private final Logger log = Logger.getLogger(this.getClass().getName()); + private ByteArrayOutputStream bout; + private PrintStream out; + private PrintStream originalPrintStream; + + private static class ConsoleSpanExporter + implements io.opentelemetry.sdk.trace.export.SpanExporter { + @Override + public CompletableResultCode export(Collection collection) { + if (collection.isEmpty()) { + return CompletableResultCode.ofFailure(); + } + for (SpanData data : collection) { + System.out.println(data); + } + return CompletableResultCode.ofSuccess(); + } + + @Override + public CompletableResultCode flush() { + return CompletableResultCode.ofSuccess(); + } + + @Override + public CompletableResultCode shutdown() { + return CompletableResultCode.ofSuccess(); + } + } + + @Before + public void setUp() { + bout = new ByteArrayOutputStream(); + out = new PrintStream(bout); + originalPrintStream = System.out; + System.setOut(out); + } + + @After + public void tearDown() { + // restores print statements in the original method + System.out.flush(); + System.setOut(originalPrintStream); + log.log(Level.INFO, "\n" + bout.toString()); + } + + @Test + public void testEnableOpenTelemetryWithParentSpan() { + final String tracerName = "testSampleTracer"; + final String parentSpanName = "testSampleParentSpan"; + final String datasetId = RemoteBigQueryHelper.generateDatasetName(); + final LocalDate currentDate = LocalDate.now(); + + SdkTracerProvider tracerProvider = + SdkTracerProvider.builder() + .addSpanProcessor(SimpleSpanProcessor.builder(new ConsoleSpanExporter()).build()) + .setSampler(Sampler.alwaysOn()) + .build(); + + OpenTelemetry otel = OpenTelemetrySdk.builder().setTracerProvider(tracerProvider).build(); + + final Tracer tracer = otel.getTracer(tracerName); + + EnableOpenTelemetryTracingWithParentSpan.enableOpenTelemetryWithParentSpan( + tracer, parentSpanName, datasetId); + + assertThat(bout.toString()).contains(parentSpanName); + assertThat(bout.toString()) + .contains(String.format("AttributesMap{data={current_date=%s}", currentDate.toString())); + } +} diff --git a/versions.txt b/versions.txt index 2b59228747..73eeb870a4 100644 --- a/versions.txt +++ b/versions.txt @@ -1,4 +1,4 @@ # Format: # module:released-version:current-version -google-cloud-bigquery:2.52.0:2.52.0 \ No newline at end of file +google-cloud-bigquery:2.55.0:2.55.0 \ No newline at end of file