From 2606dd61641385a2d97343c7feb28b4ddcc1f8f4 Mon Sep 17 00:00:00 2001 From: Nicklas Lundin Date: Fri, 10 Apr 2026 10:05:18 +0200 Subject: [PATCH] fix(java): suppress shaded gRPC DEBUG noise on startup Shaded gRPC logs ClassNotFoundException stack traces at DEBUG level when probing for optional classes (ContextStorageOverride, JndiResourceResolverFactory). Set JUL level to INFO for the shaded logger hierarchy to prevent these from reaching the app's logging pipeline. Co-Authored-By: Claude Opus 4.6 (1M context) --- .../sdk/OpenFeatureLocalResolveProvider.java | 32 +++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/openfeature-provider/java/src/main/java/com/spotify/confidence/sdk/OpenFeatureLocalResolveProvider.java b/openfeature-provider/java/src/main/java/com/spotify/confidence/sdk/OpenFeatureLocalResolveProvider.java index d40a09d1..7cc4d3be 100644 --- a/openfeature-provider/java/src/main/java/com/spotify/confidence/sdk/OpenFeatureLocalResolveProvider.java +++ b/openfeature-provider/java/src/main/java/com/spotify/confidence/sdk/OpenFeatureLocalResolveProvider.java @@ -49,6 +49,38 @@ */ @Experimental public class OpenFeatureLocalResolveProvider implements FeatureProvider { + + // The shaded package prefix used by the maven-shade-plugin relocation rules. + private static final String SHADED_PREFIX = "com.spotify.confidence.sdk.shaded"; + + /** + * Suppress DEBUG-level logging from shaded gRPC/Netty internals. + * + *

gRPC logs {@link ClassNotFoundException} at DEBUG when probing for optional classes (e.g. + * {@code ContextStorageOverride}, {@code JndiResourceResolverFactory}). These are expected and + * handled gracefully, but produce alarming stack traces when DEBUG logging is enabled. + * + *

Since these packages are relocated to {@code com.spotify.confidence.sdk.shaded.*}, users + * cannot easily configure them in their logging framework. We set the JUL level to INFO to + * prevent this noise from reaching the application's logging pipeline via the JUL-to-SLF4J + * bridge. + * + *

This only affects the shaded logger hierarchy — the application's own {@code io.grpc} + * loggers are not impacted. + * + *

The field also serves as a strong reference to prevent the JUL {@link + * java.util.logging.Logger} from being garbage-collected (JUL uses weak references internally). + */ + @SuppressWarnings("unused") + private static final java.util.logging.Logger SHADED_GRPC_LOGGER = initShadedGrpcLogging(); + + private static java.util.logging.Logger initShadedGrpcLogging() { + java.util.logging.Logger logger = + java.util.logging.Logger.getLogger(SHADED_PREFIX + ".io.grpc"); + logger.setLevel(java.util.logging.Level.INFO); + return logger; + } + private final String clientSecret; private static final Logger log = org.slf4j.LoggerFactory.getLogger(OpenFeatureLocalResolveProvider.class);