From 29b7079fea74d96d64ceb2dd88c3398730166403 Mon Sep 17 00:00:00 2001 From: Wes Tarle Date: Mon, 23 Mar 2026 13:54:15 -0400 Subject: [PATCH 1/9] 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 2/9] 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 3/9] 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 4/9] 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 5/9] 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 6/9] 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 7/9] 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 8/9] 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 9/9] 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();