From 29b7079fea74d96d64ceb2dd88c3398730166403 Mon Sep 17 00:00:00 2001 From: Wes Tarle Date: Mon, 23 Mar 2026 13:54:15 -0400 Subject: [PATCH 01/12] test(gax): add automated integration test for actionable errors logging --- .../it/logging/ITActionableErrorsLogging.java | 224 ++++++++++++++++++ 1 file changed, 224 insertions(+) create mode 100644 sdk-platform-java/java-showcase/gapic-showcase/src/test/java/com/google/showcase/v1beta1/it/logging/ITActionableErrorsLogging.java diff --git a/sdk-platform-java/java-showcase/gapic-showcase/src/test/java/com/google/showcase/v1beta1/it/logging/ITActionableErrorsLogging.java b/sdk-platform-java/java-showcase/gapic-showcase/src/test/java/com/google/showcase/v1beta1/it/logging/ITActionableErrorsLogging.java new file mode 100644 index 000000000000..bcfb91f47ed9 --- /dev/null +++ b/sdk-platform-java/java-showcase/gapic-showcase/src/test/java/com/google/showcase/v1beta1/it/logging/ITActionableErrorsLogging.java @@ -0,0 +1,224 @@ +/* + * Copyright 2026 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 + * + * https://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.google.showcase.v1beta1.it.logging; + +import static com.google.common.truth.Truth.assertThat; +import static org.junit.jupiter.api.Assertions.assertThrows; + +import ch.qos.logback.classic.Level; +import ch.qos.logback.classic.spi.ILoggingEvent; +import com.google.api.client.http.LowLevelHttpRequest; +import com.google.api.client.http.LowLevelHttpResponse; +import com.google.api.client.testing.http.MockHttpTransport; +import com.google.api.client.testing.http.MockLowLevelHttpRequest; +import com.google.api.client.testing.http.MockLowLevelHttpResponse; +import com.google.api.gax.core.NoCredentialsProvider; +import com.google.api.gax.rpc.ApiException; +import com.google.api.gax.tracing.LoggingTracerFactory; +import com.google.protobuf.Any; +import com.google.rpc.ErrorInfo; +import com.google.rpc.Status; +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 java.io.IOException; +import java.util.List; +import java.util.concurrent.TimeUnit; +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Test; +import org.slf4j.LoggerFactory; +import org.slf4j.event.KeyValuePair; + +public class ITActionableErrorsLogging { + + private static EchoClient grpcClient; + private static EchoClient httpjsonClient; + + @BeforeAll + static void createClients() throws Exception { + try { + java.lang.reflect.Method m = + com.google.api.gax.logging.LoggingUtils.class.getDeclaredMethod( + "setLoggingEnabled", boolean.class); + m.setAccessible(true); + m.invoke(null, true); + } catch (Exception e) { + throw new RuntimeException(e); + } + + grpcClient = + TestClientInitializer.createGrpcEchoClientOpentelemetry(new LoggingTracerFactory()); + httpjsonClient = + TestClientInitializer.createHttpJsonEchoClientOpentelemetry(new LoggingTracerFactory()); + } + + @AfterAll + static void destroyClients() throws InterruptedException { + grpcClient.close(); + httpjsonClient.close(); + + grpcClient.awaitTermination(TestClientInitializer.AWAIT_TERMINATION_SECONDS, TimeUnit.SECONDS); + httpjsonClient.awaitTermination( + TestClientInitializer.AWAIT_TERMINATION_SECONDS, TimeUnit.SECONDS); + try { + java.lang.reflect.Method m = + com.google.api.gax.logging.LoggingUtils.class.getDeclaredMethod( + "setLoggingEnabled", boolean.class); + m.setAccessible(true); + m.invoke(null, false); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + private TestAppender setupTestLogger() { + TestAppender testAppender = new TestAppender(); + testAppender.start(); + org.slf4j.Logger logger = LoggerFactory.getLogger("com.google.api.gax.tracing.LoggingTracer"); + ((ch.qos.logback.classic.Logger) logger).setLevel(Level.DEBUG); + ((ch.qos.logback.classic.Logger) logger).addAppender(testAppender); + return testAppender; + } + + private EchoRequest buildErrorRequest() { + ErrorInfo errorInfo = + ErrorInfo.newBuilder() + .setReason("TEST_REASON") + .setDomain("test.googleapis.com") + .putMetadata("test_metadata", "test_value") + .build(); + Status status = + Status.newBuilder() + .setCode(3) // INVALID_ARGUMENT + .setMessage("This is a test error") + .addDetails(Any.pack(errorInfo)) + .build(); + return EchoRequest.newBuilder().setError(status).build(); + } + + @Test + void testGrpc_actionableErrorLogged() { + TestAppender testAppender = setupTestLogger(); + + EchoRequest request = buildErrorRequest(); + + ApiException exception = assertThrows(ApiException.class, () -> grpcClient.echo(request)); + + assertThat(testAppender.events.size()).isAtLeast(1); + ILoggingEvent loggingEvent = testAppender.events.get(testAppender.events.size() - 1); + + assertThat(loggingEvent.getLevel()).isEqualTo(Level.DEBUG); + assertThat(loggingEvent.getMessage()).contains("This is a test error"); + + List kvps = loggingEvent.getKeyValuePairs(); + assertThat(kvps).contains(new KeyValuePair("rpc.system.name", "grpc")); + assertThat(kvps).contains(new KeyValuePair("rpc.method", "google.showcase.v1beta1.Echo/Echo")); + assertThat(kvps).contains(new KeyValuePair("rpc.response.status_code", "INVALID_ARGUMENT")); + assertThat(kvps).contains(new KeyValuePair("error.type", "TEST_REASON")); + assertThat(kvps).contains(new KeyValuePair("gcp.errors.domain", "test.googleapis.com")); + assertThat(kvps).contains(new KeyValuePair("gcp.errors.metadata.test_metadata", "test_value")); + + testAppender.stop(); + } + + @Test + void testHttpJson_actionableErrorLogged() throws Exception { + TestAppender testAppender = setupTestLogger(); + + // The gapic-showcase server currently returns text/plain for failEchoWithDetails instead of + // JSON. + // Additionally, sending an ErrorInfo in a request over REST fails serialization. + // To test HTTP JSON actionable errors logic, we use a MockHttpTransport that simulates the + // correct JSON format. + MockHttpTransport mockTransport = + new MockHttpTransport() { + @Override + public LowLevelHttpRequest buildRequest(String method, String url) throws IOException { + return new MockLowLevelHttpRequest() { + @Override + public LowLevelHttpResponse execute() throws IOException { + MockLowLevelHttpResponse response = new MockLowLevelHttpResponse(); + response.setStatusCode(409); // ABORTED + response.setContentType("application/json"); + String jsonError = + "{\n" + + " \"error\": {\n" + + " \"code\": 409,\n" + + " \"message\": \"This is a mock JSON error generated by the server\",\n" + + " \"status\": \"ABORTED\",\n" + + " \"details\": [\n" + + " {\n" + + " \"@type\": \"type.googleapis.com/google.rpc.ErrorInfo\",\n" + + " \"reason\": \"mock_error_reason\",\n" + + " \"domain\": \"mock.googleapis.com\",\n" + + " \"metadata\": {\"mock_key\": \"mock_value\"}\n" + + " }\n" + + " ]\n" + + " }\n" + + "}"; + response.setContent(jsonError); + return response; + } + }; + } + }; + + EchoSettings httpJsonEchoSettings = + EchoSettings.newHttpJsonBuilder() + .setCredentialsProvider(NoCredentialsProvider.create()) + .setTransportChannelProvider( + EchoSettings.defaultHttpJsonTransportProviderBuilder() + .setHttpTransport(mockTransport) + .setEndpoint(TestClientInitializer.DEFAULT_HTTPJSON_ENDPOINT) + .build()) + .build(); + + com.google.showcase.v1beta1.stub.EchoStubSettings echoStubSettings = + (com.google.showcase.v1beta1.stub.EchoStubSettings) + httpJsonEchoSettings.getStubSettings().toBuilder() + .setTracerFactory(new LoggingTracerFactory()) + .build(); + com.google.showcase.v1beta1.stub.EchoStub stub = echoStubSettings.createStub(); + EchoClient mockHttpJsonClient = EchoClient.create(stub); + + EchoRequest request = EchoRequest.newBuilder().build(); + + ApiException exception = + assertThrows(ApiException.class, () -> mockHttpJsonClient.echo(request)); + + assertThat(testAppender.events.size()).isAtLeast(1); + ILoggingEvent loggingEvent = testAppender.events.get(testAppender.events.size() - 1); + + assertThat(loggingEvent.getLevel()).isEqualTo(Level.DEBUG); + assertThat(loggingEvent.getMessage()) + .contains("This is a mock JSON error generated by the server"); + + List kvps = loggingEvent.getKeyValuePairs(); + assertThat(kvps).contains(new KeyValuePair("rpc.system.name", "http")); + assertThat(kvps).contains(new KeyValuePair("http.request.method", "POST")); + assertThat(kvps).contains(new KeyValuePair("url.template", "v1beta1/echo:echo")); + assertThat(kvps).contains(new KeyValuePair("rpc.response.status_code", "ABORTED")); + assertThat(kvps).contains(new KeyValuePair("error.type", "mock_error_reason")); + assertThat(kvps).contains(new KeyValuePair("gcp.errors.domain", "mock.googleapis.com")); + assertThat(kvps).contains(new KeyValuePair("gcp.errors.metadata.mock_key", "mock_value")); + + mockHttpJsonClient.close(); + testAppender.stop(); + } +} From c958a7fd961783179893c9df5dc6f3489cbc9b72 Mon Sep 17 00:00:00 2001 From: Wes Tarle Date: Tue, 31 Mar 2026 12:27:35 -0400 Subject: [PATCH 02/12] test(gax): add automated integration test for actionable errors logging --- sdk-platform-java/gax-java/gax/pom.xml | 1 + .../java-showcase/gapic-showcase/pom.xml | 51 ++++++++++ .../it/logging/ITActionableErrorsLogging.java | 98 +++++++------------ .../org.slf4j.spi.SLF4JServiceProvider | 1 + sdk-platform-java/java-showcase/pom.xml | 5 + 5 files changed, 92 insertions(+), 64 deletions(-) create mode 100644 sdk-platform-java/java-showcase/gapic-showcase/src/test/slf4j-test-provider/META-INF/services/org.slf4j.spi.SLF4JServiceProvider diff --git a/sdk-platform-java/gax-java/gax/pom.xml b/sdk-platform-java/gax-java/gax/pom.xml index 9c2589279b88..3af8a0c05480 100644 --- a/sdk-platform-java/gax-java/gax/pom.xml +++ b/sdk-platform-java/gax-java/gax/pom.xml @@ -115,6 +115,7 @@ com/google/api/gax/rpc/testing/** com/google/api/gax/rpc/mtls/** com/google/api/gax/util/** + com/google/api/gax/logging/** **/native-image.properties diff --git a/sdk-platform-java/java-showcase/gapic-showcase/pom.xml b/sdk-platform-java/java-showcase/gapic-showcase/pom.xml index 913925e02996..1117e759efb9 100644 --- a/sdk-platform-java/java-showcase/gapic-showcase/pom.xml +++ b/sdk-platform-java/java-showcase/gapic-showcase/pom.xml @@ -74,6 +74,16 @@ + + org.apache.maven.plugins + maven-failsafe-plugin + + + + **/ITActionableErrorsLogging.java + + + @@ -292,6 +302,7 @@ **/com/google/showcase/v1beta1/it/*.java **/com/google/showcase/v1beta1/it/logging/ITLoggingDisabled.java **/com/google/showcase/v1beta1/it/logging/ITLogging1x.java + **/com/google/showcase/v1beta1/it/logging/ITActionableErrorsLogging.java @@ -336,6 +347,7 @@ **/com/google/showcase/v1beta1/it/*.java **/com/google/showcase/v1beta1/it/logging/ITLoggingDisabled.java **/com/google/showcase/v1beta1/it/logging/ITLogging.java + **/com/google/showcase/v1beta1/it/logging/ITActionableErrorsLogging.java @@ -381,6 +393,7 @@ **/com/google/showcase/v1beta1/it/*.java **/com/google/showcase/v1beta1/it/logging/ITLogging1x.java **/com/google/showcase/v1beta1/it/logging/ITLogging.java + **/com/google/showcase/v1beta1/it/logging/ITActionableErrorsLogging.java @@ -406,6 +419,44 @@ + + envVarTest + + + org.slf4j + slf4j-api + test + + + + + + org.apache.maven.plugins + maven-compiler-plugin + + + + **/ITActionableErrorsLogging.java + + + + + org.apache.maven.plugins + maven-failsafe-plugin + + + + + **/ITActionableErrorsLogging.java + + + ${project.basedir}/src/test/slf4j-test-provider + + + + + + diff --git a/sdk-platform-java/java-showcase/gapic-showcase/src/test/java/com/google/showcase/v1beta1/it/logging/ITActionableErrorsLogging.java b/sdk-platform-java/java-showcase/gapic-showcase/src/test/java/com/google/showcase/v1beta1/it/logging/ITActionableErrorsLogging.java index bcfb91f47ed9..910ed08057e7 100644 --- a/sdk-platform-java/java-showcase/gapic-showcase/src/test/java/com/google/showcase/v1beta1/it/logging/ITActionableErrorsLogging.java +++ b/sdk-platform-java/java-showcase/gapic-showcase/src/test/java/com/google/showcase/v1beta1/it/logging/ITActionableErrorsLogging.java @@ -19,14 +19,13 @@ import static com.google.common.truth.Truth.assertThat; import static org.junit.jupiter.api.Assertions.assertThrows; -import ch.qos.logback.classic.Level; -import ch.qos.logback.classic.spi.ILoggingEvent; import com.google.api.client.http.LowLevelHttpRequest; import com.google.api.client.http.LowLevelHttpResponse; import com.google.api.client.testing.http.MockHttpTransport; import com.google.api.client.testing.http.MockLowLevelHttpRequest; import com.google.api.client.testing.http.MockLowLevelHttpResponse; import com.google.api.gax.core.NoCredentialsProvider; +import com.google.api.gax.logging.TestLogger; import com.google.api.gax.rpc.ApiException; import com.google.api.gax.tracing.LoggingTracerFactory; import com.google.protobuf.Any; @@ -37,31 +36,22 @@ import com.google.showcase.v1beta1.EchoSettings; import com.google.showcase.v1beta1.it.util.TestClientInitializer; import java.io.IOException; -import java.util.List; +import java.util.Map; import java.util.concurrent.TimeUnit; import org.junit.jupiter.api.AfterAll; import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.slf4j.LoggerFactory; -import org.slf4j.event.KeyValuePair; public class ITActionableErrorsLogging { private static EchoClient grpcClient; private static EchoClient httpjsonClient; + private TestLogger testLogger; @BeforeAll static void createClients() throws Exception { - try { - java.lang.reflect.Method m = - com.google.api.gax.logging.LoggingUtils.class.getDeclaredMethod( - "setLoggingEnabled", boolean.class); - m.setAccessible(true); - m.invoke(null, true); - } catch (Exception e) { - throw new RuntimeException(e); - } - grpcClient = TestClientInitializer.createGrpcEchoClientOpentelemetry(new LoggingTracerFactory()); httpjsonClient = @@ -76,24 +66,13 @@ static void destroyClients() throws InterruptedException { grpcClient.awaitTermination(TestClientInitializer.AWAIT_TERMINATION_SECONDS, TimeUnit.SECONDS); httpjsonClient.awaitTermination( TestClientInitializer.AWAIT_TERMINATION_SECONDS, TimeUnit.SECONDS); - try { - java.lang.reflect.Method m = - com.google.api.gax.logging.LoggingUtils.class.getDeclaredMethod( - "setLoggingEnabled", boolean.class); - m.setAccessible(true); - m.invoke(null, false); - } catch (Exception e) { - throw new RuntimeException(e); - } } - private TestAppender setupTestLogger() { - TestAppender testAppender = new TestAppender(); - testAppender.start(); - org.slf4j.Logger logger = LoggerFactory.getLogger("com.google.api.gax.tracing.LoggingTracer"); - ((ch.qos.logback.classic.Logger) logger).setLevel(Level.DEBUG); - ((ch.qos.logback.classic.Logger) logger).addAppender(testAppender); - return testAppender; + @BeforeEach + void setupTestLogger() { + testLogger = (TestLogger) LoggerFactory.getLogger("com.google.api.gax.tracing.LoggingTracer"); + testLogger.getMessageList().clear(); + testLogger.getKeyValuePairsMap().clear(); } private EchoRequest buildErrorRequest() { @@ -114,33 +93,26 @@ private EchoRequest buildErrorRequest() { @Test void testGrpc_actionableErrorLogged() { - TestAppender testAppender = setupTestLogger(); - EchoRequest request = buildErrorRequest(); - ApiException exception = assertThrows(ApiException.class, () -> grpcClient.echo(request)); - - assertThat(testAppender.events.size()).isAtLeast(1); - ILoggingEvent loggingEvent = testAppender.events.get(testAppender.events.size() - 1); + assertThrows(ApiException.class, () -> grpcClient.echo(request)); - assertThat(loggingEvent.getLevel()).isEqualTo(Level.DEBUG); - assertThat(loggingEvent.getMessage()).contains("This is a test error"); + assertThat(testLogger.getMessageList().size()).isAtLeast(1); + String loggedMessage = testLogger.getMessageList().get(testLogger.getMessageList().size() - 1); - List kvps = loggingEvent.getKeyValuePairs(); - assertThat(kvps).contains(new KeyValuePair("rpc.system.name", "grpc")); - assertThat(kvps).contains(new KeyValuePair("rpc.method", "google.showcase.v1beta1.Echo/Echo")); - assertThat(kvps).contains(new KeyValuePair("rpc.response.status_code", "INVALID_ARGUMENT")); - assertThat(kvps).contains(new KeyValuePair("error.type", "TEST_REASON")); - assertThat(kvps).contains(new KeyValuePair("gcp.errors.domain", "test.googleapis.com")); - assertThat(kvps).contains(new KeyValuePair("gcp.errors.metadata.test_metadata", "test_value")); + assertThat(loggedMessage).contains("This is a test error"); - testAppender.stop(); + Map kvps = testLogger.getKeyValuePairsMap(); + assertThat(kvps).containsEntry("rpc.system.name", "grpc"); + assertThat(kvps).containsEntry("rpc.method", "google.showcase.v1beta1.Echo/Echo"); + assertThat(kvps).containsEntry("rpc.response.status_code", "INVALID_ARGUMENT"); + assertThat(kvps).containsEntry("error.type", "TEST_REASON"); + assertThat(kvps).containsEntry("gcp.errors.domain", "test.googleapis.com"); + assertThat(kvps).containsEntry("gcp.errors.metadata.test_metadata", "test_value"); } @Test void testHttpJson_actionableErrorLogged() throws Exception { - TestAppender testAppender = setupTestLogger(); - // The gapic-showcase server currently returns text/plain for failEchoWithDetails instead of // JSON. // Additionally, sending an ErrorInfo in a request over REST fails serialization. @@ -199,26 +171,24 @@ public LowLevelHttpResponse execute() throws IOException { EchoRequest request = EchoRequest.newBuilder().build(); - ApiException exception = - assertThrows(ApiException.class, () -> mockHttpJsonClient.echo(request)); + assertThrows(ApiException.class, () -> mockHttpJsonClient.echo(request)); - assertThat(testAppender.events.size()).isAtLeast(1); - ILoggingEvent loggingEvent = testAppender.events.get(testAppender.events.size() - 1); + assertThat(testLogger.getMessageList().size()).isAtLeast(1); + String loggedMessage = testLogger.getMessageList().get(testLogger.getMessageList().size() - 1); - assertThat(loggingEvent.getLevel()).isEqualTo(Level.DEBUG); - assertThat(loggingEvent.getMessage()) - .contains("This is a mock JSON error generated by the server"); + assertThat(loggedMessage).contains("This is a mock JSON error generated by the server"); - List kvps = loggingEvent.getKeyValuePairs(); - assertThat(kvps).contains(new KeyValuePair("rpc.system.name", "http")); - assertThat(kvps).contains(new KeyValuePair("http.request.method", "POST")); - assertThat(kvps).contains(new KeyValuePair("url.template", "v1beta1/echo:echo")); - assertThat(kvps).contains(new KeyValuePair("rpc.response.status_code", "ABORTED")); - assertThat(kvps).contains(new KeyValuePair("error.type", "mock_error_reason")); - assertThat(kvps).contains(new KeyValuePair("gcp.errors.domain", "mock.googleapis.com")); - assertThat(kvps).contains(new KeyValuePair("gcp.errors.metadata.mock_key", "mock_value")); + Map kvps = testLogger.getKeyValuePairsMap(); + assertThat(kvps).containsEntry("rpc.system.name", "http"); + assertThat(kvps).containsEntry("http.request.method", "POST"); + assertThat(kvps).containsEntry("url.template", "v1beta1/echo:echo"); + assertThat(kvps).containsEntry("rpc.response.status_code", "ABORTED"); + assertThat(kvps).containsEntry("error.type", "mock_error_reason"); + assertThat(kvps).containsEntry("gcp.errors.domain", "mock.googleapis.com"); + assertThat(kvps).containsEntry("gcp.errors.metadata.mock_key", "mock_value"); mockHttpJsonClient.close(); - testAppender.stop(); + mockHttpJsonClient.awaitTermination( + TestClientInitializer.AWAIT_TERMINATION_SECONDS, TimeUnit.SECONDS); } } diff --git a/sdk-platform-java/java-showcase/gapic-showcase/src/test/slf4j-test-provider/META-INF/services/org.slf4j.spi.SLF4JServiceProvider b/sdk-platform-java/java-showcase/gapic-showcase/src/test/slf4j-test-provider/META-INF/services/org.slf4j.spi.SLF4JServiceProvider new file mode 100644 index 000000000000..b97d560115b5 --- /dev/null +++ b/sdk-platform-java/java-showcase/gapic-showcase/src/test/slf4j-test-provider/META-INF/services/org.slf4j.spi.SLF4JServiceProvider @@ -0,0 +1 @@ +com.google.api.gax.logging.TestServiceProvider diff --git a/sdk-platform-java/java-showcase/pom.xml b/sdk-platform-java/java-showcase/pom.xml index a241e7677e03..41efc38e5311 100644 --- a/sdk-platform-java/java-showcase/pom.xml +++ b/sdk-platform-java/java-showcase/pom.xml @@ -35,6 +35,11 @@ pom import + + org.slf4j + slf4j-api + 2.0.16 + com.google.api.grpc proto-gapic-showcase-v1beta1 From 1c338aaa455f2ea34f476d5c0c4dbf73b193c54f Mon Sep 17 00:00:00 2001 From: Wes Tarle Date: Thu, 2 Apr 2026 11:47:22 -0400 Subject: [PATCH 03/12] fix(java-showcase): Fix ITActionableErrorsLogging environment variable and classpath --- .../java-showcase/gapic-showcase/pom.xml | 7 ++ .../it/logging/ITActionableErrorsLogging.java | 107 +++++++++++++----- 2 files changed, 85 insertions(+), 29 deletions(-) diff --git a/sdk-platform-java/java-showcase/gapic-showcase/pom.xml b/sdk-platform-java/java-showcase/gapic-showcase/pom.xml index 1117e759efb9..aeabc599725a 100644 --- a/sdk-platform-java/java-showcase/gapic-showcase/pom.xml +++ b/sdk-platform-java/java-showcase/gapic-showcase/pom.xml @@ -452,6 +452,13 @@ ${project.basedir}/src/test/slf4j-test-provider + + ch.qos.logback:logback-classic + ch.qos.logback:logback-core + + + true + diff --git a/sdk-platform-java/java-showcase/gapic-showcase/src/test/java/com/google/showcase/v1beta1/it/logging/ITActionableErrorsLogging.java b/sdk-platform-java/java-showcase/gapic-showcase/src/test/java/com/google/showcase/v1beta1/it/logging/ITActionableErrorsLogging.java index 910ed08057e7..b633f263cd80 100644 --- a/sdk-platform-java/java-showcase/gapic-showcase/src/test/java/com/google/showcase/v1beta1/it/logging/ITActionableErrorsLogging.java +++ b/sdk-platform-java/java-showcase/gapic-showcase/src/test/java/com/google/showcase/v1beta1/it/logging/ITActionableErrorsLogging.java @@ -92,32 +92,7 @@ private EchoRequest buildErrorRequest() { } @Test - void testGrpc_actionableErrorLogged() { - EchoRequest request = buildErrorRequest(); - - assertThrows(ApiException.class, () -> grpcClient.echo(request)); - - assertThat(testLogger.getMessageList().size()).isAtLeast(1); - String loggedMessage = testLogger.getMessageList().get(testLogger.getMessageList().size() - 1); - - assertThat(loggedMessage).contains("This is a test error"); - - Map kvps = testLogger.getKeyValuePairsMap(); - assertThat(kvps).containsEntry("rpc.system.name", "grpc"); - assertThat(kvps).containsEntry("rpc.method", "google.showcase.v1beta1.Echo/Echo"); - assertThat(kvps).containsEntry("rpc.response.status_code", "INVALID_ARGUMENT"); - assertThat(kvps).containsEntry("error.type", "TEST_REASON"); - assertThat(kvps).containsEntry("gcp.errors.domain", "test.googleapis.com"); - assertThat(kvps).containsEntry("gcp.errors.metadata.test_metadata", "test_value"); - } - - @Test - void testHttpJson_actionableErrorLogged() throws Exception { - // The gapic-showcase server currently returns text/plain for failEchoWithDetails instead of - // JSON. - // Additionally, sending an ErrorInfo in a request over REST fails serialization. - // To test HTTP JSON actionable errors logic, we use a MockHttpTransport that simulates the - // correct JSON format. + void testHttpJson_logEmittedForLowLevelRequestFailure() throws Exception { MockHttpTransport mockTransport = new MockHttpTransport() { @Override @@ -170,7 +145,6 @@ public LowLevelHttpResponse execute() throws IOException { EchoClient mockHttpJsonClient = EchoClient.create(stub); EchoRequest request = EchoRequest.newBuilder().build(); - assertThrows(ApiException.class, () -> mockHttpJsonClient.echo(request)); assertThat(testLogger.getMessageList().size()).isAtLeast(1); @@ -188,7 +162,82 @@ public LowLevelHttpResponse execute() throws IOException { assertThat(kvps).containsEntry("gcp.errors.metadata.mock_key", "mock_value"); mockHttpJsonClient.close(); - mockHttpJsonClient.awaitTermination( - TestClientInitializer.AWAIT_TERMINATION_SECONDS, TimeUnit.SECONDS); + mockHttpJsonClient.awaitTermination(TestClientInitializer.AWAIT_TERMINATION_SECONDS, TimeUnit.SECONDS); + } + + @Test + void testHttpJson_noLogEmittedForSuccess() { + EchoRequest request = EchoRequest.newBuilder().setContent("Success").build(); + httpjsonClient.echo(request); + assertThat(testLogger.getMessageList().size()).isEqualTo(0); + } + + @Test + void testHttpJson_clientLevelFailureAttributes() throws Exception { + com.google.showcase.v1beta1.stub.EchoStubSettings.Builder stubSettingsBuilder = + com.google.showcase.v1beta1.stub.EchoStubSettings.newHttpJsonBuilder(); + stubSettingsBuilder.echoSettings().setRetrySettings( + com.google.api.gax.retrying.RetrySettings.newBuilder() + .setInitialRpcTimeoutDuration(java.time.Duration.ofMillis(0)) + .setTotalTimeoutDuration(java.time.Duration.ofMillis(0)) + .setMaxAttempts(1) + .build()); + stubSettingsBuilder.setTracerFactory(new LoggingTracerFactory()); + stubSettingsBuilder.setEndpoint(TestClientInitializer.DEFAULT_HTTPJSON_ENDPOINT); + + try (com.google.showcase.v1beta1.stub.EchoStub stub = stubSettingsBuilder.build().createStub(); + EchoClient client = EchoClient.create(stub)) { + assertThrows(ApiException.class, () -> client.echo(EchoRequest.newBuilder().build())); + assertThat(testLogger.getMessageList().size()).isAtLeast(1); + Map kvps = testLogger.getKeyValuePairsMap(); + assertThat(kvps).containsEntry("rpc.system.name", "http"); + } + } + + @Test + void testGrpc_logEmittedForLowLevelRequestFailure() { + EchoRequest request = buildErrorRequest(); + assertThrows(ApiException.class, () -> grpcClient.echo(request)); + + assertThat(testLogger.getMessageList().size()).isAtLeast(1); + String loggedMessage = testLogger.getMessageList().get(testLogger.getMessageList().size() - 1); + assertThat(loggedMessage).contains("This is a test error"); + + Map kvps = testLogger.getKeyValuePairsMap(); + assertThat(kvps).containsEntry("rpc.system.name", "grpc"); + assertThat(kvps).containsEntry("rpc.method", "google.showcase.v1beta1.Echo/Echo"); + assertThat(kvps).containsEntry("rpc.response.status_code", "INVALID_ARGUMENT"); + assertThat(kvps).containsEntry("error.type", "TEST_REASON"); + assertThat(kvps).containsEntry("gcp.errors.domain", "test.googleapis.com"); + assertThat(kvps).containsEntry("gcp.errors.metadata.test_metadata", "test_value"); + } + + @Test + void testGrpc_noLogEmittedForSuccess() { + EchoRequest request = EchoRequest.newBuilder().setContent("Success").build(); + grpcClient.echo(request); + assertThat(testLogger.getMessageList().size()).isEqualTo(0); + } + + @Test + void testGrpc_clientLevelFailureAttributes() throws Exception { + com.google.showcase.v1beta1.stub.EchoStubSettings.Builder stubSettingsBuilder = + com.google.showcase.v1beta1.stub.EchoStubSettings.newBuilder(); + stubSettingsBuilder.echoSettings().setRetrySettings( + com.google.api.gax.retrying.RetrySettings.newBuilder() + .setInitialRpcTimeoutDuration(java.time.Duration.ofMillis(0)) + .setTotalTimeoutDuration(java.time.Duration.ofMillis(0)) + .setMaxAttempts(1) + .build()); + stubSettingsBuilder.setTracerFactory(new LoggingTracerFactory()); + stubSettingsBuilder.setEndpoint(TestClientInitializer.DEFAULT_GRPC_ENDPOINT); + + try (com.google.showcase.v1beta1.stub.EchoStub stub = stubSettingsBuilder.build().createStub(); + EchoClient client = EchoClient.create(stub)) { + assertThrows(ApiException.class, () -> client.echo(EchoRequest.newBuilder().build())); + assertThat(testLogger.getMessageList().size()).isAtLeast(1); + Map kvps = testLogger.getKeyValuePairsMap(); + assertThat(kvps).containsEntry("rpc.system.name", "grpc"); + } } } From 7a927d6c0b6266f384c3d2335833def691635bd5 Mon Sep 17 00:00:00 2001 From: Wes Tarle Date: Fri, 3 Apr 2026 00:02:51 -0400 Subject: [PATCH 04/12] test(logging): address PR review feedback - Removed the `envVarTest` profile and reused the existing `slf4j2_logback` profile for running the actionable error logs test. - Refactored `ITActionableErrorsLogging` to use `TestAppender` to align with existing test patterns in `ITLogging`. - Replaced hardcoded observability attribute string literals with static constants from `ObservabilityAttributes`. --- .../java-showcase/gapic-showcase/pom.xml | 56 --------- .../it/logging/ITActionableErrorsLogging.java | 109 ++++++++++++------ 2 files changed, 73 insertions(+), 92 deletions(-) diff --git a/sdk-platform-java/java-showcase/gapic-showcase/pom.xml b/sdk-platform-java/java-showcase/gapic-showcase/pom.xml index aeabc599725a..f084a4611f5e 100644 --- a/sdk-platform-java/java-showcase/gapic-showcase/pom.xml +++ b/sdk-platform-java/java-showcase/gapic-showcase/pom.xml @@ -74,16 +74,6 @@ - - org.apache.maven.plugins - maven-failsafe-plugin - - - - **/ITActionableErrorsLogging.java - - - @@ -302,7 +292,6 @@ **/com/google/showcase/v1beta1/it/*.java **/com/google/showcase/v1beta1/it/logging/ITLoggingDisabled.java **/com/google/showcase/v1beta1/it/logging/ITLogging1x.java - **/com/google/showcase/v1beta1/it/logging/ITActionableErrorsLogging.java @@ -419,51 +408,6 @@ - - envVarTest - - - org.slf4j - slf4j-api - test - - - - - - org.apache.maven.plugins - maven-compiler-plugin - - - - **/ITActionableErrorsLogging.java - - - - - org.apache.maven.plugins - maven-failsafe-plugin - - - - - **/ITActionableErrorsLogging.java - - - ${project.basedir}/src/test/slf4j-test-provider - - - ch.qos.logback:logback-classic - ch.qos.logback:logback-core - - - true - - - - - - diff --git a/sdk-platform-java/java-showcase/gapic-showcase/src/test/java/com/google/showcase/v1beta1/it/logging/ITActionableErrorsLogging.java b/sdk-platform-java/java-showcase/gapic-showcase/src/test/java/com/google/showcase/v1beta1/it/logging/ITActionableErrorsLogging.java index b633f263cd80..9979abfe977a 100644 --- a/sdk-platform-java/java-showcase/gapic-showcase/src/test/java/com/google/showcase/v1beta1/it/logging/ITActionableErrorsLogging.java +++ b/sdk-platform-java/java-showcase/gapic-showcase/src/test/java/com/google/showcase/v1beta1/it/logging/ITActionableErrorsLogging.java @@ -19,15 +19,17 @@ import static com.google.common.truth.Truth.assertThat; import static org.junit.jupiter.api.Assertions.assertThrows; +import ch.qos.logback.classic.Level; +import ch.qos.logback.classic.spi.ILoggingEvent; import com.google.api.client.http.LowLevelHttpRequest; import com.google.api.client.http.LowLevelHttpResponse; import com.google.api.client.testing.http.MockHttpTransport; import com.google.api.client.testing.http.MockLowLevelHttpRequest; import com.google.api.client.testing.http.MockLowLevelHttpResponse; import com.google.api.gax.core.NoCredentialsProvider; -import com.google.api.gax.logging.TestLogger; import com.google.api.gax.rpc.ApiException; import com.google.api.gax.tracing.LoggingTracerFactory; +import com.google.api.gax.tracing.ObservabilityAttributes; import com.google.protobuf.Any; import com.google.rpc.ErrorInfo; import com.google.rpc.Status; @@ -36,19 +38,22 @@ import com.google.showcase.v1beta1.EchoSettings; import com.google.showcase.v1beta1.it.util.TestClientInitializer; import java.io.IOException; +import java.util.HashMap; import java.util.Map; import java.util.concurrent.TimeUnit; import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.slf4j.LoggerFactory; +import org.slf4j.event.KeyValuePair; public class ITActionableErrorsLogging { private static EchoClient grpcClient; private static EchoClient httpjsonClient; - private TestLogger testLogger; + private TestAppender testAppender; @BeforeAll static void createClients() throws Exception { @@ -68,11 +73,36 @@ static void destroyClients() throws InterruptedException { TestClientInitializer.AWAIT_TERMINATION_SECONDS, TimeUnit.SECONDS); } + private TestAppender setupTestLogger(String loggerName, Level level) { + TestAppender appender = new TestAppender(); + appender.start(); + org.slf4j.Logger logger = LoggerFactory.getLogger(loggerName); + ((ch.qos.logback.classic.Logger) logger).setLevel(level); + ((ch.qos.logback.classic.Logger) logger).addAppender(appender); + return appender; + } + @BeforeEach void setupTestLogger() { - testLogger = (TestLogger) LoggerFactory.getLogger("com.google.api.gax.tracing.LoggingTracer"); - testLogger.getMessageList().clear(); - testLogger.getKeyValuePairsMap().clear(); + testAppender = setupTestLogger("com.google.api.gax.tracing.LoggingTracer", Level.DEBUG); + testAppender.clearEvents(); + } + + @AfterEach + void teardownTestLogger() { + if (testAppender != null) { + testAppender.stop(); + } + } + + private Map getKvps(ILoggingEvent loggingEvent) { + Map map = new HashMap<>(); + if (loggingEvent.getKeyValuePairs() != null) { + for (KeyValuePair kvp : loggingEvent.getKeyValuePairs()) { + map.put(kvp.key, kvp.value); + } + } + return map; } private EchoRequest buildErrorRequest() { @@ -147,19 +177,21 @@ public LowLevelHttpResponse execute() throws IOException { EchoRequest request = EchoRequest.newBuilder().build(); assertThrows(ApiException.class, () -> mockHttpJsonClient.echo(request)); - assertThat(testLogger.getMessageList().size()).isAtLeast(1); - String loggedMessage = testLogger.getMessageList().get(testLogger.getMessageList().size() - 1); + assertThat(testAppender.events.size()).isAtLeast(1); + ILoggingEvent loggingEvent = testAppender.events.get(testAppender.events.size() - 1); - assertThat(loggedMessage).contains("This is a mock JSON error generated by the server"); + assertThat(loggingEvent.getMessage()).contains("This is a mock JSON error generated by the server"); - Map kvps = testLogger.getKeyValuePairsMap(); - assertThat(kvps).containsEntry("rpc.system.name", "http"); - assertThat(kvps).containsEntry("http.request.method", "POST"); - assertThat(kvps).containsEntry("url.template", "v1beta1/echo:echo"); - assertThat(kvps).containsEntry("rpc.response.status_code", "ABORTED"); - assertThat(kvps).containsEntry("error.type", "mock_error_reason"); - assertThat(kvps).containsEntry("gcp.errors.domain", "mock.googleapis.com"); - assertThat(kvps).containsEntry("gcp.errors.metadata.mock_key", "mock_value"); + Map kvps = getKvps(loggingEvent); + assertThat(kvps).containsEntry(ObservabilityAttributes.RPC_SYSTEM_NAME_ATTRIBUTE, "http"); + assertThat(kvps).containsEntry(ObservabilityAttributes.HTTP_METHOD_ATTRIBUTE, "POST"); + assertThat(kvps).containsEntry(ObservabilityAttributes.HTTP_URL_TEMPLATE_ATTRIBUTE, "v1beta1/echo:echo"); + assertThat(kvps).containsEntry(ObservabilityAttributes.RPC_RESPONSE_STATUS_ATTRIBUTE, "ABORTED"); + assertThat(kvps).containsEntry(ObservabilityAttributes.ERROR_TYPE_ATTRIBUTE, "mock_error_reason"); + assertThat(kvps).containsEntry(ObservabilityAttributes.ERROR_DOMAIN_ATTRIBUTE, "mock.googleapis.com"); + assertThat(kvps) + .containsEntry( + ObservabilityAttributes.ERROR_METADATA_ATTRIBUTE_PREFIX + "mock_key", "mock_value"); mockHttpJsonClient.close(); mockHttpJsonClient.awaitTermination(TestClientInitializer.AWAIT_TERMINATION_SECONDS, TimeUnit.SECONDS); @@ -169,7 +201,7 @@ public LowLevelHttpResponse execute() throws IOException { void testHttpJson_noLogEmittedForSuccess() { EchoRequest request = EchoRequest.newBuilder().setContent("Success").build(); httpjsonClient.echo(request); - assertThat(testLogger.getMessageList().size()).isEqualTo(0); + assertThat(testAppender.events.size()).isEqualTo(0); } @Test @@ -188,9 +220,10 @@ void testHttpJson_clientLevelFailureAttributes() throws Exception { try (com.google.showcase.v1beta1.stub.EchoStub stub = stubSettingsBuilder.build().createStub(); EchoClient client = EchoClient.create(stub)) { assertThrows(ApiException.class, () -> client.echo(EchoRequest.newBuilder().build())); - assertThat(testLogger.getMessageList().size()).isAtLeast(1); - Map kvps = testLogger.getKeyValuePairsMap(); - assertThat(kvps).containsEntry("rpc.system.name", "http"); + assertThat(testAppender.events.size()).isAtLeast(1); + ILoggingEvent loggingEvent = testAppender.events.get(testAppender.events.size() - 1); + Map kvps = getKvps(loggingEvent); + assertThat(kvps).containsEntry(ObservabilityAttributes.RPC_SYSTEM_NAME_ATTRIBUTE, "http"); } } @@ -199,24 +232,27 @@ void testGrpc_logEmittedForLowLevelRequestFailure() { EchoRequest request = buildErrorRequest(); assertThrows(ApiException.class, () -> grpcClient.echo(request)); - assertThat(testLogger.getMessageList().size()).isAtLeast(1); - String loggedMessage = testLogger.getMessageList().get(testLogger.getMessageList().size() - 1); - assertThat(loggedMessage).contains("This is a test error"); - - Map kvps = testLogger.getKeyValuePairsMap(); - assertThat(kvps).containsEntry("rpc.system.name", "grpc"); - assertThat(kvps).containsEntry("rpc.method", "google.showcase.v1beta1.Echo/Echo"); - assertThat(kvps).containsEntry("rpc.response.status_code", "INVALID_ARGUMENT"); - assertThat(kvps).containsEntry("error.type", "TEST_REASON"); - assertThat(kvps).containsEntry("gcp.errors.domain", "test.googleapis.com"); - assertThat(kvps).containsEntry("gcp.errors.metadata.test_metadata", "test_value"); + assertThat(testAppender.events.size()).isAtLeast(1); + ILoggingEvent loggingEvent = testAppender.events.get(testAppender.events.size() - 1); + assertThat(loggingEvent.getMessage()).contains("This is a test error"); + + Map kvps = getKvps(loggingEvent); + assertThat(kvps).containsEntry(ObservabilityAttributes.RPC_SYSTEM_NAME_ATTRIBUTE, "grpc"); + assertThat(kvps) + .containsEntry(ObservabilityAttributes.GRPC_RPC_METHOD_ATTRIBUTE, "google.showcase.v1beta1.Echo/Echo"); + assertThat(kvps).containsEntry(ObservabilityAttributes.RPC_RESPONSE_STATUS_ATTRIBUTE, "INVALID_ARGUMENT"); + assertThat(kvps).containsEntry(ObservabilityAttributes.ERROR_TYPE_ATTRIBUTE, "TEST_REASON"); + assertThat(kvps).containsEntry(ObservabilityAttributes.ERROR_DOMAIN_ATTRIBUTE, "test.googleapis.com"); + assertThat(kvps) + .containsEntry( + ObservabilityAttributes.ERROR_METADATA_ATTRIBUTE_PREFIX + "test_metadata", "test_value"); } @Test void testGrpc_noLogEmittedForSuccess() { EchoRequest request = EchoRequest.newBuilder().setContent("Success").build(); grpcClient.echo(request); - assertThat(testLogger.getMessageList().size()).isEqualTo(0); + assertThat(testAppender.events.size()).isEqualTo(0); } @Test @@ -235,9 +271,10 @@ void testGrpc_clientLevelFailureAttributes() throws Exception { try (com.google.showcase.v1beta1.stub.EchoStub stub = stubSettingsBuilder.build().createStub(); EchoClient client = EchoClient.create(stub)) { assertThrows(ApiException.class, () -> client.echo(EchoRequest.newBuilder().build())); - assertThat(testLogger.getMessageList().size()).isAtLeast(1); - Map kvps = testLogger.getKeyValuePairsMap(); - assertThat(kvps).containsEntry("rpc.system.name", "grpc"); + assertThat(testAppender.events.size()).isAtLeast(1); + ILoggingEvent loggingEvent = testAppender.events.get(testAppender.events.size() - 1); + Map kvps = getKvps(loggingEvent); + assertThat(kvps).containsEntry(ObservabilityAttributes.RPC_SYSTEM_NAME_ATTRIBUTE, "grpc"); } } -} +} \ No newline at end of file From 2662618083a441252e190ab795b19b8557fba282 Mon Sep 17 00:00:00 2001 From: Wes Tarle Date: Fri, 3 Apr 2026 00:22:02 -0400 Subject: [PATCH 05/12] test(logging): revert unnecessary slf4j-api dependencyManagement Remove `slf4j-api` from `sdk-platform-java/java-showcase/pom.xml` dependency management, as the versions are already explicitly managed within the `gapic-showcase/pom.xml` profiles and base dependencies. --- sdk-platform-java/java-showcase/pom.xml | 5 ----- 1 file changed, 5 deletions(-) diff --git a/sdk-platform-java/java-showcase/pom.xml b/sdk-platform-java/java-showcase/pom.xml index 41efc38e5311..a241e7677e03 100644 --- a/sdk-platform-java/java-showcase/pom.xml +++ b/sdk-platform-java/java-showcase/pom.xml @@ -35,11 +35,6 @@ pom import - - org.slf4j - slf4j-api - 2.0.16 - com.google.api.grpc proto-gapic-showcase-v1beta1 From 77344cac430a30d15901f6e8cf9da6e327e7fdee Mon Sep 17 00:00:00 2001 From: Wes Tarle Date: Fri, 3 Apr 2026 00:30:06 -0400 Subject: [PATCH 06/12] test(logging): remove obsolete slf4j-test-provider from java-showcase Since `ITActionableErrorsLogging` now utilizes Logback's `TestAppender` natively and the custom `envVarTest` profile was removed, the separate `slf4j-test-provider` directory is entirely orphaned and no longer necessary. --- .../META-INF/services/org.slf4j.spi.SLF4JServiceProvider | 1 - 1 file changed, 1 deletion(-) delete mode 100644 sdk-platform-java/java-showcase/gapic-showcase/src/test/slf4j-test-provider/META-INF/services/org.slf4j.spi.SLF4JServiceProvider diff --git a/sdk-platform-java/java-showcase/gapic-showcase/src/test/slf4j-test-provider/META-INF/services/org.slf4j.spi.SLF4JServiceProvider b/sdk-platform-java/java-showcase/gapic-showcase/src/test/slf4j-test-provider/META-INF/services/org.slf4j.spi.SLF4JServiceProvider deleted file mode 100644 index b97d560115b5..000000000000 --- a/sdk-platform-java/java-showcase/gapic-showcase/src/test/slf4j-test-provider/META-INF/services/org.slf4j.spi.SLF4JServiceProvider +++ /dev/null @@ -1 +0,0 @@ -com.google.api.gax.logging.TestServiceProvider From 2258e7f9bd915838ca8c2e4925b28a38e5d8e0d4 Mon Sep 17 00:00:00 2001 From: Wes Tarle Date: Fri, 3 Apr 2026 00:35:23 -0400 Subject: [PATCH 07/12] newline --- .../showcase/v1beta1/it/logging/ITActionableErrorsLogging.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sdk-platform-java/java-showcase/gapic-showcase/src/test/java/com/google/showcase/v1beta1/it/logging/ITActionableErrorsLogging.java b/sdk-platform-java/java-showcase/gapic-showcase/src/test/java/com/google/showcase/v1beta1/it/logging/ITActionableErrorsLogging.java index 9979abfe977a..c68fcbc5594e 100644 --- a/sdk-platform-java/java-showcase/gapic-showcase/src/test/java/com/google/showcase/v1beta1/it/logging/ITActionableErrorsLogging.java +++ b/sdk-platform-java/java-showcase/gapic-showcase/src/test/java/com/google/showcase/v1beta1/it/logging/ITActionableErrorsLogging.java @@ -277,4 +277,4 @@ void testGrpc_clientLevelFailureAttributes() throws Exception { assertThat(kvps).containsEntry(ObservabilityAttributes.RPC_SYSTEM_NAME_ATTRIBUTE, "grpc"); } } -} \ No newline at end of file +} From 7dfa31cedc1b399a5ded7c5c887da7650a077ca1 Mon Sep 17 00:00:00 2001 From: Wes Tarle Date: Fri, 3 Apr 2026 13:14:30 -0400 Subject: [PATCH 08/12] test(gax): revert unnecessary test-jar inclusions Since the `gapic-showcase` integration test now utilizes Logback's `TestAppender` natively and the custom `envVarTest` profile in the POM was removed, there is no longer a need to expose internal GAX test classes via the `test-jar`. --- sdk-platform-java/gax-java/gax/pom.xml | 1 - 1 file changed, 1 deletion(-) diff --git a/sdk-platform-java/gax-java/gax/pom.xml b/sdk-platform-java/gax-java/gax/pom.xml index 3af8a0c05480..9c2589279b88 100644 --- a/sdk-platform-java/gax-java/gax/pom.xml +++ b/sdk-platform-java/gax-java/gax/pom.xml @@ -115,7 +115,6 @@ com/google/api/gax/rpc/testing/** com/google/api/gax/rpc/mtls/** com/google/api/gax/util/** - com/google/api/gax/logging/** **/native-image.properties From 85e272d1c48d3c63be7c844d442ba4d26f1dad28 Mon Sep 17 00:00:00 2001 From: Wes Tarle Date: Fri, 3 Apr 2026 13:42:08 -0400 Subject: [PATCH 09/12] test(logging): fix missing credentials in Actionable Errors tests Added `NoCredentialsProvider.create()` to the `stubSettingsBuilder` in `testHttpJson_clientLevelFailureAttributes` and `testGrpc_clientLevelFailureAttributes` to prevent test failures in environments without Application Default Credentials. --- .../showcase/v1beta1/it/logging/ITActionableErrorsLogging.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/sdk-platform-java/java-showcase/gapic-showcase/src/test/java/com/google/showcase/v1beta1/it/logging/ITActionableErrorsLogging.java b/sdk-platform-java/java-showcase/gapic-showcase/src/test/java/com/google/showcase/v1beta1/it/logging/ITActionableErrorsLogging.java index c68fcbc5594e..8689f91a2c18 100644 --- a/sdk-platform-java/java-showcase/gapic-showcase/src/test/java/com/google/showcase/v1beta1/it/logging/ITActionableErrorsLogging.java +++ b/sdk-platform-java/java-showcase/gapic-showcase/src/test/java/com/google/showcase/v1beta1/it/logging/ITActionableErrorsLogging.java @@ -215,6 +215,7 @@ void testHttpJson_clientLevelFailureAttributes() throws Exception { .setMaxAttempts(1) .build()); stubSettingsBuilder.setTracerFactory(new LoggingTracerFactory()); + stubSettingsBuilder.setCredentialsProvider(NoCredentialsProvider.create()); stubSettingsBuilder.setEndpoint(TestClientInitializer.DEFAULT_HTTPJSON_ENDPOINT); try (com.google.showcase.v1beta1.stub.EchoStub stub = stubSettingsBuilder.build().createStub(); @@ -266,6 +267,7 @@ void testGrpc_clientLevelFailureAttributes() throws Exception { .setMaxAttempts(1) .build()); stubSettingsBuilder.setTracerFactory(new LoggingTracerFactory()); + stubSettingsBuilder.setCredentialsProvider(NoCredentialsProvider.create()); stubSettingsBuilder.setEndpoint(TestClientInitializer.DEFAULT_GRPC_ENDPOINT); try (com.google.showcase.v1beta1.stub.EchoStub stub = stubSettingsBuilder.build().createStub(); From cd0d671d8387e671c4ee846652e01d4b2c4e596a Mon Sep 17 00:00:00 2001 From: Wes Tarle Date: Fri, 3 Apr 2026 17:46:28 -0400 Subject: [PATCH 10/12] test(logging): fix missing exception in clientLevelFailureAttributes tests Changed the endpoint for `testHttpJson_clientLevelFailureAttributes` and `testGrpc_clientLevelFailureAttributes` to `localhost:1` instead of `DEFAULT_HTTPJSON_ENDPOINT` and `DEFAULT_GRPC_ENDPOINT`. Since the showcase server is running during integration tests, sending an empty `EchoRequest` to the default endpoint succeeds without throwing an `ApiException`, causing the `assertThrows` assertion to fail. By pointing to a bad endpoint, we ensure a network exception is always thrown and the client-level failure attributes are properly populated and logged. --- .../v1beta1/it/logging/ITActionableErrorsLogging.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sdk-platform-java/java-showcase/gapic-showcase/src/test/java/com/google/showcase/v1beta1/it/logging/ITActionableErrorsLogging.java b/sdk-platform-java/java-showcase/gapic-showcase/src/test/java/com/google/showcase/v1beta1/it/logging/ITActionableErrorsLogging.java index 8689f91a2c18..ec92863cba12 100644 --- a/sdk-platform-java/java-showcase/gapic-showcase/src/test/java/com/google/showcase/v1beta1/it/logging/ITActionableErrorsLogging.java +++ b/sdk-platform-java/java-showcase/gapic-showcase/src/test/java/com/google/showcase/v1beta1/it/logging/ITActionableErrorsLogging.java @@ -216,7 +216,7 @@ void testHttpJson_clientLevelFailureAttributes() throws Exception { .build()); stubSettingsBuilder.setTracerFactory(new LoggingTracerFactory()); stubSettingsBuilder.setCredentialsProvider(NoCredentialsProvider.create()); - stubSettingsBuilder.setEndpoint(TestClientInitializer.DEFAULT_HTTPJSON_ENDPOINT); + stubSettingsBuilder.setEndpoint("localhost:1"); try (com.google.showcase.v1beta1.stub.EchoStub stub = stubSettingsBuilder.build().createStub(); EchoClient client = EchoClient.create(stub)) { @@ -268,7 +268,7 @@ void testGrpc_clientLevelFailureAttributes() throws Exception { .build()); stubSettingsBuilder.setTracerFactory(new LoggingTracerFactory()); stubSettingsBuilder.setCredentialsProvider(NoCredentialsProvider.create()); - stubSettingsBuilder.setEndpoint(TestClientInitializer.DEFAULT_GRPC_ENDPOINT); + stubSettingsBuilder.setEndpoint("localhost:1"); try (com.google.showcase.v1beta1.stub.EchoStub stub = stubSettingsBuilder.build().createStub(); EchoClient client = EchoClient.create(stub)) { From b22433daf9970d3f356bfead85286d7af28dd9e5 Mon Sep 17 00:00:00 2001 From: Wes Tarle Date: Sat, 4 Apr 2026 01:05:19 -0400 Subject: [PATCH 11/12] style: apply fmt-maven-plugin formatting --- .../v1beta1/it/ITOtelGoldenMetrics.java | 55 +++++++++------- .../v1beta1/it/ITOtelTracePropagation.java | 23 ++++--- .../it/logging/ITActionableErrorsLogging.java | 62 ++++++++++++------- .../it/util/TestClientInitializer.java | 5 +- 4 files changed, 87 insertions(+), 58 deletions(-) diff --git a/sdk-platform-java/java-showcase/gapic-showcase/src/test/java/com/google/showcase/v1beta1/it/ITOtelGoldenMetrics.java b/sdk-platform-java/java-showcase/gapic-showcase/src/test/java/com/google/showcase/v1beta1/it/ITOtelGoldenMetrics.java index 70f86141f6c5..42d69873f78d 100644 --- a/sdk-platform-java/java-showcase/gapic-showcase/src/test/java/com/google/showcase/v1beta1/it/ITOtelGoldenMetrics.java +++ b/sdk-platform-java/java-showcase/gapic-showcase/src/test/java/com/google/showcase/v1beta1/it/ITOtelGoldenMetrics.java @@ -35,16 +35,13 @@ import com.google.api.client.http.HttpTransport; import com.google.api.gax.core.NoCredentialsProvider; -import com.google.api.gax.rpc.StatusCode; import com.google.api.gax.rpc.TransportChannelProvider; import com.google.api.gax.rpc.UnavailableException; import com.google.api.gax.tracing.GoldenSignalsMetricsTracerFactory; import com.google.api.gax.tracing.ObservabilityAttributes; import com.google.common.collect.ImmutableList; -import com.google.rpc.Status; import com.google.showcase.v1beta1.EchoClient; import com.google.showcase.v1beta1.EchoRequest; -import com.google.showcase.v1beta1.EchoResponse; import com.google.showcase.v1beta1.EchoSettings; import com.google.showcase.v1beta1.it.util.TestClientInitializer; import com.google.showcase.v1beta1.stub.EchoStubSettings; @@ -52,8 +49,8 @@ import io.grpc.Channel; import io.grpc.ClientCall; import io.grpc.ClientInterceptor; -import io.grpc.MethodDescriptor; import io.grpc.Metadata; +import io.grpc.MethodDescriptor; import io.opentelemetry.api.common.AttributeKey; import io.opentelemetry.sdk.OpenTelemetrySdk; import io.opentelemetry.sdk.metrics.SdkMeterProvider; @@ -103,7 +100,8 @@ void testMetrics_successfulEcho_grpc() throws Exception { // The end of an operation is tracked in a separate thread. // Add a small sleep to make sure the tracking is completed. - // This is implemented by adding a TraceFinisher to ApiFuture as a callback in TracedUnaryCallable, + // This is implemented by adding a TraceFinisher to ApiFuture as a callback in + // TracedUnaryCallable, // which could be executed in a different thread. Thread.sleep(100); Collection metrics = metricReader.collectAllMetrics(); @@ -122,22 +120,27 @@ void testMetrics_successfulEcho_grpc() throws Exception { durationMetric.getHistogramData().getPoints().iterator().next().getAttributes(); assertThat( - attributes.get(AttributeKey.stringKey(ObservabilityAttributes.SERVER_ADDRESS_ATTRIBUTE))) + attributes.get( + AttributeKey.stringKey(ObservabilityAttributes.SERVER_ADDRESS_ATTRIBUTE))) .isEqualTo(SHOWCASE_SERVER_ADDRESS); assertThat( attributes.get(AttributeKey.longKey(ObservabilityAttributes.SERVER_PORT_ATTRIBUTE))) .isEqualTo(SHOWCASE_SERVER_PORT); assertThat( - attributes.get(AttributeKey.stringKey(ObservabilityAttributes.RPC_SYSTEM_NAME_ATTRIBUTE))) + attributes.get( + AttributeKey.stringKey(ObservabilityAttributes.RPC_SYSTEM_NAME_ATTRIBUTE))) .isEqualTo("grpc"); assertThat( - attributes.get(AttributeKey.stringKey(ObservabilityAttributes.GCP_CLIENT_SERVICE_ATTRIBUTE))) + attributes.get( + AttributeKey.stringKey(ObservabilityAttributes.GCP_CLIENT_SERVICE_ATTRIBUTE))) .isEqualTo("showcase"); assertThat( - attributes.get(AttributeKey.stringKey(ObservabilityAttributes.GRPC_RPC_METHOD_ATTRIBUTE))) + attributes.get( + AttributeKey.stringKey(ObservabilityAttributes.GRPC_RPC_METHOD_ATTRIBUTE))) .isEqualTo("google.showcase.v1beta1.Echo/Echo"); assertThat( - attributes.get(AttributeKey.stringKey(ObservabilityAttributes.RPC_RESPONSE_STATUS_ATTRIBUTE))) + attributes.get( + AttributeKey.stringKey(ObservabilityAttributes.RPC_RESPONSE_STATUS_ATTRIBUTE))) .isEqualTo("OK"); } } @@ -201,7 +204,8 @@ public void sendMessage(ReqT message) {} durationMetric.getHistogramData().getPoints().iterator().next().getAttributes(); assertThat( - attributes.get(AttributeKey.stringKey(ObservabilityAttributes.RPC_RESPONSE_STATUS_ATTRIBUTE))) + attributes.get( + AttributeKey.stringKey(ObservabilityAttributes.RPC_RESPONSE_STATUS_ATTRIBUTE))) .isEqualTo("UNAVAILABLE"); assertThat( attributes.get(AttributeKey.stringKey(ObservabilityAttributes.ERROR_TYPE_ATTRIBUTE))) @@ -236,29 +240,36 @@ void testMetrics_successfulEcho_httpjson() throws Exception { durationMetric.getHistogramData().getPoints().iterator().next().getAttributes(); assertThat( - attributes.get(AttributeKey.stringKey(ObservabilityAttributes.SERVER_ADDRESS_ATTRIBUTE))) + attributes.get( + AttributeKey.stringKey(ObservabilityAttributes.SERVER_ADDRESS_ATTRIBUTE))) .isEqualTo(SHOWCASE_SERVER_ADDRESS); assertThat( attributes.get(AttributeKey.longKey(ObservabilityAttributes.SERVER_PORT_ATTRIBUTE))) .isEqualTo(SHOWCASE_SERVER_PORT); assertThat( - attributes.get(AttributeKey.stringKey(ObservabilityAttributes.RPC_SYSTEM_NAME_ATTRIBUTE))) + attributes.get( + AttributeKey.stringKey(ObservabilityAttributes.RPC_SYSTEM_NAME_ATTRIBUTE))) .isEqualTo("http"); assertThat( - attributes.get(AttributeKey.stringKey(ObservabilityAttributes.GCP_CLIENT_SERVICE_ATTRIBUTE))) + attributes.get( + AttributeKey.stringKey(ObservabilityAttributes.GCP_CLIENT_SERVICE_ATTRIBUTE))) .isEqualTo("showcase"); assertThat( - attributes.get(AttributeKey.stringKey(ObservabilityAttributes.RPC_RESPONSE_STATUS_ATTRIBUTE))) + attributes.get( + AttributeKey.stringKey(ObservabilityAttributes.RPC_RESPONSE_STATUS_ATTRIBUTE))) .isEqualTo("OK"); assertThat( - attributes.get(AttributeKey.longKey(ObservabilityAttributes.HTTP_RESPONSE_STATUS_ATTRIBUTE))) + attributes.get( + AttributeKey.longKey(ObservabilityAttributes.HTTP_RESPONSE_STATUS_ATTRIBUTE))) .isEqualTo(200L); assertThat( - attributes.get(AttributeKey.stringKey(ObservabilityAttributes.URL_TEMPLATE_ATTRIBUTE))) + attributes.get( + AttributeKey.stringKey(ObservabilityAttributes.URL_TEMPLATE_ATTRIBUTE))) .isEqualTo("v1beta1/echo:echo"); assertThat( - attributes.get(AttributeKey.stringKey(ObservabilityAttributes.GRPC_RPC_METHOD_ATTRIBUTE))) - .isEqualTo("google.showcase.v1beta1.Echo/Echo"); + attributes.get( + AttributeKey.stringKey(ObservabilityAttributes.GRPC_RPC_METHOD_ATTRIBUTE))) + .isEqualTo("google.showcase.v1beta1.Echo/Echo"); } } @@ -369,10 +380,12 @@ public String getHeaderValue(int index) { durationMetric.getHistogramData().getPoints().iterator().next().getAttributes(); assertThat( - attributes.get(AttributeKey.stringKey(ObservabilityAttributes.RPC_RESPONSE_STATUS_ATTRIBUTE))) + attributes.get( + AttributeKey.stringKey(ObservabilityAttributes.RPC_RESPONSE_STATUS_ATTRIBUTE))) .isEqualTo("UNAVAILABLE"); assertThat( - attributes.get(AttributeKey.longKey(ObservabilityAttributes.HTTP_RESPONSE_STATUS_ATTRIBUTE))) + attributes.get( + AttributeKey.longKey(ObservabilityAttributes.HTTP_RESPONSE_STATUS_ATTRIBUTE))) .isEqualTo(503L); assertThat( attributes.get(AttributeKey.stringKey(ObservabilityAttributes.ERROR_TYPE_ATTRIBUTE))) diff --git a/sdk-platform-java/java-showcase/gapic-showcase/src/test/java/com/google/showcase/v1beta1/it/ITOtelTracePropagation.java b/sdk-platform-java/java-showcase/gapic-showcase/src/test/java/com/google/showcase/v1beta1/it/ITOtelTracePropagation.java index 96d59cc821b7..61d59a90fcb2 100644 --- a/sdk-platform-java/java-showcase/gapic-showcase/src/test/java/com/google/showcase/v1beta1/it/ITOtelTracePropagation.java +++ b/sdk-platform-java/java-showcase/gapic-showcase/src/test/java/com/google/showcase/v1beta1/it/ITOtelTracePropagation.java @@ -20,7 +20,6 @@ import com.google.api.gax.httpjson.ApiMethodDescriptor; import com.google.api.gax.httpjson.ForwardingHttpJsonClientCall; -import com.google.api.gax.httpjson.ForwardingHttpJsonClientCallListener; import com.google.api.gax.httpjson.HttpJsonCallOptions; import com.google.api.gax.httpjson.HttpJsonChannel; import com.google.api.gax.httpjson.HttpJsonClientCall; @@ -77,7 +76,8 @@ public ClientCall interceptCall( public void start(ClientCall.Listener responseListener, Metadata headers) { requestHeaders = headers; ClientCall.Listener forwardingResponseListener = - new ForwardingClientCallListener.SimpleForwardingClientCallListener(responseListener) { + new ForwardingClientCallListener.SimpleForwardingClientCallListener( + responseListener) { @Override public void onClose(io.grpc.Status status, Metadata trailers) { responseTrailers = trailers; @@ -90,7 +90,8 @@ public void onClose(io.grpc.Status status, Metadata trailers) { } } - private static class HttpJsonResponseCapturingClientInterceptor implements HttpJsonClientInterceptor { + private static class HttpJsonResponseCapturingClientInterceptor + implements HttpJsonClientInterceptor { private HttpJsonMetadata requestHeaders; @Override @@ -203,7 +204,8 @@ void testTracePropagation_grpc() { String expectedTraceId = attemptSpan.getSpanContext().getTraceId(); String expectedSpanId = attemptSpan.getSpanContext().getSpanId(); String expectedTraceFlags = attemptSpan.getSpanContext().getTraceFlags().asHex(); - String expectedTraceparent = "00-" + expectedTraceId + "-" + expectedSpanId + "-" + expectedTraceFlags; + String expectedTraceparent = + "00-" + expectedTraceId + "-" + expectedSpanId + "-" + expectedTraceFlags; String headerValue = grpcInterceptor.requestHeaders.get(TRACEPARENT_GRPC_HEADER_KEY); assertThat(headerValue).isNotNull(); @@ -228,7 +230,8 @@ void testTracePropagation_httpjson() { String expectedTraceId = attemptSpan.getSpanContext().getTraceId(); String expectedSpanId = attemptSpan.getSpanContext().getSpanId(); String expectedTraceFlags = attemptSpan.getSpanContext().getTraceFlags().asHex(); - String expectedTraceparent = "00-" + expectedTraceId + "-" + expectedSpanId + "-" + expectedTraceFlags; + String expectedTraceparent = + "00-" + expectedTraceId + "-" + expectedSpanId + "-" + expectedTraceFlags; assertThat(httpJsonInterceptor.requestHeaders).isNotNull(); Map headers = httpJsonInterceptor.requestHeaders.getHeaders(); @@ -237,12 +240,12 @@ void testTracePropagation_httpjson() { Object headerVal = headers.get(expectedHttpHeaderKey); if (headerVal instanceof List) { - @SuppressWarnings("unchecked") - List traceparentHeaders = (List) headerVal; - assertThat(traceparentHeaders).hasSize(1); - assertThat(traceparentHeaders.get(0)).isEqualTo(expectedTraceparent); + @SuppressWarnings("unchecked") + List traceparentHeaders = (List) headerVal; + assertThat(traceparentHeaders).hasSize(1); + assertThat(traceparentHeaders.get(0)).isEqualTo(expectedTraceparent); } else { - assertThat(String.valueOf(headerVal)).isEqualTo(expectedTraceparent); + assertThat(String.valueOf(headerVal)).isEqualTo(expectedTraceparent); } } } diff --git a/sdk-platform-java/java-showcase/gapic-showcase/src/test/java/com/google/showcase/v1beta1/it/logging/ITActionableErrorsLogging.java b/sdk-platform-java/java-showcase/gapic-showcase/src/test/java/com/google/showcase/v1beta1/it/logging/ITActionableErrorsLogging.java index ec92863cba12..358fe1e1e9f8 100644 --- a/sdk-platform-java/java-showcase/gapic-showcase/src/test/java/com/google/showcase/v1beta1/it/logging/ITActionableErrorsLogging.java +++ b/sdk-platform-java/java-showcase/gapic-showcase/src/test/java/com/google/showcase/v1beta1/it/logging/ITActionableErrorsLogging.java @@ -180,21 +180,27 @@ public LowLevelHttpResponse execute() throws IOException { assertThat(testAppender.events.size()).isAtLeast(1); ILoggingEvent loggingEvent = testAppender.events.get(testAppender.events.size() - 1); - assertThat(loggingEvent.getMessage()).contains("This is a mock JSON error generated by the server"); + assertThat(loggingEvent.getMessage()) + .contains("This is a mock JSON error generated by the server"); Map kvps = getKvps(loggingEvent); assertThat(kvps).containsEntry(ObservabilityAttributes.RPC_SYSTEM_NAME_ATTRIBUTE, "http"); assertThat(kvps).containsEntry(ObservabilityAttributes.HTTP_METHOD_ATTRIBUTE, "POST"); - assertThat(kvps).containsEntry(ObservabilityAttributes.HTTP_URL_TEMPLATE_ATTRIBUTE, "v1beta1/echo:echo"); - assertThat(kvps).containsEntry(ObservabilityAttributes.RPC_RESPONSE_STATUS_ATTRIBUTE, "ABORTED"); - assertThat(kvps).containsEntry(ObservabilityAttributes.ERROR_TYPE_ATTRIBUTE, "mock_error_reason"); - assertThat(kvps).containsEntry(ObservabilityAttributes.ERROR_DOMAIN_ATTRIBUTE, "mock.googleapis.com"); + assertThat(kvps) + .containsEntry(ObservabilityAttributes.HTTP_URL_TEMPLATE_ATTRIBUTE, "v1beta1/echo:echo"); + assertThat(kvps) + .containsEntry(ObservabilityAttributes.RPC_RESPONSE_STATUS_ATTRIBUTE, "ABORTED"); + assertThat(kvps) + .containsEntry(ObservabilityAttributes.ERROR_TYPE_ATTRIBUTE, "mock_error_reason"); + assertThat(kvps) + .containsEntry(ObservabilityAttributes.ERROR_DOMAIN_ATTRIBUTE, "mock.googleapis.com"); assertThat(kvps) .containsEntry( ObservabilityAttributes.ERROR_METADATA_ATTRIBUTE_PREFIX + "mock_key", "mock_value"); mockHttpJsonClient.close(); - mockHttpJsonClient.awaitTermination(TestClientInitializer.AWAIT_TERMINATION_SECONDS, TimeUnit.SECONDS); + mockHttpJsonClient.awaitTermination( + TestClientInitializer.AWAIT_TERMINATION_SECONDS, TimeUnit.SECONDS); } @Test @@ -208,16 +214,18 @@ void testHttpJson_noLogEmittedForSuccess() { void testHttpJson_clientLevelFailureAttributes() throws Exception { com.google.showcase.v1beta1.stub.EchoStubSettings.Builder stubSettingsBuilder = com.google.showcase.v1beta1.stub.EchoStubSettings.newHttpJsonBuilder(); - stubSettingsBuilder.echoSettings().setRetrySettings( - com.google.api.gax.retrying.RetrySettings.newBuilder() - .setInitialRpcTimeoutDuration(java.time.Duration.ofMillis(0)) - .setTotalTimeoutDuration(java.time.Duration.ofMillis(0)) - .setMaxAttempts(1) - .build()); + stubSettingsBuilder + .echoSettings() + .setRetrySettings( + com.google.api.gax.retrying.RetrySettings.newBuilder() + .setInitialRpcTimeoutDuration(java.time.Duration.ofMillis(0)) + .setTotalTimeoutDuration(java.time.Duration.ofMillis(0)) + .setMaxAttempts(1) + .build()); stubSettingsBuilder.setTracerFactory(new LoggingTracerFactory()); stubSettingsBuilder.setCredentialsProvider(NoCredentialsProvider.create()); stubSettingsBuilder.setEndpoint("localhost:1"); - + try (com.google.showcase.v1beta1.stub.EchoStub stub = stubSettingsBuilder.build().createStub(); EchoClient client = EchoClient.create(stub)) { assertThrows(ApiException.class, () -> client.echo(EchoRequest.newBuilder().build())); @@ -240,13 +248,17 @@ void testGrpc_logEmittedForLowLevelRequestFailure() { Map kvps = getKvps(loggingEvent); assertThat(kvps).containsEntry(ObservabilityAttributes.RPC_SYSTEM_NAME_ATTRIBUTE, "grpc"); assertThat(kvps) - .containsEntry(ObservabilityAttributes.GRPC_RPC_METHOD_ATTRIBUTE, "google.showcase.v1beta1.Echo/Echo"); - assertThat(kvps).containsEntry(ObservabilityAttributes.RPC_RESPONSE_STATUS_ATTRIBUTE, "INVALID_ARGUMENT"); + .containsEntry( + ObservabilityAttributes.GRPC_RPC_METHOD_ATTRIBUTE, "google.showcase.v1beta1.Echo/Echo"); + assertThat(kvps) + .containsEntry(ObservabilityAttributes.RPC_RESPONSE_STATUS_ATTRIBUTE, "INVALID_ARGUMENT"); assertThat(kvps).containsEntry(ObservabilityAttributes.ERROR_TYPE_ATTRIBUTE, "TEST_REASON"); - assertThat(kvps).containsEntry(ObservabilityAttributes.ERROR_DOMAIN_ATTRIBUTE, "test.googleapis.com"); + assertThat(kvps) + .containsEntry(ObservabilityAttributes.ERROR_DOMAIN_ATTRIBUTE, "test.googleapis.com"); assertThat(kvps) .containsEntry( - ObservabilityAttributes.ERROR_METADATA_ATTRIBUTE_PREFIX + "test_metadata", "test_value"); + ObservabilityAttributes.ERROR_METADATA_ATTRIBUTE_PREFIX + "test_metadata", + "test_value"); } @Test @@ -260,16 +272,18 @@ void testGrpc_noLogEmittedForSuccess() { void testGrpc_clientLevelFailureAttributes() throws Exception { com.google.showcase.v1beta1.stub.EchoStubSettings.Builder stubSettingsBuilder = com.google.showcase.v1beta1.stub.EchoStubSettings.newBuilder(); - stubSettingsBuilder.echoSettings().setRetrySettings( - com.google.api.gax.retrying.RetrySettings.newBuilder() - .setInitialRpcTimeoutDuration(java.time.Duration.ofMillis(0)) - .setTotalTimeoutDuration(java.time.Duration.ofMillis(0)) - .setMaxAttempts(1) - .build()); + stubSettingsBuilder + .echoSettings() + .setRetrySettings( + com.google.api.gax.retrying.RetrySettings.newBuilder() + .setInitialRpcTimeoutDuration(java.time.Duration.ofMillis(0)) + .setTotalTimeoutDuration(java.time.Duration.ofMillis(0)) + .setMaxAttempts(1) + .build()); stubSettingsBuilder.setTracerFactory(new LoggingTracerFactory()); stubSettingsBuilder.setCredentialsProvider(NoCredentialsProvider.create()); stubSettingsBuilder.setEndpoint("localhost:1"); - + try (com.google.showcase.v1beta1.stub.EchoStub stub = stubSettingsBuilder.build().createStub(); EchoClient client = EchoClient.create(stub)) { assertThrows(ApiException.class, () -> client.echo(EchoRequest.newBuilder().build())); diff --git a/sdk-platform-java/java-showcase/gapic-showcase/src/test/java/com/google/showcase/v1beta1/it/util/TestClientInitializer.java b/sdk-platform-java/java-showcase/gapic-showcase/src/test/java/com/google/showcase/v1beta1/it/util/TestClientInitializer.java index 5aeb4d40655c..86eb253ade94 100644 --- a/sdk-platform-java/java-showcase/gapic-showcase/src/test/java/com/google/showcase/v1beta1/it/util/TestClientInitializer.java +++ b/sdk-platform-java/java-showcase/gapic-showcase/src/test/java/com/google/showcase/v1beta1/it/util/TestClientInitializer.java @@ -38,7 +38,6 @@ import com.google.showcase.v1beta1.stub.EchoStubSettings; import io.grpc.ClientInterceptor; import io.grpc.ManagedChannelBuilder; - import java.io.IOException; import java.util.List; import java.util.Set; @@ -371,9 +370,9 @@ public static IdentityClient createHttpJsonIdentityClientOpentelemetry( } private static EchoStub createStubWithServiceName( - EchoSettings settings, ApiTracerFactory tracingFactory) throws IOException { + EchoSettings settings, ApiTracerFactory tracingFactory) throws IOException { EchoStubSettings.Builder builder = - (EchoStubSettings.Builder) settings.getStubSettings().toBuilder(); + (EchoStubSettings.Builder) settings.getStubSettings().toBuilder(); builder.setTracerFactory(tracingFactory); return new ExtendedEchoStubSettings(builder).createStub(); } From 9601953c46b1343e8fa122de1ae5222a811978f8 Mon Sep 17 00:00:00 2001 From: Wes Tarle Date: Sat, 4 Apr 2026 01:31:23 -0400 Subject: [PATCH 12/12] style: revert formatting on unrelated files --- .../v1beta1/it/ITOtelGoldenMetrics.java | 55 +++++++------------ .../v1beta1/it/ITOtelTracePropagation.java | 23 ++++---- .../it/util/TestClientInitializer.java | 5 +- 3 files changed, 34 insertions(+), 49 deletions(-) diff --git a/sdk-platform-java/java-showcase/gapic-showcase/src/test/java/com/google/showcase/v1beta1/it/ITOtelGoldenMetrics.java b/sdk-platform-java/java-showcase/gapic-showcase/src/test/java/com/google/showcase/v1beta1/it/ITOtelGoldenMetrics.java index 42d69873f78d..70f86141f6c5 100644 --- a/sdk-platform-java/java-showcase/gapic-showcase/src/test/java/com/google/showcase/v1beta1/it/ITOtelGoldenMetrics.java +++ b/sdk-platform-java/java-showcase/gapic-showcase/src/test/java/com/google/showcase/v1beta1/it/ITOtelGoldenMetrics.java @@ -35,13 +35,16 @@ import com.google.api.client.http.HttpTransport; import com.google.api.gax.core.NoCredentialsProvider; +import com.google.api.gax.rpc.StatusCode; import com.google.api.gax.rpc.TransportChannelProvider; import com.google.api.gax.rpc.UnavailableException; import com.google.api.gax.tracing.GoldenSignalsMetricsTracerFactory; import com.google.api.gax.tracing.ObservabilityAttributes; import com.google.common.collect.ImmutableList; +import com.google.rpc.Status; import com.google.showcase.v1beta1.EchoClient; import com.google.showcase.v1beta1.EchoRequest; +import com.google.showcase.v1beta1.EchoResponse; import com.google.showcase.v1beta1.EchoSettings; import com.google.showcase.v1beta1.it.util.TestClientInitializer; import com.google.showcase.v1beta1.stub.EchoStubSettings; @@ -49,8 +52,8 @@ import io.grpc.Channel; import io.grpc.ClientCall; import io.grpc.ClientInterceptor; -import io.grpc.Metadata; import io.grpc.MethodDescriptor; +import io.grpc.Metadata; import io.opentelemetry.api.common.AttributeKey; import io.opentelemetry.sdk.OpenTelemetrySdk; import io.opentelemetry.sdk.metrics.SdkMeterProvider; @@ -100,8 +103,7 @@ void testMetrics_successfulEcho_grpc() throws Exception { // The end of an operation is tracked in a separate thread. // Add a small sleep to make sure the tracking is completed. - // This is implemented by adding a TraceFinisher to ApiFuture as a callback in - // TracedUnaryCallable, + // This is implemented by adding a TraceFinisher to ApiFuture as a callback in TracedUnaryCallable, // which could be executed in a different thread. Thread.sleep(100); Collection metrics = metricReader.collectAllMetrics(); @@ -120,27 +122,22 @@ void testMetrics_successfulEcho_grpc() throws Exception { durationMetric.getHistogramData().getPoints().iterator().next().getAttributes(); assertThat( - attributes.get( - AttributeKey.stringKey(ObservabilityAttributes.SERVER_ADDRESS_ATTRIBUTE))) + attributes.get(AttributeKey.stringKey(ObservabilityAttributes.SERVER_ADDRESS_ATTRIBUTE))) .isEqualTo(SHOWCASE_SERVER_ADDRESS); assertThat( attributes.get(AttributeKey.longKey(ObservabilityAttributes.SERVER_PORT_ATTRIBUTE))) .isEqualTo(SHOWCASE_SERVER_PORT); assertThat( - attributes.get( - AttributeKey.stringKey(ObservabilityAttributes.RPC_SYSTEM_NAME_ATTRIBUTE))) + attributes.get(AttributeKey.stringKey(ObservabilityAttributes.RPC_SYSTEM_NAME_ATTRIBUTE))) .isEqualTo("grpc"); assertThat( - attributes.get( - AttributeKey.stringKey(ObservabilityAttributes.GCP_CLIENT_SERVICE_ATTRIBUTE))) + attributes.get(AttributeKey.stringKey(ObservabilityAttributes.GCP_CLIENT_SERVICE_ATTRIBUTE))) .isEqualTo("showcase"); assertThat( - attributes.get( - AttributeKey.stringKey(ObservabilityAttributes.GRPC_RPC_METHOD_ATTRIBUTE))) + attributes.get(AttributeKey.stringKey(ObservabilityAttributes.GRPC_RPC_METHOD_ATTRIBUTE))) .isEqualTo("google.showcase.v1beta1.Echo/Echo"); assertThat( - attributes.get( - AttributeKey.stringKey(ObservabilityAttributes.RPC_RESPONSE_STATUS_ATTRIBUTE))) + attributes.get(AttributeKey.stringKey(ObservabilityAttributes.RPC_RESPONSE_STATUS_ATTRIBUTE))) .isEqualTo("OK"); } } @@ -204,8 +201,7 @@ public void sendMessage(ReqT message) {} durationMetric.getHistogramData().getPoints().iterator().next().getAttributes(); assertThat( - attributes.get( - AttributeKey.stringKey(ObservabilityAttributes.RPC_RESPONSE_STATUS_ATTRIBUTE))) + attributes.get(AttributeKey.stringKey(ObservabilityAttributes.RPC_RESPONSE_STATUS_ATTRIBUTE))) .isEqualTo("UNAVAILABLE"); assertThat( attributes.get(AttributeKey.stringKey(ObservabilityAttributes.ERROR_TYPE_ATTRIBUTE))) @@ -240,36 +236,29 @@ void testMetrics_successfulEcho_httpjson() throws Exception { durationMetric.getHistogramData().getPoints().iterator().next().getAttributes(); assertThat( - attributes.get( - AttributeKey.stringKey(ObservabilityAttributes.SERVER_ADDRESS_ATTRIBUTE))) + attributes.get(AttributeKey.stringKey(ObservabilityAttributes.SERVER_ADDRESS_ATTRIBUTE))) .isEqualTo(SHOWCASE_SERVER_ADDRESS); assertThat( attributes.get(AttributeKey.longKey(ObservabilityAttributes.SERVER_PORT_ATTRIBUTE))) .isEqualTo(SHOWCASE_SERVER_PORT); assertThat( - attributes.get( - AttributeKey.stringKey(ObservabilityAttributes.RPC_SYSTEM_NAME_ATTRIBUTE))) + attributes.get(AttributeKey.stringKey(ObservabilityAttributes.RPC_SYSTEM_NAME_ATTRIBUTE))) .isEqualTo("http"); assertThat( - attributes.get( - AttributeKey.stringKey(ObservabilityAttributes.GCP_CLIENT_SERVICE_ATTRIBUTE))) + attributes.get(AttributeKey.stringKey(ObservabilityAttributes.GCP_CLIENT_SERVICE_ATTRIBUTE))) .isEqualTo("showcase"); assertThat( - attributes.get( - AttributeKey.stringKey(ObservabilityAttributes.RPC_RESPONSE_STATUS_ATTRIBUTE))) + attributes.get(AttributeKey.stringKey(ObservabilityAttributes.RPC_RESPONSE_STATUS_ATTRIBUTE))) .isEqualTo("OK"); assertThat( - attributes.get( - AttributeKey.longKey(ObservabilityAttributes.HTTP_RESPONSE_STATUS_ATTRIBUTE))) + attributes.get(AttributeKey.longKey(ObservabilityAttributes.HTTP_RESPONSE_STATUS_ATTRIBUTE))) .isEqualTo(200L); assertThat( - attributes.get( - AttributeKey.stringKey(ObservabilityAttributes.URL_TEMPLATE_ATTRIBUTE))) + attributes.get(AttributeKey.stringKey(ObservabilityAttributes.URL_TEMPLATE_ATTRIBUTE))) .isEqualTo("v1beta1/echo:echo"); assertThat( - attributes.get( - AttributeKey.stringKey(ObservabilityAttributes.GRPC_RPC_METHOD_ATTRIBUTE))) - .isEqualTo("google.showcase.v1beta1.Echo/Echo"); + attributes.get(AttributeKey.stringKey(ObservabilityAttributes.GRPC_RPC_METHOD_ATTRIBUTE))) + .isEqualTo("google.showcase.v1beta1.Echo/Echo"); } } @@ -380,12 +369,10 @@ public String getHeaderValue(int index) { durationMetric.getHistogramData().getPoints().iterator().next().getAttributes(); assertThat( - attributes.get( - AttributeKey.stringKey(ObservabilityAttributes.RPC_RESPONSE_STATUS_ATTRIBUTE))) + attributes.get(AttributeKey.stringKey(ObservabilityAttributes.RPC_RESPONSE_STATUS_ATTRIBUTE))) .isEqualTo("UNAVAILABLE"); assertThat( - attributes.get( - AttributeKey.longKey(ObservabilityAttributes.HTTP_RESPONSE_STATUS_ATTRIBUTE))) + attributes.get(AttributeKey.longKey(ObservabilityAttributes.HTTP_RESPONSE_STATUS_ATTRIBUTE))) .isEqualTo(503L); assertThat( attributes.get(AttributeKey.stringKey(ObservabilityAttributes.ERROR_TYPE_ATTRIBUTE))) diff --git a/sdk-platform-java/java-showcase/gapic-showcase/src/test/java/com/google/showcase/v1beta1/it/ITOtelTracePropagation.java b/sdk-platform-java/java-showcase/gapic-showcase/src/test/java/com/google/showcase/v1beta1/it/ITOtelTracePropagation.java index 61d59a90fcb2..96d59cc821b7 100644 --- a/sdk-platform-java/java-showcase/gapic-showcase/src/test/java/com/google/showcase/v1beta1/it/ITOtelTracePropagation.java +++ b/sdk-platform-java/java-showcase/gapic-showcase/src/test/java/com/google/showcase/v1beta1/it/ITOtelTracePropagation.java @@ -20,6 +20,7 @@ import com.google.api.gax.httpjson.ApiMethodDescriptor; import com.google.api.gax.httpjson.ForwardingHttpJsonClientCall; +import com.google.api.gax.httpjson.ForwardingHttpJsonClientCallListener; import com.google.api.gax.httpjson.HttpJsonCallOptions; import com.google.api.gax.httpjson.HttpJsonChannel; import com.google.api.gax.httpjson.HttpJsonClientCall; @@ -76,8 +77,7 @@ public ClientCall interceptCall( public void start(ClientCall.Listener responseListener, Metadata headers) { requestHeaders = headers; ClientCall.Listener forwardingResponseListener = - new ForwardingClientCallListener.SimpleForwardingClientCallListener( - responseListener) { + new ForwardingClientCallListener.SimpleForwardingClientCallListener(responseListener) { @Override public void onClose(io.grpc.Status status, Metadata trailers) { responseTrailers = trailers; @@ -90,8 +90,7 @@ public void onClose(io.grpc.Status status, Metadata trailers) { } } - private static class HttpJsonResponseCapturingClientInterceptor - implements HttpJsonClientInterceptor { + private static class HttpJsonResponseCapturingClientInterceptor implements HttpJsonClientInterceptor { private HttpJsonMetadata requestHeaders; @Override @@ -204,8 +203,7 @@ void testTracePropagation_grpc() { String expectedTraceId = attemptSpan.getSpanContext().getTraceId(); String expectedSpanId = attemptSpan.getSpanContext().getSpanId(); String expectedTraceFlags = attemptSpan.getSpanContext().getTraceFlags().asHex(); - String expectedTraceparent = - "00-" + expectedTraceId + "-" + expectedSpanId + "-" + expectedTraceFlags; + String expectedTraceparent = "00-" + expectedTraceId + "-" + expectedSpanId + "-" + expectedTraceFlags; String headerValue = grpcInterceptor.requestHeaders.get(TRACEPARENT_GRPC_HEADER_KEY); assertThat(headerValue).isNotNull(); @@ -230,8 +228,7 @@ void testTracePropagation_httpjson() { String expectedTraceId = attemptSpan.getSpanContext().getTraceId(); String expectedSpanId = attemptSpan.getSpanContext().getSpanId(); String expectedTraceFlags = attemptSpan.getSpanContext().getTraceFlags().asHex(); - String expectedTraceparent = - "00-" + expectedTraceId + "-" + expectedSpanId + "-" + expectedTraceFlags; + String expectedTraceparent = "00-" + expectedTraceId + "-" + expectedSpanId + "-" + expectedTraceFlags; assertThat(httpJsonInterceptor.requestHeaders).isNotNull(); Map headers = httpJsonInterceptor.requestHeaders.getHeaders(); @@ -240,12 +237,12 @@ void testTracePropagation_httpjson() { Object headerVal = headers.get(expectedHttpHeaderKey); if (headerVal instanceof List) { - @SuppressWarnings("unchecked") - List traceparentHeaders = (List) headerVal; - assertThat(traceparentHeaders).hasSize(1); - assertThat(traceparentHeaders.get(0)).isEqualTo(expectedTraceparent); + @SuppressWarnings("unchecked") + List traceparentHeaders = (List) headerVal; + assertThat(traceparentHeaders).hasSize(1); + assertThat(traceparentHeaders.get(0)).isEqualTo(expectedTraceparent); } else { - assertThat(String.valueOf(headerVal)).isEqualTo(expectedTraceparent); + assertThat(String.valueOf(headerVal)).isEqualTo(expectedTraceparent); } } } diff --git a/sdk-platform-java/java-showcase/gapic-showcase/src/test/java/com/google/showcase/v1beta1/it/util/TestClientInitializer.java b/sdk-platform-java/java-showcase/gapic-showcase/src/test/java/com/google/showcase/v1beta1/it/util/TestClientInitializer.java index 86eb253ade94..5aeb4d40655c 100644 --- a/sdk-platform-java/java-showcase/gapic-showcase/src/test/java/com/google/showcase/v1beta1/it/util/TestClientInitializer.java +++ b/sdk-platform-java/java-showcase/gapic-showcase/src/test/java/com/google/showcase/v1beta1/it/util/TestClientInitializer.java @@ -38,6 +38,7 @@ import com.google.showcase.v1beta1.stub.EchoStubSettings; import io.grpc.ClientInterceptor; import io.grpc.ManagedChannelBuilder; + import java.io.IOException; import java.util.List; import java.util.Set; @@ -370,9 +371,9 @@ public static IdentityClient createHttpJsonIdentityClientOpentelemetry( } private static EchoStub createStubWithServiceName( - EchoSettings settings, ApiTracerFactory tracingFactory) throws IOException { + EchoSettings settings, ApiTracerFactory tracingFactory) throws IOException { EchoStubSettings.Builder builder = - (EchoStubSettings.Builder) settings.getStubSettings().toBuilder(); + (EchoStubSettings.Builder) settings.getStubSettings().toBuilder(); builder.setTracerFactory(tracingFactory); return new ExtendedEchoStubSettings(builder).createStub(); }