'GRPC Java: Populate/Clear the MDC on every request/message
Given a GRPC service (no matter if it is a simple RPC or uni/bidirectional service) how to correctly deal with the MDC?
I thought I'd implement a Server Interceptor where:
- Needed fields are retrieved from metadata (headers) (ex. correalation-id)
- A new Context is created with the retrieved metadata.
- A SimpleForwardingServerCallListener is returned. In the callbacks of the SimpleForwardingServerCallListener the MDC is populated/cleared.
Here is the code, and it seems to work as expected. Is this the correct way to handle this use-case? Thank you
public class GRPCLoggingInterceptor implements ServerInterceptor {
@Override
public <ReqT, RespT> ServerCall.Listener<ReqT> interceptCall(ServerCall<ReqT, RespT> call,
Metadata headers,
ServerCallHandler<ReqT, RespT> next) {
// Get Headers
String correlationId = headers.get(Metadata.Key.of(CORRELATION_ID_HEADER_KEY, Metadata.ASCII_STRING_MARSHALLER));
// Put headers into current Context
Context context = Context.current()
.withValue(Context.key(CORRELATION_ID_HEADER_KEY),correlationId);
// Obtain a listener attached to the current Context (Needed to propagate current context)
ServerCall.Listener<ReqT> ctxlistener = Contexts.interceptCall(context, call, headers, next);
// Configure the Callbacks to enrich and clean the MDC
return new SimpleForwardingServerCallListener<>(ctxlistener) {
@Override
public void onMessage(ReqT message) {
enrichMDC(correlationId);
try {
super.onMessage(message);
} finally {
clearMDC();
}
}
@Override
public void onHalfClose() {
enrichMDC(correlationId);
try {
super.onHalfClose();
} finally {
clearMDC();
}
}
@Override
public void onCancel() {
enrichMDC(correlationId);
try {
super.onCancel();
} finally {
clearMDC();
}
}
@Override
public void onComplete() {
enrichMDC(correlationId);
try {
super.onComplete();
} finally {
clearMDC();
}
}
@Override
public void onReady() {
enrichMDC(correlationId);
try {
super.onReady();
} finally {
clearMDC();
}
}
};
}
private void enrichMDC(String correlationId) {
MDC.put(CORRELATION_ID_MDC_KEY, correlationId);
}
private void clearMDC() {
MDC.clear();
}
}
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|
