diff --git a/grpc-context-utils/src/main/java/org/hypertrace/core/grpcutils/context/RequestContextConstants.java b/grpc-context-utils/src/main/java/org/hypertrace/core/grpcutils/context/RequestContextConstants.java index 9dfd39e..d713bcf 100644 --- a/grpc-context-utils/src/main/java/org/hypertrace/core/grpcutils/context/RequestContextConstants.java +++ b/grpc-context-utils/src/main/java/org/hypertrace/core/grpcutils/context/RequestContextConstants.java @@ -20,12 +20,15 @@ public class RequestContextConstants { public static final String AUTHORIZATION_HEADER = "authorization"; + public static final String CTX_HEADER_PREFIX = "x-ctx-"; + /** The values in this set are looked up with case insensitivity. */ public static final Set HEADER_PREFIXES_TO_BE_PROPAGATED = Set.of( TENANT_ID_HEADER_KEY, CONTEXT_ID_HEADER_KEY, SUPPRESS_USER_TRACKING_HEADER_KEY, + CTX_HEADER_PREFIX, "X-B3-", "grpc-trace-bin", "traceparent", diff --git a/grpc-server-utils/build.gradle.kts b/grpc-server-utils/build.gradle.kts index de8bfed..5ec0d32 100644 --- a/grpc-server-utils/build.gradle.kts +++ b/grpc-server-utils/build.gradle.kts @@ -14,6 +14,7 @@ dependencies { api(commonLibs.grpc.api) implementation(projects.grpcContextUtils) implementation(commonLibs.slf4j2.api) + compileOnly("org.apache.logging.log4j:log4j-core:2.20.0") annotationProcessor(commonLibs.lombok) compileOnly(commonLibs.lombok) diff --git a/grpc-server-utils/gradle.lockfile b/grpc-server-utils/gradle.lockfile index ffd3b06..983942a 100644 --- a/grpc-server-utils/gradle.lockfile +++ b/grpc-server-utils/gradle.lockfile @@ -24,6 +24,8 @@ io.netty:netty-bom:4.1.125.Final=compileClasspath,runtimeClasspath,testCompileCl io.perfmark:perfmark-api:0.27.0=runtimeClasspath,testRuntimeClasspath net.bytebuddy:byte-buddy-agent:1.14.10=testCompileClasspath,testRuntimeClasspath net.bytebuddy:byte-buddy:1.14.10=testCompileClasspath,testRuntimeClasspath +org.apache.logging.log4j:log4j-api:2.20.0=compileClasspath +org.apache.logging.log4j:log4j-core:2.20.0=compileClasspath org.apiguardian:apiguardian-api:1.1.2=testCompileClasspath org.checkerframework:checker-qual:3.43.0=runtimeClasspath,testRuntimeClasspath org.codehaus.mojo:animal-sniffer-annotations:1.24=runtimeClasspath,testRuntimeClasspath diff --git a/grpc-server-utils/src/main/java/org/hypertrace/core/grpcutils/server/ContextMdcPatternConverter.java b/grpc-server-utils/src/main/java/org/hypertrace/core/grpcutils/server/ContextMdcPatternConverter.java new file mode 100644 index 0000000..061463d --- /dev/null +++ b/grpc-server-utils/src/main/java/org/hypertrace/core/grpcutils/server/ContextMdcPatternConverter.java @@ -0,0 +1,41 @@ +package org.hypertrace.core.grpcutils.server; + +import org.apache.logging.log4j.core.LogEvent; +import org.apache.logging.log4j.core.config.plugins.Plugin; +import org.apache.logging.log4j.core.pattern.ConverterKeys; +import org.apache.logging.log4j.core.pattern.LogEventPatternConverter; +import org.apache.logging.log4j.core.pattern.PatternConverter; +import org.apache.logging.log4j.util.ReadOnlyStringMap; + +@Plugin(name = "ctxParams", category = PatternConverter.CATEGORY) +@ConverterKeys({"ctxParams"}) +public class ContextMdcPatternConverter extends LogEventPatternConverter { + + private static final String CTX_PREFIX = "x-ctx-"; + + private ContextMdcPatternConverter() { + super("ctxParams", "ctxParams"); + } + + public static ContextMdcPatternConverter newInstance(String[] options) { + return new ContextMdcPatternConverter(); + } + + @Override + public void format(LogEvent event, StringBuilder toAppendTo) { + ReadOnlyStringMap contextData = event.getContextData(); + if (contextData == null || contextData.isEmpty()) return; + + StringBuilder sb = new StringBuilder(); + contextData.forEach( + (key, value) -> { + if (key.startsWith(CTX_PREFIX)) { + if (sb.length() > 0) sb.append(", "); + sb.append(key).append("=").append(value); + } + }); + if (sb.length() > 0) { + toAppendTo.append("[").append(sb).append("]"); + } + } +} diff --git a/grpc-server-utils/src/main/java/org/hypertrace/core/grpcutils/server/RequestContextLoggingServerInterceptor.java b/grpc-server-utils/src/main/java/org/hypertrace/core/grpcutils/server/RequestContextLoggingServerInterceptor.java index 670bf64..a71ab5f 100644 --- a/grpc-server-utils/src/main/java/org/hypertrace/core/grpcutils/server/RequestContextLoggingServerInterceptor.java +++ b/grpc-server-utils/src/main/java/org/hypertrace/core/grpcutils/server/RequestContextLoggingServerInterceptor.java @@ -1,6 +1,7 @@ package org.hypertrace.core.grpcutils.server; import static org.hypertrace.core.grpcutils.context.RequestContextConstants.CONTEXT_ID_HEADER_KEY; +import static org.hypertrace.core.grpcutils.context.RequestContextConstants.CTX_HEADER_PREFIX; import static org.hypertrace.core.grpcutils.context.RequestContextConstants.REQUEST_ID_HEADER_KEY; import static org.hypertrace.core.grpcutils.context.RequestContextConstants.TENANT_ID_HEADER_KEY; @@ -69,6 +70,9 @@ public void onMessage(ReqT message) { MDC.put(REQUEST_ID_HEADER_KEY, requestId); opTenantId.ifPresent(s -> MDC.put(TENANT_ID_HEADER_KEY, s)); opContextId.ifPresent(s -> MDC.put(CONTEXT_ID_HEADER_KEY, s)); + currentContext.getAllHeaders().stream() + .filter(header -> header.getName().startsWith(CTX_HEADER_PREFIX)) + .forEach(header -> MDC.put(header.getName(), header.getValue())); } catch (Exception e) { log.error("Error while setting request context details in MDC params", e); }