|
|
@@ -0,0 +1,100 @@
|
|
|
+package com.shop.recycle.gateway.filter;
|
|
|
+
|
|
|
+import org.slf4j.Logger;
|
|
|
+import org.slf4j.LoggerFactory;
|
|
|
+import org.slf4j.MDC;
|
|
|
+import org.springframework.core.Ordered;
|
|
|
+import org.springframework.core.annotation.Order;
|
|
|
+import org.springframework.stereotype.Component;
|
|
|
+import org.springframework.web.server.ServerWebExchange;
|
|
|
+import org.springframework.web.server.WebFilter;
|
|
|
+import org.springframework.web.server.WebFilterChain;
|
|
|
+import reactor.core.publisher.Mono;
|
|
|
+
|
|
|
+import java.util.UUID;
|
|
|
+import java.util.concurrent.atomic.AtomicReference;
|
|
|
+
|
|
|
+/**
|
|
|
+ * WebFlux logging filter that injects MDC fields for JSON logs.
|
|
|
+ */
|
|
|
+@Component
|
|
|
+@Order(Ordered.HIGHEST_PRECEDENCE)
|
|
|
+public class LoggingMdcWebFilter implements WebFilter {
|
|
|
+
|
|
|
+ private static final Logger log = LoggerFactory.getLogger(LoggingMdcWebFilter.class);
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public Mono<Void> filter(ServerWebExchange exchange, WebFilterChain chain) {
|
|
|
+ long startTime = System.currentTimeMillis();
|
|
|
+ String traceId = resolveTraceId(exchange);
|
|
|
+ String uri = exchange.getRequest().getURI().getPath();
|
|
|
+ String uriGroup = normalizeUri(uri);
|
|
|
+ String eventClass = deriveEventClass(uri);
|
|
|
+ String userId = exchange.getRequest().getHeaders().getFirst("X-User-Id");
|
|
|
+
|
|
|
+ AtomicReference<String> errorRef = new AtomicReference<>(null);
|
|
|
+
|
|
|
+ return chain.filter(exchange)
|
|
|
+ .doOnError(ex -> errorRef.set(ex.toString()))
|
|
|
+ .doFinally(signalType -> {
|
|
|
+ int statusCode = exchange.getResponse().getStatusCode() != null
|
|
|
+ ? exchange.getResponse().getStatusCode().value()
|
|
|
+ : 200;
|
|
|
+ String status = statusCode >= 400
|
|
|
+ ? (statusCode >= 500 ? "server_error" : "client_error")
|
|
|
+ : "success";
|
|
|
+
|
|
|
+ MDC.put("traceId", traceId);
|
|
|
+ MDC.put("uri", uri);
|
|
|
+ MDC.put("uri_group", uriGroup);
|
|
|
+ MDC.put("event_class", eventClass);
|
|
|
+ if (userId != null) {
|
|
|
+ MDC.put("userId", userId);
|
|
|
+ }
|
|
|
+ MDC.put("duration", String.valueOf(System.currentTimeMillis() - startTime));
|
|
|
+ MDC.put("status", status);
|
|
|
+ if (errorRef.get() != null) {
|
|
|
+ MDC.put("error", errorRef.get());
|
|
|
+ } else if (statusCode >= 400) {
|
|
|
+ MDC.put("error", "HTTP_" + statusCode);
|
|
|
+ }
|
|
|
+
|
|
|
+ log.info("gateway_request");
|
|
|
+ MDC.clear();
|
|
|
+ });
|
|
|
+ }
|
|
|
+
|
|
|
+ private String resolveTraceId(ServerWebExchange exchange) {
|
|
|
+ String traceId = exchange.getRequest().getHeaders().getFirst("X-B3-TraceId");
|
|
|
+ if (traceId == null || traceId.isEmpty()) {
|
|
|
+ traceId = UUID.randomUUID().toString();
|
|
|
+ }
|
|
|
+ return traceId;
|
|
|
+ }
|
|
|
+
|
|
|
+ private String normalizeUri(String uri) {
|
|
|
+ if (uri.startsWith("/order/")) {
|
|
|
+ return "/order/*";
|
|
|
+ }
|
|
|
+ if (uri.startsWith("/payment/")) {
|
|
|
+ return "/payment/*";
|
|
|
+ }
|
|
|
+ if (uri.startsWith("/gateway/")) {
|
|
|
+ return "/gateway/*";
|
|
|
+ }
|
|
|
+ return uri;
|
|
|
+ }
|
|
|
+
|
|
|
+ private String deriveEventClass(String uri) {
|
|
|
+ if (uri.contains("order")) {
|
|
|
+ return "order";
|
|
|
+ }
|
|
|
+ if (uri.contains("payment")) {
|
|
|
+ return "payment";
|
|
|
+ }
|
|
|
+ if (uri.contains("login")) {
|
|
|
+ return "auth";
|
|
|
+ }
|
|
|
+ return "api";
|
|
|
+ }
|
|
|
+}
|