package net.dubboclub.tracing.client; import com.alibaba.dubbo.common.Constants; import com.alibaba.dubbo.common.extension.ExtensionLoader; import com.alibaba.dubbo.common.utils.ConfigUtils; import com.alibaba.dubbo.common.utils.StringUtils; import com.alibaba.dubbo.rpc.RpcContext; import net.dubboclub.tracing.api.Annotation; import net.dubboclub.tracing.api.BinaryAnnotation; import net.dubboclub.tracing.api.Endpoint; import net.dubboclub.tracing.api.Span; import net.dubboclub.tracing.client.util.GUId; import net.dubboclub.tracing.client.util.Sampler; /** * Created by Zetas on 2016/7/8. */ public class Tracer { private SyncTransfer syncTransfer = ExtensionLoader.getExtensionLoader(SyncTransfer.class) .getExtension(ConfigUtils.getProperty(DstConstants.SYNC_TRANSFER_TYPE,DstConstants.DEFAULT_SYNC_TRANSFER)); public void init(){ syncTransfer.start(); } public void beforeInvoke(boolean isConsumerSide) { if (isConsumerSide) { String traceId = createConsumerSideTraceId(); if(traceId!=null){ createConsumerSideSpan(); addClientSendAnnotation(); } } else{ createProvideSideTraceId(); createProviderSideSpan(); addServerReceiveAnnotation(); } setAttachment(); } public void afterInvoke(boolean isConsumerSide) { if (isConsumerSide) { addClientReceiveAnnotation(); } else{ addServerSendAnnotation(); } send(); } private void send() { //弹出栈顶span Span span = ContextHolder.popSpan(); if (span != null) { syncTransfer.syncSend(span); } } public void addException(Throwable throwable) { Span span = ContextHolder.getSpan(); if (span != null) { Endpoint endpoint = createEndpoint(); BinaryAnnotation annotation = new BinaryAnnotation(); annotation.setKey(DstConstants.EXCEPTION); annotation.setType(throwable.getClass().getName()); annotation.setValue(throwable.getMessage()); annotation.setHost(endpoint); span.addAnnotation(annotation); } } private Span createConsumerSideSpan() { if(ContextHolder.isSample()){ Span span = new Span(); span.setId(GUId.singleton().nextId()); Span parentSpan = ContextHolder.getSpan(); if (parentSpan != null) { span.setParentId(parentSpan.getId()); span.setTraceId(parentSpan.getTraceId()); } else { span.setTraceId(ContextHolder.getTraceId()); } span.setServiceName(getServiceName()); span.setName(getMethodName()); ContextHolder.setSpan(span); } return ContextHolder.getSpan(); } private Span createProviderSideSpan() { RpcContext rpcContext = RpcContext.getContext(); String traceId = rpcContext.getAttachment(DstConstants.DST_TRACE_ID); String spanId = rpcContext.getAttachment(DstConstants.DST_SPAN_ID); String parentSpanId = rpcContext.getAttachment(DstConstants.DST_PARENT_SPAN_ID); if (StringUtils.isNotEmpty(traceId) && StringUtils.isNotEmpty(spanId)) {//只需要判断traceId和spanid即可 Span span = new Span(); span.setId(spanId); span.setParentId(parentSpanId); span.setTraceId(traceId); span.setServiceName(getServiceName()); span.setName(getMethodName()); ContextHolder.setSpan(span); } return ContextHolder.getSpan(); } private String createConsumerSideTraceId() { String traceId = ContextHolder.getTraceId(); if (StringUtils.isBlank(traceId)) {//启动一个新的链路 if(ContextHolder.isSample()&&Sampler.isSample(getServiceName())){ ContextHolder.setTraceId(GUId.singleton().nextId()); }else{ ContextHolder.setLocalSample(false); } } return ContextHolder.getTraceId(); } private String createProvideSideTraceId() { RpcContext rpcContext = RpcContext.getContext(); String isSample = rpcContext.getAttachment(DstConstants.DST_IS_SAMPLE); if(StringUtils.isNotEmpty(isSample)){ ContextHolder.setLocalSample(Boolean.valueOf(isSample)); } String traceId = rpcContext.getAttachment(DstConstants.DST_TRACE_ID); if (StringUtils.isBlank(traceId)) { ContextHolder.setTraceId(GUId.singleton().nextId()); } else { ContextHolder.setTraceId(traceId); } return ContextHolder.getTraceId(); } private void setAttachment() { RpcContext rpcContext = RpcContext.getContext(); String traceId = ContextHolder.getTraceId(); rpcContext.setAttachment(DstConstants.DST_IS_SAMPLE,ContextHolder.isSample()+""); if (traceId != null) { rpcContext.setAttachment(DstConstants.DST_TRACE_ID, traceId); } Span span = ContextHolder.getSpan(); if (span != null) { rpcContext.setAttachment(DstConstants.DST_SPAN_ID, span.getId()); rpcContext.setAttachment(DstConstants.DST_PARENT_SPAN_ID, span.getParentId()); } } private Endpoint createEndpoint() { Endpoint endpoint = new Endpoint(); endpoint.setApplicationName(getApplicationName()); endpoint.setIp(getIp()); endpoint.setPort(getPort()); return endpoint; } private long currentTimeMillis() { return System.currentTimeMillis(); } private void addClientSendAnnotation() { addAnnotation(Annotation.CLIENT_SEND); } private void addClientReceiveAnnotation() { addAnnotation(Annotation.CLIENT_RECEIVE); } private void addServerSendAnnotation() { addAnnotation(Annotation.SERVER_SEND); } private void addServerReceiveAnnotation() { addAnnotation(Annotation.SERVER_RECEIVE); } private void addAnnotation(String value) { Span span = ContextHolder.getSpan(); if (span != null) { Endpoint endpoint = createEndpoint(); Annotation annotation = new Annotation(); annotation.setValue(value); annotation.setHost(endpoint); annotation.setTimestamp(currentTimeMillis()); span.addAnnotation(annotation); } } private String getApplicationName() { return RpcContext.getContext().getUrl().getParameter(Constants.APPLICATION_KEY); } private String getServiceName() { return RpcContext.getContext().getUrl().getServiceInterface(); } private String getMethodName() { return RpcContext.getContext().getMethodName(); } private String getIp() { return RpcContext.getContext().getLocalHost(); } private Integer getPort() { return RpcContext.getContext().getLocalPort(); } }