Skip to content

Commit e81515d

Browse files
committed
chore(bigquery): add span tracing integration test
1 parent 39133b5 commit e81515d

3 files changed

Lines changed: 231 additions & 3 deletions

File tree

java-bigquery/google-cloud-bigquery/src/main/java/com/google/cloud/bigquery/telemetry/ErrorTypeUtil.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,9 +23,9 @@
2323
* https://github.com/googleapis/google-cloud-java/issues/12105
2424
*/
2525
@BetaApi
26-
class ErrorTypeUtil {
26+
public class ErrorTypeUtil {
2727

28-
enum ErrorType {
28+
public enum ErrorType {
2929
CLIENT_TIMEOUT,
3030
CLIENT_CONNECTION_ERROR,
3131
CLIENT_REQUEST_ERROR,

java-bigquery/google-cloud-bigquery/src/main/java/com/google/cloud/bigquery/telemetry/HttpTracingRequestInitializer.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,7 @@ public void initialize(HttpRequest request) throws IOException {
7474
// Get the current active span (created by HttpBigQueryRpc) and add HTTP attributes to it
7575
Span span = Span.current();
7676
if (!span.getSpanContext().isValid()) {
77-
// No active span to exists, skip instrumentation
77+
// No active span exists, skip instrumentation
7878
return;
7979
}
8080
addInitialHttpAttributesToSpan(span, request);
Lines changed: 228 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,228 @@
1+
/*
2+
* Copyright 2026 Google LLC
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package com.google.cloud.bigquery.it;
17+
18+
import static com.google.cloud.bigquery.telemetry.ErrorTypeUtil.ErrorType;
19+
import static org.junit.jupiter.api.Assertions.assertEquals;
20+
import static org.junit.jupiter.api.Assertions.assertNotNull;
21+
import static org.junit.jupiter.api.Assertions.assertTrue;
22+
import static org.junit.jupiter.api.Assertions.fail;
23+
24+
import com.google.cloud.bigquery.BigQuery;
25+
import com.google.cloud.bigquery.BigQueryException;
26+
import com.google.cloud.bigquery.telemetry.BigQueryTelemetryTracer;
27+
import com.google.cloud.bigquery.telemetry.HttpTracingRequestInitializer;
28+
import com.google.cloud.bigquery.testing.RemoteBigQueryHelper;
29+
import io.opentelemetry.api.OpenTelemetry;
30+
import io.opentelemetry.api.common.AttributeKey;
31+
import io.opentelemetry.api.trace.Tracer;
32+
import io.opentelemetry.sdk.OpenTelemetrySdk;
33+
import io.opentelemetry.sdk.testing.exporter.InMemorySpanExporter;
34+
import io.opentelemetry.sdk.trace.SdkTracerProvider;
35+
import io.opentelemetry.sdk.trace.data.SpanData;
36+
import io.opentelemetry.sdk.trace.export.SimpleSpanProcessor;
37+
import java.io.IOException;
38+
import java.util.List;
39+
import java.util.Map;
40+
import org.junit.jupiter.api.BeforeAll;
41+
import org.junit.jupiter.api.BeforeEach;
42+
import org.junit.jupiter.api.Test;
43+
44+
public class ITOpenTelemetryTest {
45+
46+
private static BigQuery bigquery;
47+
private static RemoteBigQueryHelper bigqueryHelper;
48+
private InMemorySpanExporter memoryExporter;
49+
private OpenTelemetry openTelemetry;
50+
private Tracer tracer;
51+
52+
@BeforeAll
53+
public static void setUpClass() throws IOException {
54+
System.setProperty("com.google.cloud.bigquery.http.tracing.dev.enabled", "true");
55+
bigqueryHelper = RemoteBigQueryHelper.create();
56+
bigquery = bigqueryHelper.getOptions().getService();
57+
}
58+
59+
@BeforeEach
60+
public void setUp() {
61+
memoryExporter = InMemorySpanExporter.create();
62+
SdkTracerProvider tracerProvider =
63+
SdkTracerProvider.builder()
64+
.addSpanProcessor(SimpleSpanProcessor.create(memoryExporter))
65+
.build();
66+
openTelemetry = OpenTelemetrySdk.builder().setTracerProvider(tracerProvider).build();
67+
tracer = openTelemetry.getTracer("it-otel-test");
68+
}
69+
70+
@Test
71+
public void testListDatasetsTraced() {
72+
BigQuery bq =
73+
bigqueryHelper.getOptions().toBuilder()
74+
.setEnableOpenTelemetryTracing(true)
75+
.setOpenTelemetryTracer(tracer)
76+
.build()
77+
.getService();
78+
79+
bq.listDatasets();
80+
81+
List<SpanData> spans = memoryExporter.getFinishedSpanItems();
82+
assertNotNull(spans);
83+
assertTrue(spans.size() > 0, "Expected at least one span collected");
84+
85+
boolean foundRpcSpan = false;
86+
for (SpanData span : spans) {
87+
if (span.getName().equals("com.google.cloud.bigquery.BigQueryRpc.listDatasets")) {
88+
foundRpcSpan = true;
89+
Map<AttributeKey<?>, Object> attrs = span.getAttributes().asMap();
90+
91+
assertEquals("GET", attrs.get(HttpTracingRequestInitializer.HTTP_REQUEST_METHOD));
92+
assertEquals("DatasetService", attrs.get(AttributeKey.stringKey("bq.rpc.service")));
93+
assertEquals("ListDatasets", attrs.get(AttributeKey.stringKey("bq.rpc.method")));
94+
assertEquals("bigquery.googleapis.com", attrs.get(BigQueryTelemetryTracer.SERVER_ADDRESS));
95+
checkGeneralAttributes(attrs);
96+
97+
assertEquals(
98+
"https://bigquery.googleapis.com/bigquery/v2/projects/gcloud-devel/datasets?prettyPrint=false",
99+
(String) attrs.get(HttpTracingRequestInitializer.URL_FULL));
100+
101+
String destinationId =
102+
(String) attrs.get(BigQueryTelemetryTracer.GCP_RESOURCE_DESTINATION_ID);
103+
assertNotNull(destinationId);
104+
assertTrue(destinationId.contains("projects/"));
105+
}
106+
}
107+
assertTrue(foundRpcSpan, "Expected to find BigQueryRpc.listDatasets span");
108+
}
109+
110+
@Test
111+
public void testGetDatasetNotFoundTraced() {
112+
BigQuery bq =
113+
bigqueryHelper.getOptions().toBuilder()
114+
.setEnableOpenTelemetryTracing(true)
115+
.setOpenTelemetryTracer(tracer)
116+
.build()
117+
.getService();
118+
119+
bq.getDataset("non_existent_dataset");
120+
121+
List<SpanData> spans = memoryExporter.getFinishedSpanItems();
122+
assertNotNull(spans);
123+
assertTrue(spans.size() > 0, "Expected at least one span collected");
124+
125+
boolean foundRpcSpan = false;
126+
for (SpanData span : spans) {
127+
if (span.getName().equals("com.google.cloud.bigquery.BigQueryRpc.getDataset")) {
128+
foundRpcSpan = true;
129+
Map<AttributeKey<?>, Object> attrs = span.getAttributes().asMap();
130+
checkGeneralAttributes(attrs);
131+
assertEquals("GET", attrs.get(HttpTracingRequestInitializer.HTTP_REQUEST_METHOD));
132+
assertEquals("DatasetService", attrs.get(AttributeKey.stringKey("bq.rpc.service")));
133+
assertEquals("GetDataset", attrs.get(AttributeKey.stringKey("bq.rpc.method")));
134+
assertEquals(404L, attrs.get(HttpTracingRequestInitializer.HTTP_RESPONSE_STATUS_CODE));
135+
assertEquals(
136+
"projects/{+projectId}/datasets/{+datasetId}",
137+
attrs.get(BigQueryTelemetryTracer.URL_TEMPLATE));
138+
assertEquals(
139+
"https://bigquery.googleapis.com/bigquery/v2/projects/gcloud-devel/datasets/non_existent_dataset?prettyPrint=false",
140+
attrs.get(HttpTracingRequestInitializer.URL_FULL));
141+
assertEquals("bigquery.googleapis.com", attrs.get(BigQueryTelemetryTracer.SERVER_ADDRESS));
142+
143+
// Error attributes
144+
assertEquals("notFound", attrs.get(BigQueryTelemetryTracer.ERROR_TYPE));
145+
assertEquals(
146+
"Not found: Dataset gcloud-devel:non_existent_dataset",
147+
attrs.get(BigQueryTelemetryTracer.STATUS_MESSAGE));
148+
}
149+
}
150+
assertTrue(foundRpcSpan, "Expected to find BigQueryRpc.getDataset span");
151+
}
152+
153+
@Test
154+
public void testConnectionErrorRetriesTraced() {
155+
// Pass invalid host to force connection error and retries
156+
BigQuery bq =
157+
bigqueryHelper.getOptions().toBuilder()
158+
.setEnableOpenTelemetryTracing(true)
159+
.setOpenTelemetryTracer(tracer)
160+
.setHost("https://invalid-host-name-12345.com")
161+
.build()
162+
.getService();
163+
164+
try {
165+
bq.listDatasets();
166+
fail("Expected BigQueryException due to invalid host");
167+
} catch (BigQueryException e) {
168+
// Expected
169+
}
170+
171+
List<SpanData> spans = memoryExporter.getFinishedSpanItems();
172+
assertNotNull(spans);
173+
assertTrue(spans.size() > 0, "Expected at least one span collected");
174+
175+
int rpcSpanCount = 0;
176+
for (SpanData span : spans) {
177+
if (span.getName().equals("com.google.cloud.bigquery.BigQueryRpc.listDatasets")) {
178+
rpcSpanCount++;
179+
Map<AttributeKey<?>, Object> attrs = span.getAttributes().asMap();
180+
181+
// Validate common attributes if they are set before failure
182+
checkGeneralAttributes(attrs);
183+
assertEquals(
184+
"https://invalid-host-name-12345.com/bigquery/v2/projects/gcloud-devel/datasets?prettyPrint=false",
185+
(String) attrs.get(HttpTracingRequestInitializer.URL_FULL));
186+
assertEquals(
187+
"invalid-host-name-12345.com", attrs.get(BigQueryTelemetryTracer.SERVER_ADDRESS));
188+
189+
Long resendCount =
190+
(Long) attrs.get(HttpTracingRequestInitializer.HTTP_REQUEST_RESEND_COUNT);
191+
if (rpcSpanCount == 1) {
192+
assertTrue(resendCount == null || resendCount == 0);
193+
} else {
194+
assertNotNull(resendCount, "Expected resend count for retry attempt " + rpcSpanCount);
195+
assertEquals((long) (rpcSpanCount - 1), resendCount.longValue());
196+
}
197+
198+
// Error attributes
199+
assertEquals(
200+
"java.net.UnknownHostException", attrs.get(BigQueryTelemetryTracer.EXCEPTION_TYPE));
201+
assertEquals(
202+
ErrorType.CLIENT_CONNECTION_ERROR.toString(),
203+
attrs.get(BigQueryTelemetryTracer.ERROR_TYPE));
204+
assertNotNull(attrs.get(BigQueryTelemetryTracer.STATUS_MESSAGE));
205+
}
206+
}
207+
assertTrue(rpcSpanCount > 0, "Expected to find at least one listDatasets span");
208+
// Verify it went up to 4 (5 attempts total: 1 original + 4 retries)
209+
assertEquals(5, rpcSpanCount, "Expected 5 attempts total if it retries up to 4 times");
210+
}
211+
212+
private void checkGeneralAttributes(Map<AttributeKey<?>, Object> attrs) {
213+
assertEquals("http", attrs.get(BigQueryTelemetryTracer.RPC_SYSTEM_NAME));
214+
assertEquals(
215+
BigQueryTelemetryTracer.BQ_GCP_CLIENT_SERVICE,
216+
attrs.get(BigQueryTelemetryTracer.GCP_CLIENT_SERVICE));
217+
assertEquals(
218+
BigQueryTelemetryTracer.BQ_GCP_CLIENT_REPO,
219+
attrs.get(BigQueryTelemetryTracer.GCP_CLIENT_REPO));
220+
assertEquals(
221+
BigQueryTelemetryTracer.BQ_GCP_CLIENT_LANGUAGE,
222+
attrs.get(BigQueryTelemetryTracer.GCP_CLIENT_LANGUAGE));
223+
assertEquals(
224+
BigQueryTelemetryTracer.BQ_GCP_CLIENT_ARTIFACT,
225+
attrs.get(BigQueryTelemetryTracer.GCP_CLIENT_ARTIFACT));
226+
assertNotNull(attrs.get(BigQueryTelemetryTracer.GCP_CLIENT_VERSION));
227+
}
228+
}

0 commit comments

Comments
 (0)