From 16d3cd7331798e3aded727482bd22261d3addbf9 Mon Sep 17 00:00:00 2001 From: Diego Marquez Date: Fri, 20 Mar 2026 14:35:12 -0400 Subject: [PATCH 1/8] impl(o11y): introduce request status attributes --- .../gax/tracing/ObservabilityAttributes.java | 6 + .../api/gax/tracing/ObservabilityUtils.java | 51 +++++++ .../tracing/OpenTelemetryTraceManager.java | 7 + .../google/api/gax/tracing/SpanTracer.java | 38 +++++- .../google/api/gax/tracing/TraceManager.java | 6 + .../gax/tracing/ObservabilityUtilsTest.java | 107 +++++++++++++++ .../api/gax/tracing/SpanTracerTest.java | 126 ++++++++++++++++++ 7 files changed, 339 insertions(+), 2 deletions(-) diff --git a/gax-java/gax/src/main/java/com/google/api/gax/tracing/ObservabilityAttributes.java b/gax-java/gax/src/main/java/com/google/api/gax/tracing/ObservabilityAttributes.java index 5ea52462ca..7419d37527 100644 --- a/gax-java/gax/src/main/java/com/google/api/gax/tracing/ObservabilityAttributes.java +++ b/gax-java/gax/src/main/java/com/google/api/gax/tracing/ObservabilityAttributes.java @@ -84,4 +84,10 @@ public class ObservabilityAttributes { /** The url template of the request (e.g. /v1/{name}:access). */ public static final String URL_TEMPLATE_ATTRIBUTE = "url.template"; + + /** The HTTP status code of the request (e.g., 200, 404). */ + public static final String HTTP_RESPONSE_STATUS_ATTRIBUTE = "http.response.status_code"; + + /** The gRPC status code of the request (e.g., 0, 14). */ + public static final String RPC_GRPC_STATUS_ATTRIBUTE = "rpc.grpc.status_code"; } diff --git a/gax-java/gax/src/main/java/com/google/api/gax/tracing/ObservabilityUtils.java b/gax-java/gax/src/main/java/com/google/api/gax/tracing/ObservabilityUtils.java index f2a787fc95..88703b7ce1 100644 --- a/gax-java/gax/src/main/java/com/google/api/gax/tracing/ObservabilityUtils.java +++ b/gax-java/gax/src/main/java/com/google/api/gax/tracing/ObservabilityUtils.java @@ -56,6 +56,57 @@ static String extractStatus(@Nullable Throwable error) { return statusString; } + static void populateStatusAttributes( + Map attributes, + @Nullable Throwable error, + ApiTracerContext.Transport transport) { + if (transport == ApiTracerContext.Transport.GRPC) { + if (error == null) { + attributes.put( + ObservabilityAttributes.RPC_RESPONSE_STATUS_ATTRIBUTE, StatusCode.Code.OK.toString()); + attributes.put( + ObservabilityAttributes.RPC_GRPC_STATUS_ATTRIBUTE, (long) StatusCode.Code.OK.ordinal()); + } else if (error instanceof ApiException) { + attributes.put( + ObservabilityAttributes.RPC_RESPONSE_STATUS_ATTRIBUTE, + ((ApiException) error).getStatusCode().getCode().toString()); + attributes.put( + ObservabilityAttributes.RPC_GRPC_STATUS_ATTRIBUTE, + (long) ((ApiException) error).getStatusCode().getCode().ordinal()); + } else { + attributes.put(ObservabilityAttributes.RPC_RESPONSE_STATUS_ATTRIBUTE, extractStatus(error)); + StatusCode.Code code = StatusCode.Code.UNKNOWN; + if (error instanceof CancellationException) { + code = StatusCode.Code.CANCELLED; + } + attributes.put(ObservabilityAttributes.RPC_GRPC_STATUS_ATTRIBUTE, (long) code.ordinal()); + } + } else if (transport == ApiTracerContext.Transport.HTTP) { + if (error == null) { + attributes.put(ObservabilityAttributes.HTTP_RESPONSE_STATUS_ATTRIBUTE, 200L); + } else if (error instanceof ApiException) { + Object transportCode = ((ApiException) error).getStatusCode().getTransportCode(); + if (transportCode instanceof Integer) { + attributes.put( + ObservabilityAttributes.HTTP_RESPONSE_STATUS_ATTRIBUTE, + ((Integer) transportCode).longValue()); + } else { + attributes.put( + ObservabilityAttributes.HTTP_RESPONSE_STATUS_ATTRIBUTE, + (long) ((ApiException) error).getStatusCode().getCode().getHttpStatusCode()); + } + } else { + StatusCode.Code code = StatusCode.Code.UNKNOWN; + if (error instanceof CancellationException) { + code = StatusCode.Code.CANCELLED; + } + attributes.put( + ObservabilityAttributes.HTTP_RESPONSE_STATUS_ATTRIBUTE, + (long) code.getHttpStatusCode()); + } + } + } + static Attributes toOtelAttributes(Map attributes) { AttributesBuilder attributesBuilder = Attributes.builder(); if (attributes == null) { diff --git a/gax-java/gax/src/main/java/com/google/api/gax/tracing/OpenTelemetryTraceManager.java b/gax-java/gax/src/main/java/com/google/api/gax/tracing/OpenTelemetryTraceManager.java index 833e56fda4..093b656424 100644 --- a/gax-java/gax/src/main/java/com/google/api/gax/tracing/OpenTelemetryTraceManager.java +++ b/gax-java/gax/src/main/java/com/google/api/gax/tracing/OpenTelemetryTraceManager.java @@ -71,6 +71,13 @@ private OtelSpan(io.opentelemetry.api.trace.Span span) { this.span = span; } + @Override + public void addAttributes(Map attributes) { + if (attributes != null) { + span.setAllAttributes(ObservabilityUtils.toOtelAttributes(attributes)); + } + } + @Override public void end() { span.end(); diff --git a/gax-java/gax/src/main/java/com/google/api/gax/tracing/SpanTracer.java b/gax-java/gax/src/main/java/com/google/api/gax/tracing/SpanTracer.java index c5c28aebe0..3fedcebe73 100644 --- a/gax-java/gax/src/main/java/com/google/api/gax/tracing/SpanTracer.java +++ b/gax-java/gax/src/main/java/com/google/api/gax/tracing/SpanTracer.java @@ -34,6 +34,7 @@ import com.google.api.core.InternalApi; import java.util.HashMap; import java.util.Map; +import java.util.concurrent.CancellationException; /** * An implementation of {@link ApiTracer} that uses a {@link TraceManager} to record traces. This @@ -82,11 +83,44 @@ public void attemptStarted(Object request, int attemptNumber) { @Override public void attemptSucceeded() { - endAttempt(); + endAttempt(null); } - private void endAttempt() { + @Override + public void attemptCancelled() { + endAttempt(new CancellationException()); + } + + @Override + public void attemptFailedRetriesExhausted(Throwable error) { + endAttempt(error); + } + + @Override + public void attemptPermanentFailure(Throwable error) { + endAttempt(error); + } + + @Override + public void attemptFailedDuration(Throwable error, java.time.Duration delay) { + endAttempt(error); + } + + @Override + public void attemptFailed(Throwable error, org.threeten.bp.Duration delay) { + endAttempt(error); + } + + private void endAttempt(Throwable error) { if (attemptHandle != null) { + Map endAttributes = new HashMap<>(); + ObservabilityUtils.populateStatusAttributes( + endAttributes, error, this.apiTracerContext.transport()); + + if (!endAttributes.isEmpty()) { + attemptHandle.addAttributes(endAttributes); + } + attemptHandle.end(); attemptHandle = null; } diff --git a/gax-java/gax/src/main/java/com/google/api/gax/tracing/TraceManager.java b/gax-java/gax/src/main/java/com/google/api/gax/tracing/TraceManager.java index 8572d1ce11..c0420f1051 100644 --- a/gax-java/gax/src/main/java/com/google/api/gax/tracing/TraceManager.java +++ b/gax-java/gax/src/main/java/com/google/api/gax/tracing/TraceManager.java @@ -45,6 +45,12 @@ public interface TraceManager { Span createSpan(String name, Map attributes); interface Span { + /** + * Adds an attribute to the span. This is useful for adding attributes that are only available + * after the span has started, e.g. status codes. + */ + void addAttributes(Map attributes); + void end(); } } diff --git a/gax-java/gax/src/test/java/com/google/api/gax/tracing/ObservabilityUtilsTest.java b/gax-java/gax/src/test/java/com/google/api/gax/tracing/ObservabilityUtilsTest.java index 0af3be4746..5c469956f1 100644 --- a/gax-java/gax/src/test/java/com/google/api/gax/tracing/ObservabilityUtilsTest.java +++ b/gax-java/gax/src/test/java/com/google/api/gax/tracing/ObservabilityUtilsTest.java @@ -114,6 +114,113 @@ void testToOtelAttributes_shouldMapIntAttributes() { .isEqualTo((long) attribute2Value); } + @Test + void testPopulateStatusAttributes_grpc_success() { + Map attributes = new java.util.HashMap<>(); + ObservabilityUtils.populateStatusAttributes(attributes, null, ApiTracerContext.Transport.GRPC); + assertThat(attributes) + .containsEntry(ObservabilityAttributes.RPC_RESPONSE_STATUS_ATTRIBUTE, "OK"); + assertThat(attributes) + .containsEntry( + ObservabilityAttributes.RPC_GRPC_STATUS_ATTRIBUTE, (long) StatusCode.Code.OK.ordinal()); + } + + @Test + void testPopulateStatusAttributes_grpc_apiException() { + Map attributes = new java.util.HashMap<>(); + ApiException error = + new ApiException("fake_error", null, new FakeStatusCode(StatusCode.Code.NOT_FOUND), false); + ObservabilityUtils.populateStatusAttributes(attributes, error, ApiTracerContext.Transport.GRPC); + assertThat(attributes) + .containsEntry(ObservabilityAttributes.RPC_RESPONSE_STATUS_ATTRIBUTE, "NOT_FOUND"); + assertThat(attributes) + .containsEntry( + ObservabilityAttributes.RPC_GRPC_STATUS_ATTRIBUTE, + (long) StatusCode.Code.NOT_FOUND.ordinal()); + } + + @Test + void testPopulateStatusAttributes_grpc_cancellationException() { + Map attributes = new java.util.HashMap<>(); + Throwable error = new java.util.concurrent.CancellationException(); + ObservabilityUtils.populateStatusAttributes(attributes, error, ApiTracerContext.Transport.GRPC); + assertThat(attributes) + .containsEntry(ObservabilityAttributes.RPC_RESPONSE_STATUS_ATTRIBUTE, "CANCELLED"); + assertThat(attributes) + .containsEntry( + ObservabilityAttributes.RPC_GRPC_STATUS_ATTRIBUTE, + (long) StatusCode.Code.CANCELLED.ordinal()); + } + + @Test + void testPopulateStatusAttributes_http_success() { + Map attributes = new java.util.HashMap<>(); + ObservabilityUtils.populateStatusAttributes(attributes, null, ApiTracerContext.Transport.HTTP); + assertThat(attributes) + .containsEntry(ObservabilityAttributes.HTTP_RESPONSE_STATUS_ATTRIBUTE, 200L); + } + + @Test + void testPopulateStatusAttributes_http_apiExceptionWithIntegerTransportCode() { + Map attributes = new java.util.HashMap<>(); + ApiException error = + new ApiException( + "fake_error", + null, + new com.google.api.gax.rpc.StatusCode() { + @Override + public Code getCode() { + return Code.NOT_FOUND; + } + + @Override + public Object getTransportCode() { + return 404; + } + }, + false); + ObservabilityUtils.populateStatusAttributes(attributes, error, ApiTracerContext.Transport.HTTP); + assertThat(attributes) + .containsEntry(ObservabilityAttributes.HTTP_RESPONSE_STATUS_ATTRIBUTE, 404L); + } + + @Test + void testPopulateStatusAttributes_http_apiExceptionWithNonIntegerTransportCode() { + Map attributes = new java.util.HashMap<>(); + ApiException error = + new ApiException( + "fake_error", + null, + new com.google.api.gax.rpc.StatusCode() { + @Override + public Code getCode() { + return Code.NOT_FOUND; + } + + @Override + public Object getTransportCode() { + return "Not Found"; + } + }, + false); + ObservabilityUtils.populateStatusAttributes(attributes, error, ApiTracerContext.Transport.HTTP); + assertThat(attributes) + .containsEntry( + ObservabilityAttributes.HTTP_RESPONSE_STATUS_ATTRIBUTE, + (long) StatusCode.Code.NOT_FOUND.getHttpStatusCode()); + } + + @Test + void testPopulateStatusAttributes_http_cancellationException() { + Map attributes = new java.util.HashMap<>(); + Throwable error = new java.util.concurrent.CancellationException(); + ObservabilityUtils.populateStatusAttributes(attributes, error, ApiTracerContext.Transport.HTTP); + assertThat(attributes) + .containsEntry( + ObservabilityAttributes.HTTP_RESPONSE_STATUS_ATTRIBUTE, + (long) StatusCode.Code.CANCELLED.getHttpStatusCode()); + } + @Test void testToOtelAttributes_shouldReturnEmptyAttributes_nullInput() { assertThat(ObservabilityUtils.toOtelAttributes(null)).isEqualTo(Attributes.empty()); diff --git a/gax-java/gax/src/test/java/com/google/api/gax/tracing/SpanTracerTest.java b/gax-java/gax/src/test/java/com/google/api/gax/tracing/SpanTracerTest.java index b5e6100fe6..515aef46fc 100644 --- a/gax-java/gax/src/test/java/com/google/api/gax/tracing/SpanTracerTest.java +++ b/gax-java/gax/src/test/java/com/google/api/gax/tracing/SpanTracerTest.java @@ -76,4 +76,130 @@ void testAttemptStarted_includesLanguageAttribute() { assertThat(attributesCaptor.getValue()) .containsEntry(SpanTracer.LANGUAGE_ATTRIBUTE, SpanTracer.DEFAULT_LANGUAGE); } + + @Test + void testAttemptSucceeded_grpc() { + ApiTracerContext context = + ApiTracerContext.newBuilder() + .setLibraryMetadata(com.google.api.gax.rpc.LibraryMetadata.empty()) + .setTransport(ApiTracerContext.Transport.GRPC) + .build(); + tracer = new SpanTracer(recorder, context, ATTEMPT_SPAN_NAME); + when(recorder.createSpan(eq(ATTEMPT_SPAN_NAME), anyMap())).thenReturn(attemptHandle); + + tracer.attemptStarted(new Object(), 1); + tracer.attemptSucceeded(); + + ArgumentCaptor> attrsCaptor = ArgumentCaptor.forClass(Map.class); + verify(attemptHandle).addAttributes(attrsCaptor.capture()); + verify(attemptHandle).end(); + + assertThat(attrsCaptor.getValue()) + .containsEntry(ObservabilityAttributes.RPC_RESPONSE_STATUS_ATTRIBUTE, "OK"); + assertThat(attrsCaptor.getValue()) + .containsEntry( + ObservabilityAttributes.RPC_GRPC_STATUS_ATTRIBUTE, + (long) com.google.api.gax.rpc.StatusCode.Code.OK.ordinal()); + } + + @Test + void testAttemptSucceeded_http() { + ApiTracerContext context = + ApiTracerContext.newBuilder() + .setLibraryMetadata(com.google.api.gax.rpc.LibraryMetadata.empty()) + .setTransport(ApiTracerContext.Transport.HTTP) + .build(); + tracer = new SpanTracer(recorder, context, ATTEMPT_SPAN_NAME); + when(recorder.createSpan(eq(ATTEMPT_SPAN_NAME), anyMap())).thenReturn(attemptHandle); + + tracer.attemptStarted(new Object(), 1); + tracer.attemptSucceeded(); + + ArgumentCaptor> attrsCaptor = ArgumentCaptor.forClass(Map.class); + verify(attemptHandle).addAttributes(attrsCaptor.capture()); + verify(attemptHandle).end(); + + assertThat(attrsCaptor.getValue()) + .containsEntry(ObservabilityAttributes.HTTP_RESPONSE_STATUS_ATTRIBUTE, 200L); + } + + @Test + void testAttemptFailed_grpc() { + ApiTracerContext context = + ApiTracerContext.newBuilder() + .setLibraryMetadata(com.google.api.gax.rpc.LibraryMetadata.empty()) + .setTransport(ApiTracerContext.Transport.GRPC) + .build(); + tracer = new SpanTracer(recorder, context, ATTEMPT_SPAN_NAME); + when(recorder.createSpan(eq(ATTEMPT_SPAN_NAME), anyMap())).thenReturn(attemptHandle); + + com.google.api.gax.rpc.ApiException exception = + new com.google.api.gax.rpc.ApiException( + "error", + null, + new com.google.api.gax.rpc.StatusCode() { + @Override + public Code getCode() { + return Code.NOT_FOUND; + } + + @Override + public Object getTransportCode() { + return null; + } + }, + false); + + tracer.attemptStarted(new Object(), 1); + tracer.attemptFailedRetriesExhausted(exception); + + ArgumentCaptor> attrsCaptor = ArgumentCaptor.forClass(Map.class); + verify(attemptHandle).addAttributes(attrsCaptor.capture()); + verify(attemptHandle).end(); + + assertThat(attrsCaptor.getValue()) + .containsEntry(ObservabilityAttributes.RPC_RESPONSE_STATUS_ATTRIBUTE, "NOT_FOUND"); + assertThat(attrsCaptor.getValue()) + .containsEntry( + ObservabilityAttributes.RPC_GRPC_STATUS_ATTRIBUTE, + (long) com.google.api.gax.rpc.StatusCode.Code.NOT_FOUND.ordinal()); + } + + @Test + void testAttemptFailed_http() { + ApiTracerContext context = + ApiTracerContext.newBuilder() + .setLibraryMetadata(com.google.api.gax.rpc.LibraryMetadata.empty()) + .setTransport(ApiTracerContext.Transport.HTTP) + .build(); + tracer = new SpanTracer(recorder, context, ATTEMPT_SPAN_NAME); + when(recorder.createSpan(eq(ATTEMPT_SPAN_NAME), anyMap())).thenReturn(attemptHandle); + + com.google.api.gax.rpc.ApiException exception = + new com.google.api.gax.rpc.ApiException( + "error", + null, + new com.google.api.gax.rpc.StatusCode() { + @Override + public Code getCode() { + return Code.NOT_FOUND; + } + + @Override + public Object getTransportCode() { + return 404; + } + }, + false); + + tracer.attemptStarted(new Object(), 1); + tracer.attemptFailedRetriesExhausted(exception); + + ArgumentCaptor> attrsCaptor = ArgumentCaptor.forClass(Map.class); + verify(attemptHandle).addAttributes(attrsCaptor.capture()); + verify(attemptHandle).end(); + + assertThat(attrsCaptor.getValue()) + .containsEntry(ObservabilityAttributes.HTTP_RESPONSE_STATUS_ATTRIBUTE, 404L); + } } From 1bf460f02f7603281d46764a638190a069b4ea19 Mon Sep 17 00:00:00 2001 From: Diego Marquez Date: Fri, 20 Mar 2026 14:54:51 -0400 Subject: [PATCH 2/8] refactor(o11y): extract status attributes logic to private helpers --- .../api/gax/tracing/ObservabilityUtils.java | 85 ++++++++++--------- 1 file changed, 47 insertions(+), 38 deletions(-) diff --git a/gax-java/gax/src/main/java/com/google/api/gax/tracing/ObservabilityUtils.java b/gax-java/gax/src/main/java/com/google/api/gax/tracing/ObservabilityUtils.java index 88703b7ce1..5b8249e9ef 100644 --- a/gax-java/gax/src/main/java/com/google/api/gax/tracing/ObservabilityUtils.java +++ b/gax-java/gax/src/main/java/com/google/api/gax/tracing/ObservabilityUtils.java @@ -61,49 +61,58 @@ static void populateStatusAttributes( @Nullable Throwable error, ApiTracerContext.Transport transport) { if (transport == ApiTracerContext.Transport.GRPC) { - if (error == null) { - attributes.put( - ObservabilityAttributes.RPC_RESPONSE_STATUS_ATTRIBUTE, StatusCode.Code.OK.toString()); - attributes.put( - ObservabilityAttributes.RPC_GRPC_STATUS_ATTRIBUTE, (long) StatusCode.Code.OK.ordinal()); - } else if (error instanceof ApiException) { - attributes.put( - ObservabilityAttributes.RPC_RESPONSE_STATUS_ATTRIBUTE, - ((ApiException) error).getStatusCode().getCode().toString()); - attributes.put( - ObservabilityAttributes.RPC_GRPC_STATUS_ATTRIBUTE, - (long) ((ApiException) error).getStatusCode().getCode().ordinal()); - } else { - attributes.put(ObservabilityAttributes.RPC_RESPONSE_STATUS_ATTRIBUTE, extractStatus(error)); - StatusCode.Code code = StatusCode.Code.UNKNOWN; - if (error instanceof CancellationException) { - code = StatusCode.Code.CANCELLED; - } - attributes.put(ObservabilityAttributes.RPC_GRPC_STATUS_ATTRIBUTE, (long) code.ordinal()); - } + populateGrpcStatusAttributes(attributes, error); } else if (transport == ApiTracerContext.Transport.HTTP) { - if (error == null) { - attributes.put(ObservabilityAttributes.HTTP_RESPONSE_STATUS_ATTRIBUTE, 200L); - } else if (error instanceof ApiException) { - Object transportCode = ((ApiException) error).getStatusCode().getTransportCode(); - if (transportCode instanceof Integer) { - attributes.put( - ObservabilityAttributes.HTTP_RESPONSE_STATUS_ATTRIBUTE, - ((Integer) transportCode).longValue()); - } else { - attributes.put( - ObservabilityAttributes.HTTP_RESPONSE_STATUS_ATTRIBUTE, - (long) ((ApiException) error).getStatusCode().getCode().getHttpStatusCode()); - } + populateHttpStatusAttributes(attributes, error); + } + } + + private static void populateGrpcStatusAttributes( + Map attributes, @Nullable Throwable error) { + if (error == null) { + attributes.put( + ObservabilityAttributes.RPC_RESPONSE_STATUS_ATTRIBUTE, StatusCode.Code.OK.toString()); + attributes.put( + ObservabilityAttributes.RPC_GRPC_STATUS_ATTRIBUTE, (long) StatusCode.Code.OK.ordinal()); + } else if (error instanceof ApiException) { + attributes.put( + ObservabilityAttributes.RPC_RESPONSE_STATUS_ATTRIBUTE, + ((ApiException) error).getStatusCode().getCode().toString()); + attributes.put( + ObservabilityAttributes.RPC_GRPC_STATUS_ATTRIBUTE, + (long) ((ApiException) error).getStatusCode().getCode().ordinal()); + } else { + attributes.put(ObservabilityAttributes.RPC_RESPONSE_STATUS_ATTRIBUTE, extractStatus(error)); + StatusCode.Code code = StatusCode.Code.UNKNOWN; + if (error instanceof CancellationException) { + code = StatusCode.Code.CANCELLED; + } + attributes.put(ObservabilityAttributes.RPC_GRPC_STATUS_ATTRIBUTE, (long) code.ordinal()); + } + } + + private static void populateHttpStatusAttributes( + Map attributes, @Nullable Throwable error) { + if (error == null) { + attributes.put(ObservabilityAttributes.HTTP_RESPONSE_STATUS_ATTRIBUTE, 200L); + } else if (error instanceof ApiException) { + Object transportCode = ((ApiException) error).getStatusCode().getTransportCode(); + if (transportCode instanceof Integer) { + attributes.put( + ObservabilityAttributes.HTTP_RESPONSE_STATUS_ATTRIBUTE, + ((Integer) transportCode).longValue()); } else { - StatusCode.Code code = StatusCode.Code.UNKNOWN; - if (error instanceof CancellationException) { - code = StatusCode.Code.CANCELLED; - } attributes.put( ObservabilityAttributes.HTTP_RESPONSE_STATUS_ATTRIBUTE, - (long) code.getHttpStatusCode()); + (long) ((ApiException) error).getStatusCode().getCode().getHttpStatusCode()); + } + } else { + StatusCode.Code code = StatusCode.Code.UNKNOWN; + if (error instanceof CancellationException) { + code = StatusCode.Code.CANCELLED; } + attributes.put( + ObservabilityAttributes.HTTP_RESPONSE_STATUS_ATTRIBUTE, (long) code.getHttpStatusCode()); } } From 9f2ecd97c4980630bf466605eb167383db04fc32 Mon Sep 17 00:00:00 2001 From: Diego Marquez Date: Fri, 20 Mar 2026 14:56:00 -0400 Subject: [PATCH 3/8] test(o11y): add status attributes tests in ITOtelTracing --- .../showcase/v1beta1/it/ITOtelTracing.java | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/java-showcase/gapic-showcase/src/test/java/com/google/showcase/v1beta1/it/ITOtelTracing.java b/java-showcase/gapic-showcase/src/test/java/com/google/showcase/v1beta1/it/ITOtelTracing.java index e0f0295cc9..d9a5678d40 100644 --- a/java-showcase/gapic-showcase/src/test/java/com/google/showcase/v1beta1/it/ITOtelTracing.java +++ b/java-showcase/gapic-showcase/src/test/java/com/google/showcase/v1beta1/it/ITOtelTracing.java @@ -143,6 +143,18 @@ void testTracing_successfulEcho_grpc() throws Exception { .get(AttributeKey.stringKey(ObservabilityAttributes.VERSION_ATTRIBUTE))) .isEqualTo("0.0.0-SNAPSHOT"); // {x-version-update-end} + assertThat( + attemptSpan + .getAttributes() + .get( + AttributeKey.stringKey( + ObservabilityAttributes.RPC_RESPONSE_STATUS_ATTRIBUTE))) + .isEqualTo("OK"); + assertThat( + attemptSpan + .getAttributes() + .get(AttributeKey.longKey(ObservabilityAttributes.RPC_GRPC_STATUS_ATTRIBUTE))) + .isEqualTo(0L); } } @@ -201,6 +213,12 @@ void testTracing_successfulEcho_httpjson() throws Exception { .getAttributes() .get(AttributeKey.stringKey(ObservabilityAttributes.HTTP_URL_TEMPLATE_ATTRIBUTE))) .isEqualTo("v1beta1/echo:echo"); + assertThat( + attemptSpan + .getAttributes() + .get( + AttributeKey.longKey(ObservabilityAttributes.HTTP_RESPONSE_STATUS_ATTRIBUTE))) + .isEqualTo(200L); } } } From ba55a34964b7533f529d958ea791d79197b25763 Mon Sep 17 00:00:00 2001 From: Diego Marquez Date: Fri, 20 Mar 2026 14:59:32 -0400 Subject: [PATCH 4/8] test(o11y): remove assertions for deprecated rpc.grpc.status_code --- .../api/gax/tracing/ObservabilityUtilsTest.java | 11 ----------- .../com/google/api/gax/tracing/SpanTracerTest.java | 8 -------- .../com/google/showcase/v1beta1/it/ITOtelTracing.java | 5 ----- 3 files changed, 24 deletions(-) diff --git a/gax-java/gax/src/test/java/com/google/api/gax/tracing/ObservabilityUtilsTest.java b/gax-java/gax/src/test/java/com/google/api/gax/tracing/ObservabilityUtilsTest.java index 5c469956f1..f798bbf5f9 100644 --- a/gax-java/gax/src/test/java/com/google/api/gax/tracing/ObservabilityUtilsTest.java +++ b/gax-java/gax/src/test/java/com/google/api/gax/tracing/ObservabilityUtilsTest.java @@ -120,9 +120,6 @@ void testPopulateStatusAttributes_grpc_success() { ObservabilityUtils.populateStatusAttributes(attributes, null, ApiTracerContext.Transport.GRPC); assertThat(attributes) .containsEntry(ObservabilityAttributes.RPC_RESPONSE_STATUS_ATTRIBUTE, "OK"); - assertThat(attributes) - .containsEntry( - ObservabilityAttributes.RPC_GRPC_STATUS_ATTRIBUTE, (long) StatusCode.Code.OK.ordinal()); } @Test @@ -133,10 +130,6 @@ void testPopulateStatusAttributes_grpc_apiException() { ObservabilityUtils.populateStatusAttributes(attributes, error, ApiTracerContext.Transport.GRPC); assertThat(attributes) .containsEntry(ObservabilityAttributes.RPC_RESPONSE_STATUS_ATTRIBUTE, "NOT_FOUND"); - assertThat(attributes) - .containsEntry( - ObservabilityAttributes.RPC_GRPC_STATUS_ATTRIBUTE, - (long) StatusCode.Code.NOT_FOUND.ordinal()); } @Test @@ -146,10 +139,6 @@ void testPopulateStatusAttributes_grpc_cancellationException() { ObservabilityUtils.populateStatusAttributes(attributes, error, ApiTracerContext.Transport.GRPC); assertThat(attributes) .containsEntry(ObservabilityAttributes.RPC_RESPONSE_STATUS_ATTRIBUTE, "CANCELLED"); - assertThat(attributes) - .containsEntry( - ObservabilityAttributes.RPC_GRPC_STATUS_ATTRIBUTE, - (long) StatusCode.Code.CANCELLED.ordinal()); } @Test diff --git a/gax-java/gax/src/test/java/com/google/api/gax/tracing/SpanTracerTest.java b/gax-java/gax/src/test/java/com/google/api/gax/tracing/SpanTracerTest.java index 515aef46fc..2d65e8fdf3 100644 --- a/gax-java/gax/src/test/java/com/google/api/gax/tracing/SpanTracerTest.java +++ b/gax-java/gax/src/test/java/com/google/api/gax/tracing/SpanTracerTest.java @@ -96,10 +96,6 @@ void testAttemptSucceeded_grpc() { assertThat(attrsCaptor.getValue()) .containsEntry(ObservabilityAttributes.RPC_RESPONSE_STATUS_ATTRIBUTE, "OK"); - assertThat(attrsCaptor.getValue()) - .containsEntry( - ObservabilityAttributes.RPC_GRPC_STATUS_ATTRIBUTE, - (long) com.google.api.gax.rpc.StatusCode.Code.OK.ordinal()); } @Test @@ -159,10 +155,6 @@ public Object getTransportCode() { assertThat(attrsCaptor.getValue()) .containsEntry(ObservabilityAttributes.RPC_RESPONSE_STATUS_ATTRIBUTE, "NOT_FOUND"); - assertThat(attrsCaptor.getValue()) - .containsEntry( - ObservabilityAttributes.RPC_GRPC_STATUS_ATTRIBUTE, - (long) com.google.api.gax.rpc.StatusCode.Code.NOT_FOUND.ordinal()); } @Test diff --git a/java-showcase/gapic-showcase/src/test/java/com/google/showcase/v1beta1/it/ITOtelTracing.java b/java-showcase/gapic-showcase/src/test/java/com/google/showcase/v1beta1/it/ITOtelTracing.java index d9a5678d40..235c40e930 100644 --- a/java-showcase/gapic-showcase/src/test/java/com/google/showcase/v1beta1/it/ITOtelTracing.java +++ b/java-showcase/gapic-showcase/src/test/java/com/google/showcase/v1beta1/it/ITOtelTracing.java @@ -150,11 +150,6 @@ void testTracing_successfulEcho_grpc() throws Exception { AttributeKey.stringKey( ObservabilityAttributes.RPC_RESPONSE_STATUS_ATTRIBUTE))) .isEqualTo("OK"); - assertThat( - attemptSpan - .getAttributes() - .get(AttributeKey.longKey(ObservabilityAttributes.RPC_GRPC_STATUS_ATTRIBUTE))) - .isEqualTo(0L); } } From b7d7b4a647e2297a98241b08e971df454cea5565 Mon Sep 17 00:00:00 2001 From: Diego Marquez Date: Fri, 20 Mar 2026 15:18:57 -0400 Subject: [PATCH 5/8] fix: handle longs in ObsUtils --- .../java/com/google/api/gax/tracing/ObservabilityUtils.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/gax-java/gax/src/main/java/com/google/api/gax/tracing/ObservabilityUtils.java b/gax-java/gax/src/main/java/com/google/api/gax/tracing/ObservabilityUtils.java index 5b8249e9ef..3f8c906fc4 100644 --- a/gax-java/gax/src/main/java/com/google/api/gax/tracing/ObservabilityUtils.java +++ b/gax-java/gax/src/main/java/com/google/api/gax/tracing/ObservabilityUtils.java @@ -127,6 +127,8 @@ static Attributes toOtelAttributes(Map attributes) { attributesBuilder.put(k, (String) v); } else if (v instanceof Integer) { attributesBuilder.put(k, (long) (Integer) v); + } else if (v instanceof Long) { + attributesBuilder.put(k, (Long) v); } }); return attributesBuilder.build(); From 3c815d5fe4a74c910a46866feb9a49ca96d73575 Mon Sep 17 00:00:00 2001 From: Diego Marquez Date: Fri, 20 Mar 2026 18:49:23 -0400 Subject: [PATCH 6/8] fix: separate logic for http and grpc --- .../gax/tracing/ObservabilityAttributes.java | 3 - .../api/gax/tracing/ObservabilityUtils.java | 77 +++++++----------- .../gax/tracing/ObservabilityUtilsTest.java | 7 +- .../api/gax/tracing/SpanTracerTest.java | 80 ++++++++++--------- 4 files changed, 77 insertions(+), 90 deletions(-) diff --git a/gax-java/gax/src/main/java/com/google/api/gax/tracing/ObservabilityAttributes.java b/gax-java/gax/src/main/java/com/google/api/gax/tracing/ObservabilityAttributes.java index 7419d37527..86e922b94e 100644 --- a/gax-java/gax/src/main/java/com/google/api/gax/tracing/ObservabilityAttributes.java +++ b/gax-java/gax/src/main/java/com/google/api/gax/tracing/ObservabilityAttributes.java @@ -87,7 +87,4 @@ public class ObservabilityAttributes { /** The HTTP status code of the request (e.g., 200, 404). */ public static final String HTTP_RESPONSE_STATUS_ATTRIBUTE = "http.response.status_code"; - - /** The gRPC status code of the request (e.g., 0, 14). */ - public static final String RPC_GRPC_STATUS_ATTRIBUTE = "rpc.grpc.status_code"; } diff --git a/gax-java/gax/src/main/java/com/google/api/gax/tracing/ObservabilityUtils.java b/gax-java/gax/src/main/java/com/google/api/gax/tracing/ObservabilityUtils.java index 3f8c906fc4..0c939a488c 100644 --- a/gax-java/gax/src/main/java/com/google/api/gax/tracing/ObservabilityUtils.java +++ b/gax-java/gax/src/main/java/com/google/api/gax/tracing/ObservabilityUtils.java @@ -39,10 +39,20 @@ class ObservabilityUtils { - /** Function to extract the status of the error as a string */ + /** Function to extract the status of the error as a string (defaults to gRPC canonical codes). */ static String extractStatus(@Nullable Throwable error) { - final String statusString; + return (String) extractStatus(error, ApiTracerContext.Transport.GRPC); + } + + static Object extractStatus(@Nullable Throwable error, ApiTracerContext.Transport transport) { + if (transport == ApiTracerContext.Transport.HTTP) { + return extractHttpStatus(error); + } + return extractGrpcStatus(error); + } + private static String extractGrpcStatus(@Nullable Throwable error) { + final String statusString; if (error == null) { return StatusCode.Code.OK.toString(); } else if (error instanceof CancellationException) { @@ -52,67 +62,38 @@ static String extractStatus(@Nullable Throwable error) { } else { statusString = StatusCode.Code.UNKNOWN.toString(); } - return statusString; } - static void populateStatusAttributes( - Map attributes, - @Nullable Throwable error, - ApiTracerContext.Transport transport) { - if (transport == ApiTracerContext.Transport.GRPC) { - populateGrpcStatusAttributes(attributes, error); - } else if (transport == ApiTracerContext.Transport.HTTP) { - populateHttpStatusAttributes(attributes, error); - } - } - - private static void populateGrpcStatusAttributes( - Map attributes, @Nullable Throwable error) { - if (error == null) { - attributes.put( - ObservabilityAttributes.RPC_RESPONSE_STATUS_ATTRIBUTE, StatusCode.Code.OK.toString()); - attributes.put( - ObservabilityAttributes.RPC_GRPC_STATUS_ATTRIBUTE, (long) StatusCode.Code.OK.ordinal()); - } else if (error instanceof ApiException) { - attributes.put( - ObservabilityAttributes.RPC_RESPONSE_STATUS_ATTRIBUTE, - ((ApiException) error).getStatusCode().getCode().toString()); - attributes.put( - ObservabilityAttributes.RPC_GRPC_STATUS_ATTRIBUTE, - (long) ((ApiException) error).getStatusCode().getCode().ordinal()); - } else { - attributes.put(ObservabilityAttributes.RPC_RESPONSE_STATUS_ATTRIBUTE, extractStatus(error)); - StatusCode.Code code = StatusCode.Code.UNKNOWN; - if (error instanceof CancellationException) { - code = StatusCode.Code.CANCELLED; - } - attributes.put(ObservabilityAttributes.RPC_GRPC_STATUS_ATTRIBUTE, (long) code.ordinal()); - } - } - - private static void populateHttpStatusAttributes( - Map attributes, @Nullable Throwable error) { + private static Long extractHttpStatus(@Nullable Throwable error) { if (error == null) { - attributes.put(ObservabilityAttributes.HTTP_RESPONSE_STATUS_ATTRIBUTE, 200L); + return 200L; } else if (error instanceof ApiException) { Object transportCode = ((ApiException) error).getStatusCode().getTransportCode(); if (transportCode instanceof Integer) { - attributes.put( - ObservabilityAttributes.HTTP_RESPONSE_STATUS_ATTRIBUTE, - ((Integer) transportCode).longValue()); + return ((Integer) transportCode).longValue(); } else { - attributes.put( - ObservabilityAttributes.HTTP_RESPONSE_STATUS_ATTRIBUTE, - (long) ((ApiException) error).getStatusCode().getCode().getHttpStatusCode()); + return (long) ((ApiException) error).getStatusCode().getCode().getHttpStatusCode(); } } else { StatusCode.Code code = StatusCode.Code.UNKNOWN; if (error instanceof CancellationException) { code = StatusCode.Code.CANCELLED; } + return (long) code.getHttpStatusCode(); + } + } + + static void populateStatusAttributes( + Map attributes, + @Nullable Throwable error, + ApiTracerContext.Transport transport) { + if (transport == ApiTracerContext.Transport.GRPC) { + attributes.put( + ObservabilityAttributes.RPC_RESPONSE_STATUS_ATTRIBUTE, extractStatus(error, transport)); + } else if (transport == ApiTracerContext.Transport.HTTP) { attributes.put( - ObservabilityAttributes.HTTP_RESPONSE_STATUS_ATTRIBUTE, (long) code.getHttpStatusCode()); + ObservabilityAttributes.HTTP_RESPONSE_STATUS_ATTRIBUTE, extractStatus(error, transport)); } } diff --git a/gax-java/gax/src/test/java/com/google/api/gax/tracing/ObservabilityUtilsTest.java b/gax-java/gax/src/test/java/com/google/api/gax/tracing/ObservabilityUtilsTest.java index f798bbf5f9..b4b9365a5e 100644 --- a/gax-java/gax/src/test/java/com/google/api/gax/tracing/ObservabilityUtilsTest.java +++ b/gax-java/gax/src/test/java/com/google/api/gax/tracing/ObservabilityUtilsTest.java @@ -146,7 +146,7 @@ void testPopulateStatusAttributes_http_success() { Map attributes = new java.util.HashMap<>(); ObservabilityUtils.populateStatusAttributes(attributes, null, ApiTracerContext.Transport.HTTP); assertThat(attributes) - .containsEntry(ObservabilityAttributes.HTTP_RESPONSE_STATUS_ATTRIBUTE, 200L); + .containsEntry(ObservabilityAttributes.HTTP_RESPONSE_STATUS_ATTRIBUTE, StatusCode.Code.OK.getHttpStatusCode()); } @Test @@ -164,13 +164,14 @@ public Code getCode() { @Override public Object getTransportCode() { - return 404; + return StatusCode.Code.NOT_FOUND.getHttpStatusCode(); } }, false); ObservabilityUtils.populateStatusAttributes(attributes, error, ApiTracerContext.Transport.HTTP); assertThat(attributes) - .containsEntry(ObservabilityAttributes.HTTP_RESPONSE_STATUS_ATTRIBUTE, 404L); + .containsEntry(ObservabilityAttributes.HTTP_RESPONSE_STATUS_ATTRIBUTE, + StatusCode.Code.NOT_FOUND.getHttpStatusCode()); } @Test diff --git a/gax-java/gax/src/test/java/com/google/api/gax/tracing/SpanTracerTest.java b/gax-java/gax/src/test/java/com/google/api/gax/tracing/SpanTracerTest.java index 54b1c3c996..39bbe4fd27 100644 --- a/gax-java/gax/src/test/java/com/google/api/gax/tracing/SpanTracerTest.java +++ b/gax-java/gax/src/test/java/com/google/api/gax/tracing/SpanTracerTest.java @@ -94,18 +94,20 @@ void testAttemptSucceeded_grpc() { .setLibraryMetadata(com.google.api.gax.rpc.LibraryMetadata.empty()) .setTransport(ApiTracerContext.Transport.GRPC) .build(); - tracer = new SpanTracer(recorder, context, ATTEMPT_SPAN_NAME); - when(recorder.createSpan(eq(ATTEMPT_SPAN_NAME), anyMap())).thenReturn(attemptHandle); + spanTracer = new SpanTracer(tracer, context, ATTEMPT_SPAN_NAME); - tracer.attemptStarted(new Object(), 1); - tracer.attemptSucceeded(); + spanTracer.attemptStarted(new Object(), 1); + spanTracer.attemptSucceeded(); - ArgumentCaptor> attrsCaptor = ArgumentCaptor.forClass(Map.class); - verify(attemptHandle).addAttributes(attrsCaptor.capture()); - verify(attemptHandle).end(); + ArgumentCaptor attrsCaptor = ArgumentCaptor.forClass(Attributes.class); + verify(span).setAllAttributes(attrsCaptor.capture()); + verify(span).end(); - assertThat(attrsCaptor.getValue()) - .containsEntry(ObservabilityAttributes.RPC_RESPONSE_STATUS_ATTRIBUTE, "OK"); + assertThat(attrsCaptor.getValue().asMap()) + .containsEntry( + io.opentelemetry.api.common.AttributeKey.stringKey( + ObservabilityAttributes.RPC_RESPONSE_STATUS_ATTRIBUTE), + "OK"); } @Test @@ -115,18 +117,20 @@ void testAttemptSucceeded_http() { .setLibraryMetadata(com.google.api.gax.rpc.LibraryMetadata.empty()) .setTransport(ApiTracerContext.Transport.HTTP) .build(); - tracer = new SpanTracer(recorder, context, ATTEMPT_SPAN_NAME); - when(recorder.createSpan(eq(ATTEMPT_SPAN_NAME), anyMap())).thenReturn(attemptHandle); + spanTracer = new SpanTracer(tracer, context, ATTEMPT_SPAN_NAME); - tracer.attemptStarted(new Object(), 1); - tracer.attemptSucceeded(); + spanTracer.attemptStarted(new Object(), 1); + spanTracer.attemptSucceeded(); - ArgumentCaptor> attrsCaptor = ArgumentCaptor.forClass(Map.class); - verify(attemptHandle).addAttributes(attrsCaptor.capture()); - verify(attemptHandle).end(); + ArgumentCaptor attrsCaptor = ArgumentCaptor.forClass(Attributes.class); + verify(span).setAllAttributes(attrsCaptor.capture()); + verify(span).end(); - assertThat(attrsCaptor.getValue()) - .containsEntry(ObservabilityAttributes.HTTP_RESPONSE_STATUS_ATTRIBUTE, 200L); + assertThat(attrsCaptor.getValue().asMap()) + .containsEntry( + io.opentelemetry.api.common.AttributeKey.longKey( + ObservabilityAttributes.HTTP_RESPONSE_STATUS_ATTRIBUTE), + 200L); } @Test @@ -136,8 +140,7 @@ void testAttemptFailed_grpc() { .setLibraryMetadata(com.google.api.gax.rpc.LibraryMetadata.empty()) .setTransport(ApiTracerContext.Transport.GRPC) .build(); - tracer = new SpanTracer(recorder, context, ATTEMPT_SPAN_NAME); - when(recorder.createSpan(eq(ATTEMPT_SPAN_NAME), anyMap())).thenReturn(attemptHandle); + spanTracer = new SpanTracer(tracer, context, ATTEMPT_SPAN_NAME); com.google.api.gax.rpc.ApiException exception = new com.google.api.gax.rpc.ApiException( @@ -156,15 +159,18 @@ public Object getTransportCode() { }, false); - tracer.attemptStarted(new Object(), 1); - tracer.attemptFailedRetriesExhausted(exception); + spanTracer.attemptStarted(new Object(), 1); + spanTracer.attemptFailedRetriesExhausted(exception); - ArgumentCaptor> attrsCaptor = ArgumentCaptor.forClass(Map.class); - verify(attemptHandle).addAttributes(attrsCaptor.capture()); - verify(attemptHandle).end(); + ArgumentCaptor attrsCaptor = ArgumentCaptor.forClass(Attributes.class); + verify(span).setAllAttributes(attrsCaptor.capture()); + verify(span).end(); - assertThat(attrsCaptor.getValue()) - .containsEntry(ObservabilityAttributes.RPC_RESPONSE_STATUS_ATTRIBUTE, "NOT_FOUND"); + assertThat(attrsCaptor.getValue().asMap()) + .containsEntry( + io.opentelemetry.api.common.AttributeKey.stringKey( + ObservabilityAttributes.RPC_RESPONSE_STATUS_ATTRIBUTE), + "NOT_FOUND"); } @Test @@ -174,8 +180,7 @@ void testAttemptFailed_http() { .setLibraryMetadata(com.google.api.gax.rpc.LibraryMetadata.empty()) .setTransport(ApiTracerContext.Transport.HTTP) .build(); - tracer = new SpanTracer(recorder, context, ATTEMPT_SPAN_NAME); - when(recorder.createSpan(eq(ATTEMPT_SPAN_NAME), anyMap())).thenReturn(attemptHandle); + spanTracer = new SpanTracer(tracer, context, ATTEMPT_SPAN_NAME); com.google.api.gax.rpc.ApiException exception = new com.google.api.gax.rpc.ApiException( @@ -194,14 +199,17 @@ public Object getTransportCode() { }, false); - tracer.attemptStarted(new Object(), 1); - tracer.attemptFailedRetriesExhausted(exception); + spanTracer.attemptStarted(new Object(), 1); + spanTracer.attemptFailedRetriesExhausted(exception); - ArgumentCaptor> attrsCaptor = ArgumentCaptor.forClass(Map.class); - verify(attemptHandle).addAttributes(attrsCaptor.capture()); - verify(attemptHandle).end(); + ArgumentCaptor attrsCaptor = ArgumentCaptor.forClass(Attributes.class); + verify(span).setAllAttributes(attrsCaptor.capture()); + verify(span).end(); - assertThat(attrsCaptor.getValue()) - .containsEntry(ObservabilityAttributes.HTTP_RESPONSE_STATUS_ATTRIBUTE, 404L); + assertThat(attrsCaptor.getValue().asMap()) + .containsEntry( + io.opentelemetry.api.common.AttributeKey.longKey( + ObservabilityAttributes.HTTP_RESPONSE_STATUS_ATTRIBUTE), + 404L); } } From 981d76f317c259c512cbf35100a976480560fee3 Mon Sep 17 00:00:00 2001 From: Diego Marquez Date: Tue, 24 Mar 2026 16:00:30 -0400 Subject: [PATCH 7/8] fix: correct ITOtelTracing.java --- .../java/com/google/showcase/v1beta1/it/ITOtelTracing.java | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/java-showcase/gapic-showcase/src/test/java/com/google/showcase/v1beta1/it/ITOtelTracing.java b/java-showcase/gapic-showcase/src/test/java/com/google/showcase/v1beta1/it/ITOtelTracing.java index 4c5c0927cb..c5f686ee9c 100644 --- a/java-showcase/gapic-showcase/src/test/java/com/google/showcase/v1beta1/it/ITOtelTracing.java +++ b/java-showcase/gapic-showcase/src/test/java/com/google/showcase/v1beta1/it/ITOtelTracing.java @@ -42,11 +42,13 @@ import com.google.api.gax.tracing.SpanTracer; import com.google.api.gax.tracing.SpanTracerFactory; import com.google.rpc.Status; +import com.google.showcase.v1beta1.CreateUserRequest; import com.google.showcase.v1beta1.EchoClient; import com.google.showcase.v1beta1.EchoRequest; import com.google.showcase.v1beta1.EchoSettings; import com.google.showcase.v1beta1.GetUserRequest; import com.google.showcase.v1beta1.IdentityClient; +import com.google.showcase.v1beta1.User; import com.google.showcase.v1beta1.it.util.TestClientInitializer; import com.google.showcase.v1beta1.stub.EchoStub; import com.google.showcase.v1beta1.stub.EchoStubSettings; @@ -95,13 +97,14 @@ void tearDown() { @Test void testTracing_successfulIdentityGetUser_grpc() throws Exception { + final String username = "users/test-user"; SpanTracerFactory tracingFactory = new SpanTracerFactory(openTelemetrySdk); try (IdentityClient client = TestClientInitializer.createGrpcIdentityClientOpentelemetry(tracingFactory)) { try { - client.getUser(GetUserRequest.newBuilder().setName("users/test-user").build()); + client.getUser(GetUserRequest.newBuilder().setName(username).build()); } catch (Exception e) { // Ignored, the showcase server may not have this user, but trace is still generated. } @@ -176,12 +179,14 @@ void testTracing_successfulIdentityGetUser_grpc() throws Exception { @Test void testTracing_successfulIdentityGetUser_httpjson() throws Exception { + final String username = "users/test-user"; SpanTracerFactory tracingFactory = new SpanTracerFactory(openTelemetrySdk); try (IdentityClient client = TestClientInitializer.createHttpJsonIdentityClientOpentelemetry(tracingFactory)) { try { + client.createUser(CreateUserRequest.newBuilder().setUser(User.newBuilder().setName(username)).build()); client.getUser(GetUserRequest.newBuilder().setName("users/test-user").build()); } catch (Exception e) { // Ignored, the showcase server may not have this user, but trace is still generated. From 9213e06bd739929fe569916625e0100b38e63b5e Mon Sep 17 00:00:00 2001 From: cloud-java-bot Date: Tue, 24 Mar 2026 20:08:24 +0000 Subject: [PATCH 8/8] chore: generate libraries at Tue Mar 24 20:06:22 UTC 2026 --- .../com/google/showcase/v1beta1/it/ITOtelTracing.java | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/java-showcase/gapic-showcase/src/test/java/com/google/showcase/v1beta1/it/ITOtelTracing.java b/java-showcase/gapic-showcase/src/test/java/com/google/showcase/v1beta1/it/ITOtelTracing.java index c5f686ee9c..2cc3076003 100644 --- a/java-showcase/gapic-showcase/src/test/java/com/google/showcase/v1beta1/it/ITOtelTracing.java +++ b/java-showcase/gapic-showcase/src/test/java/com/google/showcase/v1beta1/it/ITOtelTracing.java @@ -97,14 +97,14 @@ void tearDown() { @Test void testTracing_successfulIdentityGetUser_grpc() throws Exception { - final String username = "users/test-user"; + final String username = "users/test-user"; SpanTracerFactory tracingFactory = new SpanTracerFactory(openTelemetrySdk); try (IdentityClient client = TestClientInitializer.createGrpcIdentityClientOpentelemetry(tracingFactory)) { try { - client.getUser(GetUserRequest.newBuilder().setName(username).build()); + client.getUser(GetUserRequest.newBuilder().setName(username).build()); } catch (Exception e) { // Ignored, the showcase server may not have this user, but trace is still generated. } @@ -179,14 +179,15 @@ void testTracing_successfulIdentityGetUser_grpc() throws Exception { @Test void testTracing_successfulIdentityGetUser_httpjson() throws Exception { - final String username = "users/test-user"; + final String username = "users/test-user"; SpanTracerFactory tracingFactory = new SpanTracerFactory(openTelemetrySdk); try (IdentityClient client = TestClientInitializer.createHttpJsonIdentityClientOpentelemetry(tracingFactory)) { try { - client.createUser(CreateUserRequest.newBuilder().setUser(User.newBuilder().setName(username)).build()); + client.createUser( + CreateUserRequest.newBuilder().setUser(User.newBuilder().setName(username)).build()); client.getUser(GetUserRequest.newBuilder().setName("users/test-user").build()); } catch (Exception e) { // Ignored, the showcase server may not have this user, but trace is still generated.