class RpcSofaTracer extends Tracer {

    @Override
    public void startRpc(SofaRequest request) {
        //客户端的启动
        SofaTraceContext sofaTraceContext = SofaTraceContextHolder.getSofaTraceContext();
        SofaTracerSpan serverSpan = sofaTraceContext.pop();

        SofaTracerSpan clientSpan = (SofaTracerSpan) this.sofaTracer.buildSpan(request.getInterfaceName())
            .asChildOf(serverSpan)
            .withTag(Tags.SPAN_KIND.getKey(), Tags.SPAN_KIND_CLIENT)
            .start();

        if (RpcInternalContext.isAttachmentEnable()) {
            RpcInternalContext context = RpcInternalContext.getContext();
            clientSpan
                .setTag(RpcSpanTags.LOCAL_APP, (String) context.getAttachment(RpcConstants.INTERNAL_KEY_APP_NAME));
            clientSpan.setTag(RpcSpanTags.PROTOCOL,
                (String) context.getAttachment(RpcConstants.INTERNAL_KEY_PROTOCOL_NAME));
            SofaTracerSpanContext spanContext = clientSpan.getSofaTracerSpanContext();
            if (spanContext != null) {
                context.setAttachment(RpcConstants.INTERNAL_KEY_TRACE_ID, spanContext.getTraceId());
                context.setAttachment(RpcConstants.INTERNAL_KEY_SPAN_ID, spanContext.getSpanId());
            }
        }

        clientSpan.setTag(RpcSpanTags.SERVICE, request.getTargetServiceUniqueName());
        clientSpan.setTag(RpcSpanTags.METHOD, request.getMethodName());
        clientSpan.setTag(RpcSpanTags.CURRENT_THREAD_NAME, Thread.currentThread().getName());

        //需要主动缓存自己的 serverSpan,原因是:asChildOf 关注的是 spanContext
        clientSpan.setParentSofaTracerSpan(serverSpan);
        //push
        sofaTraceContext.push(clientSpan);
    }

    public  RpcSofaTracer();

}