安徽鲁班建设集团网站,公司注册如何网上核名,同ip网站是怎么做的,网站策划书的意义背景#xff1a;
随着业务的复杂化、解耦化#xff0c;运维人员和开发人员需要对请求链路跟踪来快速发现和定位问题#xff0c;基于应用已经集成了SkyWalking的前提下#xff0c;如何通过获取SkyWalking生成的统一traceId并加入打印日志中#xff0c;方便开发人员能够根据…背景
随着业务的复杂化、解耦化运维人员和开发人员需要对请求链路跟踪来快速发现和定位问题基于应用已经集成了SkyWalking的前提下如何通过获取SkyWalking生成的统一traceId并加入打印日志中方便开发人员能够根据链路ID快速搜索单个请求的全链路日志呢
基本思路
trace-id的生成
结合apm-toolkit-trace提供的工具类获取请求的trace-id前提是应用已经集成对接了SkyWalking
trace-id的存放
一种轻量级的实现通过 MDC 机制将请求的 trace-id 放入到MDC中在日志打印时通过 MDC 中的 trace-id 将同一个请求的每一条日志串联起来。因为 MDC 是线程隔离且安全的。
trace-id的打印
通过修改logback.xml配置中pattern增加输出参数%X{traceId}来控制。
trace-id存放的触发机制
通常实现方式采用增加日志拦截器的做法将拦截服务所有外部请求在请求前置处理中将生成trace-id并保存入MDC中。
代码示例
通用做法-开发三板斧依赖、配置、注解与编码
依赖
!-- skywalking依赖包 打印traceid --
dependencygroupIdorg.apache.skywalking/groupIdartifactIdapm-toolkit-trace/artifactIdversion8.7.0/version
/dependency
配置
?xml version1.0 encodingUTF-8?
configuration debugfalse scantrue scanPeriod1 secondsjmxConfigurator/contextNamelogback/contextNamespringProperty scopecontext namemodule_name sourcespring.application.name/!-- 读取apollo配置中心设置的变量 --springProperty scopecontext nameversion sourceapp.version/springProperty scopecontext nameenv sourceapp.env/timestamp keylog_date datePatternyyyy-MM-dd/!--自定义输出 --appender nameSTDOUT classch.qos.logback.core.ConsoleAppenderencoderpattern%d{yyyy-MM-dd HH:mm:ss.SSS} - thead%thread - level%-5level - class%logger{20} - token%X{token} - traceId%X{traceId} - content%msg%n/pattern/encoder/appender!-- 日志输出级别 --root leveldebugappender-ref refSTDOUT//root/configuration
编码
(1) 自定义拦截器LoggerInterceptor
package com.zzia.demo.interceptor;import org.slf4j.MDC;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;import org.apache.skywalking.apm.toolkit.trace.TraceContext;Component
public class LoggerInterceptor implements HandlerInterceptor {/*** return 返回 true 放行、放回 false 拦截*/Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {System.out.println(进入拦截器前置通知 request.getRequestURI());// 过滤掉确认的 options 请求if (OPTIONS.equals(request.getMethod())) {return true;}// 单链路上下文信息存入MDC// 请求凭证String token request.getHeader(__ub_token);MDC.put(token, token);//每次请求生成唯一的请求标识作为内部链路的日志追踪标识MDC.put(traceId, TraceContext.traceId());// 业务身份字段可扩展加入String userId 123456;MDC.put(userId, userId);if (token ! null) {return true;}return false;}Overridepublic void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {System.out.println(后置通知);}Overridepublic void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {System.out.println(最终通知);MDC.clear();}
}(2) 注册拦截器
package com.zzia.demo.interceptor;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 MyLoggerConfigurer implements WebMvcConfigurer {AutowiredLoggerInterceptor myInterceptor;Overridepublic void addInterceptors(InterceptorRegistry registry) {registry.addInterceptor(myInterceptor) // 添加自定义拦截器.excludePathPatterns(/index) // 设置放行路径.addPathPatterns(/**); // 设置拦截路径}
}演示效果 说明本示例的前置准备参见文章Spring boot 集成Skywalking_幽幽之心的博客-CSDN博客