From fd5c4f94688c237754ed733753ba9e6855065b28 Mon Sep 17 00:00:00 2001 From: Diego Date: Mon, 30 Mar 2026 15:27:50 -0400 Subject: [PATCH 1/3] impl(o11y): introduce `gcp.client.service` attribute --- .../com/google/api/gax/rpc/ClientContext.java | 1 + .../api/gax/tracing/ApiTracerContextTest.java | 13 ++++ .../showcase/v1beta1/it/ITOtelTracing.java | 63 +++++++++++++++++-- 3 files changed, 73 insertions(+), 4 deletions(-) diff --git a/sdk-platform-java/gax-java/gax/src/main/java/com/google/api/gax/rpc/ClientContext.java b/sdk-platform-java/gax-java/gax/src/main/java/com/google/api/gax/rpc/ClientContext.java index 43fdd848b6c7..d88c279d7dc1 100644 --- a/sdk-platform-java/gax-java/gax/src/main/java/com/google/api/gax/rpc/ClientContext.java +++ b/sdk-platform-java/gax-java/gax/src/main/java/com/google/api/gax/rpc/ClientContext.java @@ -276,6 +276,7 @@ public static ClientContext create(StubSettings settings) throws IOException { .setServerAddress(endpointContext.resolvedServerAddress()) .setServerPort(endpointContext.resolvedServerPort()) .setLibraryMetadata(settings.getLibraryMetadata()) + .setServiceName(endpointContext.serviceName()) .build(); ApiTracerFactory apiTracerFactory = settings.getTracerFactory(); if (apiTracerFactory instanceof SpanTracerFactory) { diff --git a/sdk-platform-java/gax-java/gax/src/test/java/com/google/api/gax/tracing/ApiTracerContextTest.java b/sdk-platform-java/gax-java/gax/src/test/java/com/google/api/gax/tracing/ApiTracerContextTest.java index b465dfbebe02..86a0156c0e8f 100644 --- a/sdk-platform-java/gax-java/gax/src/test/java/com/google/api/gax/tracing/ApiTracerContextTest.java +++ b/sdk-platform-java/gax-java/gax/src/test/java/com/google/api/gax/tracing/ApiTracerContextTest.java @@ -186,6 +186,19 @@ void testGetAttemptAttributes_emptyStrings() { assertThat(attributes).isEmpty(); } + @Test + void testGetAttemptAttributes_serviceName() { + ApiTracerContext context = + ApiTracerContext.newBuilder() + .setLibraryMetadata(LibraryMetadata.empty()) + .setServiceName("test-service") + .build(); + Map attributes = context.getAttemptAttributes(); + + assertThat(attributes) + .containsEntry(ObservabilityAttributes.GCP_CLIENT_SERVICE_ATTRIBUTE, "test-service"); + } + @Test void testGetMetricsAttributes_serverPort() { ApiTracerContext context = diff --git a/sdk-platform-java/java-showcase/gapic-showcase/src/test/java/com/google/showcase/v1beta1/it/ITOtelTracing.java b/sdk-platform-java/java-showcase/gapic-showcase/src/test/java/com/google/showcase/v1beta1/it/ITOtelTracing.java index ff4731c99d36..73023b953cb4 100644 --- a/sdk-platform-java/java-showcase/gapic-showcase/src/test/java/com/google/showcase/v1beta1/it/ITOtelTracing.java +++ b/sdk-platform-java/java-showcase/gapic-showcase/src/test/java/com/google/showcase/v1beta1/it/ITOtelTracing.java @@ -50,6 +50,8 @@ import com.google.showcase.v1beta1.it.util.TestClientInitializer; import com.google.showcase.v1beta1.stub.EchoStub; import com.google.showcase.v1beta1.stub.EchoStubSettings; +import io.grpc.ManagedChannelBuilder; +import java.io.IOException; import io.opentelemetry.api.GlobalOpenTelemetry; import io.opentelemetry.api.common.AttributeKey; import io.opentelemetry.api.trace.SpanKind; @@ -98,8 +100,22 @@ void tearDown() { void testTracing_successfulEcho_grpc() throws Exception { SpanTracerFactory tracingFactory = new SpanTracerFactory(openTelemetrySdk); - try (EchoClient client = - TestClientInitializer.createGrpcEchoClientOpentelemetry(tracingFactory)) { + EchoSettings grpcEchoSettings = + EchoSettings.newBuilder() + .setCredentialsProvider(NoCredentialsProvider.create()) + .setTransportChannelProvider( + EchoSettings.defaultGrpcTransportProviderBuilder() + .setChannelConfigurator(ManagedChannelBuilder::usePlaintext) + .build()) + .setEndpoint("localhost:7469") + .build(); + + EchoStubSettings.Builder builder = (EchoStubSettings.Builder) grpcEchoSettings.getStubSettings().toBuilder(); + builder.setTracerFactory(tracingFactory); + ExtendedEchoStubSettings echoStubSettings = new ExtendedEchoStubSettings(builder); + EchoStub stub = echoStubSettings.createStub(); + + try (EchoClient client = EchoClient.create(stub)) { client.echo(EchoRequest.newBuilder().setContent("tracing-test").build()); @@ -142,6 +158,11 @@ void testTracing_successfulEcho_grpc() throws Exception { .getAttributes() .get(AttributeKey.stringKey(ObservabilityAttributes.RPC_SYSTEM_NAME_ATTRIBUTE))) .isEqualTo("grpc"); + assertThat( + attemptSpan + .getAttributes() + .get(AttributeKey.stringKey(ObservabilityAttributes.GCP_CLIENT_SERVICE_ATTRIBUTE))) + .isEqualTo("showcase"); assertThat( attemptSpan .getAttributes() @@ -156,8 +177,23 @@ void testTracing_successfulEcho_grpc() throws Exception { void testTracing_successfulEcho_httpjson() throws Exception { SpanTracerFactory tracingFactory = new SpanTracerFactory(openTelemetrySdk); - try (EchoClient client = - TestClientInitializer.createHttpJsonEchoClientOpentelemetry(tracingFactory)) { + EchoSettings httpJsonEchoSettings = + EchoSettings.newHttpJsonBuilder() + .setCredentialsProvider(NoCredentialsProvider.create()) + .setTransportChannelProvider( + EchoSettings.defaultHttpJsonTransportProviderBuilder() + .setHttpTransport( + new NetHttpTransport.Builder().doNotValidateCertificate().build()) + .build()) + .setEndpoint("http://localhost:7469") + .build(); + + EchoStubSettings.Builder builder = (EchoStubSettings.Builder) httpJsonEchoSettings.getStubSettings().toBuilder(); + builder.setTracerFactory(tracingFactory); + ExtendedEchoStubSettings echoStubSettings = new ExtendedEchoStubSettings(builder); + EchoStub stub = echoStubSettings.createStub(); + + try (EchoClient client = EchoClient.create(stub)) { client.echo(EchoRequest.newBuilder().setContent("tracing-test").build()); @@ -196,6 +232,11 @@ void testTracing_successfulEcho_httpjson() throws Exception { .getAttributes() .get(AttributeKey.stringKey(ObservabilityAttributes.ARTIFACT_ATTRIBUTE))) .isEqualTo(SHOWCASE_ARTIFACT); + assertThat( + attemptSpan + .getAttributes() + .get(AttributeKey.stringKey(ObservabilityAttributes.GCP_CLIENT_SERVICE_ATTRIBUTE))) + .isEqualTo("showcase"); assertThat( attemptSpan .getAttributes() @@ -365,4 +406,18 @@ void testTracing_retry_httpjson() throws Exception { .collect(java.util.stream.Collectors.toList()); assertThat(resendCounts).containsExactlyElementsIn(expectedCounts).inOrder(); } + + /** + * Custom wrapper to set a service name for showcase clients, which lack one by default. + */ + private static class ExtendedEchoStubSettings extends EchoStubSettings { + protected ExtendedEchoStubSettings(EchoStubSettings.Builder builder) throws IOException { + super(builder); + } + + @Override + public String getServiceName() { + return "showcase"; + } + } } From 77161eca0b18abcc2424e592cf31a294de21d6af Mon Sep 17 00:00:00 2001 From: Diego Date: Tue, 31 Mar 2026 15:59:25 -0400 Subject: [PATCH 2/3] test: refactor repeated code --- .../showcase/v1beta1/it/ITOtelTracing.java | 43 +++++++++++-------- 1 file changed, 24 insertions(+), 19 deletions(-) diff --git a/sdk-platform-java/java-showcase/gapic-showcase/src/test/java/com/google/showcase/v1beta1/it/ITOtelTracing.java b/sdk-platform-java/java-showcase/gapic-showcase/src/test/java/com/google/showcase/v1beta1/it/ITOtelTracing.java index 73023b953cb4..ef95c05a8bb5 100644 --- a/sdk-platform-java/java-showcase/gapic-showcase/src/test/java/com/google/showcase/v1beta1/it/ITOtelTracing.java +++ b/sdk-platform-java/java-showcase/gapic-showcase/src/test/java/com/google/showcase/v1beta1/it/ITOtelTracing.java @@ -47,11 +47,9 @@ import com.google.showcase.v1beta1.EchoClient; import com.google.showcase.v1beta1.EchoRequest; import com.google.showcase.v1beta1.EchoSettings; -import com.google.showcase.v1beta1.it.util.TestClientInitializer; import com.google.showcase.v1beta1.stub.EchoStub; import com.google.showcase.v1beta1.stub.EchoStubSettings; import io.grpc.ManagedChannelBuilder; -import java.io.IOException; import io.opentelemetry.api.GlobalOpenTelemetry; import io.opentelemetry.api.common.AttributeKey; import io.opentelemetry.api.trace.SpanKind; @@ -60,6 +58,7 @@ import io.opentelemetry.sdk.trace.SdkTracerProvider; import io.opentelemetry.sdk.trace.data.SpanData; import io.opentelemetry.sdk.trace.export.SimpleSpanProcessor; +import java.io.IOException; import java.nio.charset.StandardCharsets; import java.util.List; import org.junit.jupiter.api.AfterEach; @@ -69,6 +68,10 @@ class ITOtelTracing { private static final String SHOWCASE_SERVER_ADDRESS = "localhost"; private static final long SHOWCASE_SERVER_PORT = 7469; + private static final String SHOWCASE_GRPC_ENDPOINT = + String.format("%s:%s", SHOWCASE_SERVER_ADDRESS, SHOWCASE_SERVER_PORT); + private static final String SHOWCASE_HTTPJSON_ENDPOINT = + String.format("http://%s:%s", SHOWCASE_SERVER_ADDRESS, SHOWCASE_SERVER_PORT); private static final String SHOWCASE_REPO = "googleapis/sdk-platform-java"; private static final String SHOWCASE_ARTIFACT = "com.google.cloud:gapic-showcase"; @@ -107,13 +110,10 @@ void testTracing_successfulEcho_grpc() throws Exception { EchoSettings.defaultGrpcTransportProviderBuilder() .setChannelConfigurator(ManagedChannelBuilder::usePlaintext) .build()) - .setEndpoint("localhost:7469") + .setEndpoint(SHOWCASE_GRPC_ENDPOINT) .build(); - EchoStubSettings.Builder builder = (EchoStubSettings.Builder) grpcEchoSettings.getStubSettings().toBuilder(); - builder.setTracerFactory(tracingFactory); - ExtendedEchoStubSettings echoStubSettings = new ExtendedEchoStubSettings(builder); - EchoStub stub = echoStubSettings.createStub(); + EchoStub stub = createStubWithServiceName(grpcEchoSettings, tracingFactory); try (EchoClient client = EchoClient.create(stub)) { @@ -161,7 +161,8 @@ void testTracing_successfulEcho_grpc() throws Exception { assertThat( attemptSpan .getAttributes() - .get(AttributeKey.stringKey(ObservabilityAttributes.GCP_CLIENT_SERVICE_ATTRIBUTE))) + .get( + AttributeKey.stringKey(ObservabilityAttributes.GCP_CLIENT_SERVICE_ATTRIBUTE))) .isEqualTo("showcase"); assertThat( attemptSpan @@ -185,13 +186,10 @@ void testTracing_successfulEcho_httpjson() throws Exception { .setHttpTransport( new NetHttpTransport.Builder().doNotValidateCertificate().build()) .build()) - .setEndpoint("http://localhost:7469") + .setEndpoint(SHOWCASE_HTTPJSON_ENDPOINT) .build(); - EchoStubSettings.Builder builder = (EchoStubSettings.Builder) httpJsonEchoSettings.getStubSettings().toBuilder(); - builder.setTracerFactory(tracingFactory); - ExtendedEchoStubSettings echoStubSettings = new ExtendedEchoStubSettings(builder); - EchoStub stub = echoStubSettings.createStub(); + EchoStub stub = createStubWithServiceName(httpJsonEchoSettings, tracingFactory); try (EchoClient client = EchoClient.create(stub)) { @@ -235,7 +233,8 @@ void testTracing_successfulEcho_httpjson() throws Exception { assertThat( attemptSpan .getAttributes() - .get(AttributeKey.stringKey(ObservabilityAttributes.GCP_CLIENT_SERVICE_ATTRIBUTE))) + .get( + AttributeKey.stringKey(ObservabilityAttributes.GCP_CLIENT_SERVICE_ATTRIBUTE))) .isEqualTo("showcase"); assertThat( attemptSpan @@ -283,7 +282,7 @@ void testTracing_retry_grpc() throws Exception { grpcEchoSettings.toBuilder() .setCredentialsProvider(NoCredentialsProvider.create()) .setTransportChannelProvider(EchoSettings.defaultGrpcTransportProviderBuilder().build()) - .setEndpoint("localhost:7469") + .setEndpoint(SHOWCASE_GRPC_ENDPOINT) .build(); SpanTracerFactory tracingFactory = new SpanTracerFactory(openTelemetrySdk); @@ -358,7 +357,7 @@ void testTracing_retry_httpjson() throws Exception { EchoSettings.defaultHttpJsonTransportProviderBuilder() .setHttpTransport( new NetHttpTransport.Builder().doNotValidateCertificate().build()) - .setEndpoint("http://localhost:7469") + .setEndpoint(SHOWCASE_HTTPJSON_ENDPOINT) .build()) .build(); @@ -407,9 +406,15 @@ void testTracing_retry_httpjson() throws Exception { assertThat(resendCounts).containsExactlyElementsIn(expectedCounts).inOrder(); } - /** - * Custom wrapper to set a service name for showcase clients, which lack one by default. - */ + private EchoStub createStubWithServiceName( + EchoSettings settings, SpanTracerFactory tracingFactory) throws IOException { + EchoStubSettings.Builder builder = + (EchoStubSettings.Builder) settings.getStubSettings().toBuilder(); + builder.setTracerFactory(tracingFactory); + return new ExtendedEchoStubSettings(builder).createStub(); + } + + /** Custom wrapper to set a service name for showcase clients, which lack one by default. */ private static class ExtendedEchoStubSettings extends EchoStubSettings { protected ExtendedEchoStubSettings(EchoStubSettings.Builder builder) throws IOException { super(builder); From 8d8addb214d83960d672a571439629478845e24b Mon Sep 17 00:00:00 2001 From: Diego Date: Tue, 31 Mar 2026 16:13:06 -0400 Subject: [PATCH 3/3] test: refactor duplicated code --- .../showcase/v1beta1/it/ITOtelTracing.java | 44 +++++++++++-------- 1 file changed, 25 insertions(+), 19 deletions(-) diff --git a/sdk-platform-java/java-showcase/gapic-showcase/src/test/java/com/google/showcase/v1beta1/it/ITOtelTracing.java b/sdk-platform-java/java-showcase/gapic-showcase/src/test/java/com/google/showcase/v1beta1/it/ITOtelTracing.java index ef95c05a8bb5..dfa0899131d2 100644 --- a/sdk-platform-java/java-showcase/gapic-showcase/src/test/java/com/google/showcase/v1beta1/it/ITOtelTracing.java +++ b/sdk-platform-java/java-showcase/gapic-showcase/src/test/java/com/google/showcase/v1beta1/it/ITOtelTracing.java @@ -103,15 +103,7 @@ void tearDown() { void testTracing_successfulEcho_grpc() throws Exception { SpanTracerFactory tracingFactory = new SpanTracerFactory(openTelemetrySdk); - EchoSettings grpcEchoSettings = - EchoSettings.newBuilder() - .setCredentialsProvider(NoCredentialsProvider.create()) - .setTransportChannelProvider( - EchoSettings.defaultGrpcTransportProviderBuilder() - .setChannelConfigurator(ManagedChannelBuilder::usePlaintext) - .build()) - .setEndpoint(SHOWCASE_GRPC_ENDPOINT) - .build(); + EchoSettings grpcEchoSettings = createEchoSettings(false); EchoStub stub = createStubWithServiceName(grpcEchoSettings, tracingFactory); @@ -178,16 +170,7 @@ void testTracing_successfulEcho_grpc() throws Exception { void testTracing_successfulEcho_httpjson() throws Exception { SpanTracerFactory tracingFactory = new SpanTracerFactory(openTelemetrySdk); - EchoSettings httpJsonEchoSettings = - EchoSettings.newHttpJsonBuilder() - .setCredentialsProvider(NoCredentialsProvider.create()) - .setTransportChannelProvider( - EchoSettings.defaultHttpJsonTransportProviderBuilder() - .setHttpTransport( - new NetHttpTransport.Builder().doNotValidateCertificate().build()) - .build()) - .setEndpoint(SHOWCASE_HTTPJSON_ENDPOINT) - .build(); + EchoSettings httpJsonEchoSettings = createEchoSettings(true); EchoStub stub = createStubWithServiceName(httpJsonEchoSettings, tracingFactory); @@ -406,6 +389,29 @@ void testTracing_retry_httpjson() throws Exception { assertThat(resendCounts).containsExactlyElementsIn(expectedCounts).inOrder(); } + private EchoSettings createEchoSettings(boolean isHttpJson) throws Exception { + if (isHttpJson) { + return EchoSettings.newHttpJsonBuilder() + .setCredentialsProvider(NoCredentialsProvider.create()) + .setTransportChannelProvider( + EchoSettings.defaultHttpJsonTransportProviderBuilder() + .setHttpTransport( + new NetHttpTransport.Builder().doNotValidateCertificate().build()) + .build()) + .setEndpoint(SHOWCASE_HTTPJSON_ENDPOINT) + .build(); + } else { + return EchoSettings.newBuilder() + .setCredentialsProvider(NoCredentialsProvider.create()) + .setTransportChannelProvider( + EchoSettings.defaultGrpcTransportProviderBuilder() + .setChannelConfigurator(ManagedChannelBuilder::usePlaintext) + .build()) + .setEndpoint(SHOWCASE_GRPC_ENDPOINT) + .build(); + } + } + private EchoStub createStubWithServiceName( EchoSettings settings, SpanTracerFactory tracingFactory) throws IOException { EchoStubSettings.Builder builder =