莱芜在线头条杭州网站排名seo
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";@Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {// 生成唯一的traceIdString traceId = UUID.randomUUID().toString();// 将traceId放入MDCMDC.put(TRACE_ID, traceId);return true;}@Overridepublic void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {// 请求完成后清理MDC中的traceIdMDC.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 {@Autowiredprivate TraceIdInterceptor traceIdInterceptor;@Overridepublic 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() {// 获取traceIdString 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
在异步任务中传递。
通过这些扩展,你可以在更复杂的系统中实现全链路的日志跟踪。