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 条评论
 下一页
  
   
   
   
   
  
  
  
  
  
  
  
  
 