import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.slf4j.MDC;
import org.springframework.stereotype.Component;
import org.springframework.web.filter.OncePerRequestFilter;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.UUID;
@Component
public class LoggingAndTraceFilter extends OncePerRequestFilter {
private static final Logger log = LoggerFactory.getLogger(LoggingAndTraceFilter.class);
private static final String TRACE_ID_HEADER = "X-Trace-ID";
private static final String TENANT_ID_HEADER = "X-Tenant-ID";
private static final String TRACE_ID_MDC_KEY = "traceId";
private static final String TENANT_ID_MDC_KEY = "tenantId";
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
throws ServletException, IOException {
String traceId = request.getHeader(TRACE_ID_HEADER);
if (traceId == null || traceId.isEmpty()) {
traceId = UUID.randomUUID().toString();
log.debug("Generated new Trace ID: {}", traceId);
}
String tenantId = request.getHeader(TENANT_ID_HEADER);
if (tenantId == null) {
tenantId = "unknown";
}
MDC.put(TRACE_ID_MDC_KEY, traceId);
MDC.put(TENANT_ID_MDC_KEY, tenantId);
log.info("Request received: {} {} for Tenant: {}", request.getMethod(), request.getRequestURI(), tenantId);
try {
filterChain.doFilter(request, response);
} finally {
MDC.remove(TRACE_ID_MDC_KEY);
MDC.remove(TENANT_ID_MDC_KEY);
log.info("Request completed: {} {}", request.getMethod(), request.getRequestURI());
}
}
}