TraceIdFilter.java
package com.project.auth.config.web;
import com.project.auth.application.support.logging.LogSanitizer;
import jakarta.servlet.FilterChain;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.slf4j.MDC;
import org.slf4j.MDC.MDCCloseable;
import org.springframework.web.filter.OncePerRequestFilter;
import java.io.IOException;
import java.util.HexFormat;
import java.util.concurrent.ThreadLocalRandom;
public class TraceIdFilter extends OncePerRequestFilter {
private static final String TRACE_ID_KEY = "traceId";
private static final String CLIENT_IP_KEY = "clientIp";
private static final String USER_AGENT_KEY = "userAgent";
private static final String TRACE_ID_HEADER = "X-Trace-Id";
private static final String USER_AGENT_HEADER = "User-Agent";
private static final HexFormat HEX_FORMAT = HexFormat.of();
@Override
protected void doFilterInternal(
HttpServletRequest request,
HttpServletResponse response,
FilterChain filterChain) throws ServletException, IOException {
String traceId = nextTraceId();
String clientIp = LogSanitizer.clientIp(request.getRemoteAddr());
String userAgent = LogSanitizer.userAgent(request.getHeader(USER_AGENT_HEADER));
response.setHeader(TRACE_ID_HEADER, traceId);
try (
MDCCloseable ignoredTraceId = MDC.putCloseable(TRACE_ID_KEY, traceId);
MDCCloseable ignoredClientIp = MDC.putCloseable(CLIENT_IP_KEY, clientIp);
MDCCloseable ignoredUserAgent = MDC.putCloseable(USER_AGENT_KEY, userAgent)) {
filterChain.doFilter(request, response);
}
}
private String nextTraceId() {
long highBits;
long lowBits;
do {
highBits = ThreadLocalRandom.current().nextLong();
lowBits = ThreadLocalRandom.current().nextLong();
} while (highBits == 0L && lowBits == 0L);
return HEX_FORMAT.toHexDigits(highBits) + HEX_FORMAT.toHexDigits(lowBits);
}
}