ELK traceId实现跨服务日志追踪
ELK怎么实现跨服务日志追踪,Trace-Id 具体实现方案及代码_kibana关联其他服务器的日志-CSDN博客
ELK+MDC追踪日志 ---- SpringCloud实现传递_elk的mdc-CSDN博客
SpringBoot之HandlerInterceptor拦截器的使用 ——(一)-CSDN博客
在使用ELK(Elasticsearch, Logstash, Kibana)进行日志管理时,通过traceId
实现日志跟踪是一种常见的做法。traceId
可以帮助我们在分布式系统中追踪请求的完整链路。通过Spring的HandlerInterceptor
,我们可以在请求进入时生成traceId
,并将其传递到日志中。
实现思路
-
生成
traceId
:在请求进入时生成一个唯一的traceId
,并将其存储在MDC
(Mapped Diagnostic Context)中。 -
传递
traceId
:在请求处理过程中,确保traceId
能够传递到各个组件和日志中。 -
清理
traceId
:在请求处理完成后,清理MDC
中的traceId
,避免内存泄漏。
代码实现
1. 创建TraceIdInterceptor
首先,我们需要创建一个HandlerInterceptor
实现类,用于在请求进入时生成traceId
,并在请求完成后清理traceId
。
java
复制
import org.slf4j.MDC; import org.springframework.stereotype.Component; import org.springframework.web.servlet.HandlerInterceptor; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.util.UUID; @Component public class TraceIdInterceptor implements HandlerInterceptor { private static final String TRACE_ID = "traceId"; @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { // 生成唯一的traceId String traceId = UUID.randomUUID().toString(); // 将traceId放入MDC MDC.put(TRACE_ID, traceId); return true; } @Override public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception { // 请求完成后清理MDC中的traceId MDC.remove(TRACE_ID); } }
2. 注册TraceIdInterceptor
接下来,我们需要将TraceIdInterceptor
注册到Spring的拦截器链中。
java
复制
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Configuration; import org.springframework.web.servlet.config.annotation.InterceptorRegistry; import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; @Configuration public class WebConfig implements WebMvcConfigurer { @Autowired private TraceIdInterceptor traceIdInterceptor; @Override public void addInterceptors(InterceptorRegistry registry) { registry.addInterceptor(traceIdInterceptor); } }
3. 配置日志输出traceId
在日志配置文件中,配置日志输出格式,确保traceId
能够被打印出来。以logback.xml
为例:
xml
复制
<configuration> <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender"> <encoder> <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{36} - [%X{traceId}] %msg%n</pattern> </encoder> </appender> <root level="info"> <appender-ref ref="STDOUT" /> </root> </configuration>
运行 HTML
在这个配置中,%X{traceId}
会从MDC
中获取traceId
并输出到日志中。
4. 在代码中使用traceId
在业务代码中,你可以通过MDC
获取traceId
,并将其传递到其他服务或日志中。
java
复制
import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.slf4j.MDC; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RestController; @RestController public class MyController { private static final Logger logger = LoggerFactory.getLogger(MyController.class); @GetMapping("/test") public String test() { // 获取traceId String traceId = MDC.get("traceId"); logger.info("Processing request with traceId: {}", traceId); return "Hello, World!"; } }
总结
通过上述步骤,我们实现了一个简单的traceId
日志跟踪系统。HandlerInterceptor
在请求进入时生成traceId
并将其放入MDC
,在请求完成后清理MDC
。日志配置确保traceId
能够被输出到日志中,从而方便我们在ELK中追踪请求的完整链路。
扩展
-
分布式系统中的
traceId
传递:在微服务架构中,traceId
需要在服务之间传递。可以通过HTTP头、消息队列等方式传递traceId
。 -
异步任务中的
traceId
:在异步任务中,traceId
可能会丢失。可以通过自定义线程池或使用TaskDecorator
来确保traceId
在异步任务中传递。
通过这些扩展,你可以在更复杂的系统中实现全链路的日志跟踪。