粗略看了下spring cloud sleuth core源碼,發現內容真的有點多,它支持了不少類型的鏈路追蹤,我就找其中一個比較有表明性的深刻剖析下源碼結構和內容java
@Bean public FilterRegistrationBean traceWebFilter(TraceFilter traceFilter) { FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean( traceFilter); filterRegistrationBean.setDispatcherTypes(ASYNC, ERROR, FORWARD, INCLUDE, REQUEST); filterRegistrationBean.setOrder(TraceFilter.ORDER); return filterRegistrationBean; } @Bean @ConditionalOnMissingBean public TraceFilter traceFilter(BeanFactory beanFactory, SkipPatternProvider skipPatternProvider) { return new TraceFilter(beanFactory, skipPatternProvider.skipPattern()); }
TraceWebMvcConfigurer
類,它會進行攔截器的註冊@Configuration class TraceWebMvcConfigurer extends WebMvcConfigurerAdapter { @Autowired BeanFactory beanFactory; @Bean public TraceHandlerInterceptor traceHandlerInterceptor(BeanFactory beanFactory) { return new TraceHandlerInterceptor(beanFactory); } @Override public void addInterceptors(InterceptorRegistry registry) { registry.addInterceptor(this.beanFactory.getBean(TraceHandlerInterceptor.class)); } }
TraceHandlerInterceptor
類中,preHandle
,afterCompletion
方法能夠看出,這是對請求進行攔截進行span的包裝@Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { String spanName = spanName(handler); boolean continueSpan = getRootSpanFromAttribute(request) != null; Span span = continueSpan ? getRootSpanFromAttribute(request) : getTracer().createSpan(spanName); if (log.isDebugEnabled()) { log.debug("Handling span " + span); } addClassMethodTag(handler, span); addClassNameTag(handler, span); setSpanInAttribute(request, span); if (!continueSpan) { setNewSpanCreatedAttribute(request, span); } return true; }
@Override public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception { if (isErrorControllerRelated(request)) { if (log.isDebugEnabled()) { log.debug("Skipping closing of a span for error controller processing"); } return; } Span span = getRootSpanFromAttribute(request); if (ex != null) { getErrorParser().parseErrorTags(span, ex); } if (getNewSpanFromAttribute(request) != null) { if (log.isDebugEnabled()) { log.debug("Closing span " + span); } Span newSpan = getNewSpanFromAttribute(request); getTracer().continueSpan(newSpan); getTracer().close(newSpan); clearNewSpanCreatedAttribute(request); } }
HttpZipkinSpanReporter
類,,用來進行span
端點提交,而後初始化ZipkinSpanListener
span的監聽器,用來監聽並調用端點提交,以上配置再下圖位置TraceFilter
中的過濾方法doFilter
,這裏會作span
的建立private Span createSpan(HttpServletRequest request, boolean skip, Span spanFromRequest, String name) { if (spanFromRequest != null) { if (log.isDebugEnabled()) { log.debug("Span has already been created - continuing with the previous one"); } return spanFromRequest; } //加入調用鏈路ZipkinHttpSpanExtractor,此鏈路在TraceHttpAutoConfiguration中配置實例化,調用鏈尚未時,返回爲空,做爲頭節點 Span parent = spanExtractor().joinTrace(new HttpServletRequestTextMap(request)); if (parent != null) { if (log.isDebugEnabled()) { log.debug("Found a parent span " + parent + " in the request"); } addRequestTagsForParentSpan(request, parent); spanFromRequest = parent; tracer().continueSpan(spanFromRequest); if (parent.isRemote()) { parent.logEvent(Span.SERVER_RECV); } request.setAttribute(TRACE_REQUEST_ATTR, spanFromRequest); if (log.isDebugEnabled()) { log.debug("Parent span is " + parent + ""); } } else { if (skip) { spanFromRequest = tracer().createSpan(name, NeverSampler.INSTANCE); } else { String header = request.getHeader(Span.SPAN_FLAGS); if (Span.SPAN_SAMPLED.equals(header)) { spanFromRequest = tracer().createSpan(name, new AlwaysSampler()); } else { //建立span節點 spanFromRequest = tracer().createSpan(name); } } spanFromRequest.logEvent(Span.SERVER_RECV); request.setAttribute(TRACE_REQUEST_ATTR, spanFromRequest); if (log.isDebugEnabled()) { log.debug("No parent span present - creating a new span"); } } return spanFromRequest; }
preHandle
方法中,對span
進行包裝,而後把span放入請求頭header中DefaultTracer
中進行span的關閉和spanReporter
的提交