diff --git a/google-cloud-spanner/src/main/java/com/google/cloud/spanner/XGoogSpannerRequestId.java b/google-cloud-spanner/src/main/java/com/google/cloud/spanner/XGoogSpannerRequestId.java index 7c2006b64a..3b15f974fe 100644 --- a/google-cloud-spanner/src/main/java/com/google/cloud/spanner/XGoogSpannerRequestId.java +++ b/google-cloud-spanner/src/main/java/com/google/cloud/spanner/XGoogSpannerRequestId.java @@ -198,4 +198,8 @@ XGoogSpannerRequestId withNthClientId(long replacementClientId) { return XGoogSpannerRequestId.of( replacementClientId, this.nthChannelId, this.nthRequest, this.attempt); } + + public static String getRequestIdFromMetadata(Metadata md) { + return md.get(REQUEST_HEADER_KEY); + } } diff --git a/google-cloud-spanner/src/main/java/com/google/cloud/spanner/spi/v1/HeaderInterceptor.java b/google-cloud-spanner/src/main/java/com/google/cloud/spanner/spi/v1/HeaderInterceptor.java index 01aa28d8d9..6b82978e9e 100644 --- a/google-cloud-spanner/src/main/java/com/google/cloud/spanner/spi/v1/HeaderInterceptor.java +++ b/google-cloud-spanner/src/main/java/com/google/cloud/spanner/spi/v1/HeaderInterceptor.java @@ -28,6 +28,7 @@ import com.google.cloud.spanner.CompositeTracer; import com.google.cloud.spanner.SpannerExceptionFactory; import com.google.cloud.spanner.SpannerRpcMetrics; +import com.google.cloud.spanner.XGoogSpannerRequestId; import com.google.common.cache.Cache; import com.google.common.cache.CacheBuilder; import com.google.spanner.admin.database.v1.DatabaseName; @@ -174,6 +175,10 @@ private void processHeader( } if (span != null) { span.setAttribute("gfe_latency", String.valueOf(gfeLatency)); + String reqId = XGoogSpannerRequestId.getRequestIdFromMetadata(metadata); + if (reqId != null) { + span.setAttribute("x_goog_spanner_request_id", reqId); + } } } else { measureMap.put(SPANNER_GFE_HEADER_MISSING_COUNT, 1L).record(tagContext); diff --git a/google-cloud-spanner/src/test/java/com/google/cloud/spanner/OpenTelemetrySpanTest.java b/google-cloud-spanner/src/test/java/com/google/cloud/spanner/OpenTelemetrySpanTest.java index 90e66526f1..55681d3570 100644 --- a/google-cloud-spanner/src/test/java/com/google/cloud/spanner/OpenTelemetrySpanTest.java +++ b/google-cloud-spanner/src/test/java/com/google/cloud/spanner/OpenTelemetrySpanTest.java @@ -748,6 +748,13 @@ public void testTransactionRunnerWithRetryOnBeginTransaction() { beginTransactionSpan.toString(), beginTransactionSpan.getEvents().stream() .anyMatch(event -> event.getName().equals("Starting RPC retry 1"))); + verifyAtLeast1SpanHasXGoogSpannerRequestIdAttribute(finishedSpans); + } + + private void verifyAtLeast1SpanHasXGoogSpannerRequestIdAttribute(List finishedSpans) { + AttributeKey attributeKey = AttributeKey.stringKey("x_goog_spanner_request_id"); + assertTrue( + finishedSpans.stream().anyMatch(span -> !span.getAttributes().get(attributeKey).isEmpty())); } @Test @@ -798,6 +805,7 @@ public void testSingleUseRetryOnExecuteStreamingSql() { executeStreamingQuery.toString(), executeStreamingQuery.getEvents().stream() .anyMatch(event -> event.getName().contains("Stream broken. Safe to retry"))); + verifyAtLeast1SpanHasXGoogSpannerRequestIdAttribute(finishedSpans); } @Test @@ -845,6 +853,7 @@ public void testRetryOnExecuteSql() { executeSqlSpan.toString(), executeSqlSpan.getEvents().stream() .anyMatch(event -> event.getName().equals("Starting RPC retry 1"))); + verifyAtLeast1SpanHasXGoogSpannerRequestIdAttribute(finishedSpans); } @Test @@ -866,12 +875,14 @@ public void testTableAttributes() { } return null; }); + List finishedSpans = spanExporter.getFinishedSpanItems(); SpanData spanData = - spanExporter.getFinishedSpanItems().stream() + finishedSpans.stream() .filter(x -> x.getName().equals("CloudSpannerOperation.ExecuteStreamingRead")) .findFirst() .get(); verifyTableAttributes(spanData); + verifyAtLeast1SpanHasXGoogSpannerRequestIdAttribute(finishedSpans); } private void waitForFinishedSpans(int numExpectedSpans) {