sleuth和zipkin调试流程图(手工创建span上报)
2020-03-06 17:52:02 1 举报
springcloud的sleuth分布式链路方案客户端手动创建span上报源码流程图
作者其他创作
大纲/内容
Y
跟踪进去
N
关闭方法里执行后续所有的逻辑
throw new IllegalStateException(\t\t\t\t\t\t\"Span for \" + this.name + \" has not been started\");
手工创建span上报流程图
循环加入父span到span上下文,此处只有一个父span,所以while只执行一次
SpanContext current = CURRENT_SPAN.get();
org.springframework.cloud.sleuth.instrument.web.client.TraceHttpResponse#close
span != null && parent != null
span.isExportable()根据配置判断是否需要上报
org.springframework.cloud.sleuth.instrument.web.client.AbstractTraceHttpRequestInterceptor#finish
执行关闭response和关闭span
添加第三个span的cs事件并关闭且上报
org.springframework.cloud.sleuth.trace.DefaultTracer#close
判断span的标签是否含有LC,此时是刚手工创建的span,所有不包含,继续往下执行此时的processid为unknown的字节码,创建lc的BinaryAnnotation组件,并加入span的set集合中
org.springframework.cloud.sleuth.trace.SpanContextHolder#close(org.springframework.cloud.sleuth.trace.SpanContextHolder.SpanFunction)
org.springframework.cloud.sleuth.zipkin.ZipkinSpanListener#convert
this.tracer.close(this.currentSpan());
结束:return null
关闭第三个span
!this.pending.offer(span)
org.springframework.web.client.RestTemplate#doExecute
创建第二个新span
this.spanMetricReporter.incrementAcceptedSpans(1);
log(\"With parent: {}\
org.springframework.cloud.sleuth.zipkin.ZipkinSpanListener#report
span.stop();
执行上报所有逻辑
span.equals(cur)
if (span.tags().containsKey(Constants.LOCAL_COMPONENT)) { return; } byte[] processId = span.getProcessId() != null ? span.getProcessId().toLowerCase().getBytes(UTF_8) : UNKNOWN_BYTES; BinaryAnnotation component = BinaryAnnotation.builder() .type(BinaryAnnotation.Type.STRING) .key(\"lc\") // LOCAL_COMPONENT .value(processId) .endpoint(this.endpointLocator.local()).build(); zipkinSpan.addBinaryAnnotation(component);
org.springframework.cloud.sleuth.metric.CounterServiceBasedSpanMetricReporter#incrementAcceptedSpans@Override public void incrementAcceptedSpans(long quantity) { for (int i = 0; i < quantity; i++) { this.counterService.increment(this.acceptedSpansMetricName); } }
抛异常:\"Tried to close span but \" + \"it is not the current span: \" + span\t\t\t\t\t\t\t+ \". You may have forgotten to close or detach \" + cur
不做任何操作
log.error(\"Zipkin doesn't support spans with multiple parents. Omitting \" + \"other parents for \" + span);
CURRENT_SPAN.remove();
创建span对象
跟踪进去:加时间日志和关闭当前手动创建的span
手工创建span上报后,通过拦截器关闭并上报第三个span--->后台接口返回时上报
final Span savedSpan = span.getSavedSpan();
!isTracing()
org.springframework.cloud.sleuth.zipkin.ZipkinSpanListener#ensureServerAddr
跟踪进去convert方法
关闭当前span以及其所有父span
N:继续给span赋值属性
this.interceptor.finish();
org.springframework.cloud.sleuth.trace.SpanContextHolder#CURRENT_SPAN---------------------------------private static final ThreadLocal<SpanContext> CURRENT_SPAN = new NamedThreadLocal<>( \"Trace Context\");
org.springframework.cloud.sleuth.trace.DefaultTracer#createSpan(java.lang.String)
this.spanReporter.report(span);
org.springframework.cloud.sleuth.zipkin.ZipkinSpanListener#notClientOrServer
this.reporter.report(convert(span));
Add annotations from the sleuth Span.
结束: return savedSpan;
while (current != null) { current = current.parent; spanFunction.apply(current != null ? current.span : null); if (current != null) { if (!current.autoClose) { CURRENT_SPAN.set(current); current = null; } } }
org.springframework.cloud.sleuth.zipkin.ZipkinSpanListener#addZipkinAnnotations
判断span中logs的size是否为0,第一个span肯定为0,如果不为0,则判断log中是否有cr或者sr事件,如果有则返回false
savedSpan != null && span.getParents().contains(savedSpan.getSpanId())
通过close方法中传入的span获取需要保存的span
MDC.remove(Span.SPAN_ID_NAME);\t\t\tMDC.remove(Span.SPAN_EXPORT_NAME);\t\t\tMDC.remove(Span.TRACE_ID_NAME);
跟踪进去report方法
zipkinSpan.timestamp(span.getBegin() * 1000L); zipkinSpan.duration(span.getAccumulatedMillis() * 1000L); zipkinSpan.traceId(span.getTraceId());
for (Log log : span.logs()) { if (ZIPKIN_START_EVENTS.contains(log.getEvent())) { return false; } } return true;
ResponseEntity<String> forEntity = restTemplate.getForEntity(new URI(\"http://localhost:\"+otherappPort+\"/getTime\
拦截器TraceRestTemplateInteceptor------------------------* Interceptor that verifies whether the trance and span id has been set on the request * and sets them if one or both of them are missing.
(close方法唯一的入参span)span == null
调用成员变量spanReporter的report方法
此拦截器为TraceHttpResponse的成员变量
判断是否是起始span判断是否有父span
什么都不做
org.slf4j.MDC#remove日志删除
org.springframework.cloud.sleuth.zipkin.ZipkinSpanListener#hasClientSend
跟踪进去:循环对父span调用logStoppedSpan
span.getParents().size() > 0
hasClientSend(span)
close方法唯一的入参和当前span上下文中的span是否相等
Y:错误提示只能有一个父span
this.end = System.currentTimeMillis();
org.springframework.cloud.sleuth.Span#stop
zipkinSpan.parentId(span.getParents().get(0));
不做任何操作即计数器不减1
currentSpan().logEvent(Span.CLIENT_RECV);
this.begin == 0
span.getParents().size() > 1
/**\t * Close the current span and all parents that can be auto closed.\t * On every iteration a function will be applied on the closed Span.\t */
zipkinSpan.id(span.getSpanId()); if (StringUtils.hasText(span.getName())) { zipkinSpan.name(span.getName()); } return zipkinSpan.build();
notClientOrServer(span)
减去1this.spanMetricReporter.incrementDroppedSpans(1)
finally(关闭此新建的span)
private boolean hasClientSend(Span span) {\t\tfor (org.springframework.cloud.sleuth.Log log : span.logs()) {\t\t\tif (Constants.CLIENT_SEND.equals(log.getEvent())) {\t\t\t\treturn !span.tags().containsKey(Constants.SERVER_ADDR);\t\t\t}\t\t}\t\treturn false;\t}
关闭第二个span
this.end == 0
this.delegate.close();
org.springframework.cloud.sleuth.zipkin.HttpZipkinSpanReporter#report
Span cur = SpanContextHolder.getCurrentSpan();
跟踪进去实际上就是给此span的结束时间赋值
取第一个父spanID
zipkin.Span.Builder zipkinSpan = zipkin.Span.builder();
0 条评论
下一页