MDC implementiert globale TraceId (Vollversion)

Was ist MDC?

MDC ist ein Protokollierungstool in Java. Die zugrunde liegende Implementierung ist die Kapselung von ThreadLocal, um die Verfolgung und Speicherung von Aufruflinks auf Thread-Ebene in Form von kv zu implementieren

TraceId generieren

Generierungsregeln: Server-IP + ID-Generierungszeit + automatische Inkrementierungssequenz + aktuelle Prozessnummer

import java.net.InetAddress;
import java.net.NetworkInterface;
import java.util.Enumeration;
import java.util.concurrent.atomic.AtomicInteger;
import org.apache.commons.lang3.StringUtils;

public class TraceIdGenerator {

  private static String IP_16 = "ffffffff";
  private static AtomicInteger count = new AtomicInteger(1000);

  public static String P_ID_CACHE = null;

  static {
    try {
      String ipAddress = getInetAddress();
      if (ipAddress != null) {
        IP_16 = getIP_16(ipAddress);
      }
    } catch (Throwable e) {
      // ignore
    }
  }

  private static String getTraceId(String ip, long timestamp, int nextId) {
    StringBuilder appender = new StringBuilder(30);
    appender.append(ip).append(timestamp).append(nextId).append(getPID());
    return appender.toString();
  }

  public static String generate() {
    return getTraceId(IP_16, System.currentTimeMillis(), getNextId());
  }

  private static String getIP_16(String ip) {
    String[] ips = ip.split("\\.");
    StringBuilder sb = new StringBuilder();
    for (String column : ips) {
      String hex = Integer.toHexString(Integer.parseInt(column));
      if (hex.length() == 1) {
        sb.append('0').append(hex);
      } else {
        sb.append(hex);
      }
    }
    return sb.toString();
  }

  private static int getNextId() {
    for (; ; ) {
      int current = count.get();
      int next = (current > 9000) ? 1000 : current + 1;
      if (count.compareAndSet(current, next)) {
        return next;
      }
    }
  }

  public static String getInetAddress() {
    try {
      Enumeration<NetworkInterface> interfaces = NetworkInterface.getNetworkInterfaces();
      InetAddress address = null;
      while (interfaces.hasMoreElements()) {
        NetworkInterface ni = interfaces.nextElement();
        Enumeration<InetAddress> addresses = ni.getInetAddresses();
        while (addresses.hasMoreElements()) {
          address = addresses.nextElement();
          if (!address.isLoopbackAddress() && address.getHostAddress().indexOf(":") == -1) {
            return address.getHostAddress();
          }
        }
      }
      return null;
    } catch (Throwable t) {
      return null;
    }
  }

  @SuppressWarnings("AbbreviationAsWordInName")
  public static String getPID() {
    // Check pid is cached.
    if (P_ID_CACHE != null) {
      return P_ID_CACHE;
    }
    String processName = java.lang.management.ManagementFactory.getRuntimeMXBean().getName();

    if (StringUtils.isBlank(processName)) {
      return StringUtils.EMPTY;
    }

    String[] processSplitName = processName.split("@");

    if (processSplitName.length == 0) {
      return StringUtils.EMPTY;
    }

    String pid = processSplitName[0];

    if (StringUtils.isBlank(pid)) {
      return StringUtils.EMPTY;
    }
    P_ID_CACHE = pid;
    return pid;
  }
}

MDC-Paket

import com.google.common.collect.Sets;
import java.util.Optional;
import java.util.Set;
import org.slf4j.MDC;

@SuppressWarnings("AbbreviationAsWordInName")
public class MDCUtil {
  String TRACE_ID = "TRACE_ID";
  private static final Set<String> MDC_KEYs = Sets.newHashSet(TRACE_ID);

  private MDCUtil() {}

  public static void putTraceId() {
    putTraceId(TraceIdGenerator.generate());
  }

  public static void putTraceId(String traceId) {
    if (MDC.get(TRACE_ID) == null) {
      MDC.put(TRACE_ID, traceId);
    }
  }

  public static Optional<String> getTraceId() {
    String traceId = MDC.get(TRACE_ID);
    return traceId == null ? Optional.empty() : Optional.of(traceId);
  }

  public static void clear() {
    MDC_KEYs.forEach(key -> MDC.remove(TRACE_ID));
  }
}

globaler TraceId-Interceptor

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.web.servlet.HandlerInterceptor;

@RequiredArgsConstructor
@Service
@Slf4j
public class TraceIdInterceptor implements HandlerInterceptor {

  @Override
  public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
      throws Exception {
    MDCUtil.putTraceId();
    return HandlerInterceptor.super.preHandle(request, response, handler);
  }

  @Override
  public void afterCompletion(
      HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
      throws Exception {
    MDCUtil.clear();
    HandlerInterceptor.super.afterCompletion(request, response, handler, ex);
  }
}

Interceptor-Konfiguration

import lombok.RequiredArgsConstructor;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

@Configuration
@RequiredArgsConstructor
public class TraceIdConfig implements WebMvcConfigurer {

  private final TraceIdInterceptor traceIdInterceptor;

  @Override
  public void addInterceptors(InterceptorRegistry registry) {
    registry.addInterceptor(traceIdInterceptor).addPathPatterns("/**");
  }
}

Supongo que te gusta

Origin blog.csdn.net/qq_38685503/article/details/130325172
Recomendado
Clasificación