Skywalking系列学习之agent收集trace数据

前言

  在上篇文章《SkyWalking系列学习之环境搭建以及分析如何类增强》中已经知道业务系统通过-javaagent引入代理,通过ByteBuddy对指定的类做增强处理。下面介绍Skywalking-Java怎样收集trace数据

实例方法增强入口InstMethodsInter#intercept

  1. 在入口打上条件断点,准确分析Skywalking-Java怎样收集trace数据
    在这里插入图片描述
  2. 分析InstMethodsInter#intercept整体结构发现,就是在原有方法前后做了拦截处理(重点)
    在这里插入图片描述

InstMethodsInter前置处理

	public void beforeMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class<?>[] argumentsTypes,
                             MethodInterceptResult result) throws Throwable {
         // 构建操作名,例如发送get请求 --> GET:/demo/hello                    
    	String operationName = this.buildOperationName(method, httpServletRequest.getMethod(),
                                                                   (EnhanceRequireObjectCache) objInst.getSkyWalkingDynamicField());
        // 创建EntrySpan                                                          
        AbstractSpan span = ContextManager.createEntrySpan(operationName, contextCarrier);        
        //为EntrySpan打url的tag
        Tags.URL.set(span, httpServletRequest.getRequestURL().toString());
        //为EntrySpan打http.method的tag
        Tags.HTTP.METHOD.set(span, httpServletRequest.getMethod());
                                                  
    }                         
  1. 在执行业务方法前,
    1.1 创建TracingContext,并初始化segment属性
    1.2 创建EntrySpan,放入activeSpanStack有序队列中。
  2. 业务方法内执行http远程请求前,创建ExitSpan,放入activeSpanStack有序队列中。执行完后从activeSpanStack取出
  3. 整个业务方法执行完后,将trace信息存入buffer中

创建EntrySpan

  1. EntrySpan是入口Span,用于服务提供者(Service Provider) ,例如Tomcat
    在这里插入图片描述
  2. Agent 会在Tomcat 定义的方法切面,创建 EntrySpan对象,也会在SpringMVC定义的方法切面,创建EntrySpan对象
    2.1 Agent只会在第一个方法切面,生成 EntrySpan 对象,第二个方法切面,栈深度+ 1(通过这样的方式,保持一个 TraceSegment 有且仅有一个 EntrySpan 对象)
    在这里插入图片描述

创建ExitSpan

  1. 在业务方法中发起http请求,执行httpClient.execute(httpGet)时会被HttpClientExecuteInterceptor拦截
    public void beforeMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class<?>[] argumentsTypes,
                             MethodInterceptResult result) throws Throwable {
            // operationName = /v1.0/menu/viewCount                 
            String operationName = requestURI;
            // 创建ExitSpan
            AbstractSpan span = ContextManager.createExitSpan(operationName, contextCarrier, remotePeer);
        
     }
    
  2. 创建ExitSpan,设置parentSpanId为activeSpanStack的最后一个span,并将ExitSpan放入activeSpanStack队列最后
    在这里插入图片描述

InstMethodsInter后置处理

  1. 通过ContextManager#stopSpan停止链路追踪,最终在创建EntrySpan地方完全终止(例如tomcat)
    1.1 如果stackDepth-1为0表示已经完成,将该span添加到TraceSegment中,并从队列StackBasedTracingSpan里弹出
    // TracingContext
     public boolean stopSpan(AbstractSpan span) {
        AbstractSpan lastSpan = peek();
        if (lastSpan == span) {
            if (lastSpan instanceof AbstractTracingSpan) {
                AbstractTracingSpan toFinishSpan = (AbstractTracingSpan) lastSpan;
               // 判断EntrySpan的stackDepth-1后是否为0,是则将该span添加到TraceSegment中
                if (toFinishSpan.finish(segment)) {
                   // 从队列里弹出 --> StackBasedTracingSpan#finish
                    pop();
                }
            } else {
                pop();
            }
        } else {
            throw new IllegalStateException("Stopping the unexpected span = " + span);
        }
    	// 如果结束则trace线程记录在buffer中
        finish();
        return activeSpanStack.isEmpty();
    }
    
  2. TraceSegmentServiceClient记录traceSegment,并存储在buffer中
    在这里插入图片描述

ConsumerThread线程处理TraceSegment

  1. ConsumerThread线程拉去buffer数据,让TraceSegmentServiceClient消费处理
     private boolean consume(List<T> consumeList) {
          for (DataSource dataSource : dataSources) {
          		// 从buffer中读取数据存放在consumeList中
               dataSource.obtain(consumeList);
           }
    
           if (!consumeList.isEmpty()) {
               try {
               		// 消费者消费数据
                   consumer.consume(consumeList);
               } catch (Throwable t) {
                   consumer.onError(consumeList, t);
               } finally {
                   consumeList.clear();
               }
               return true;
           }
           consumer.nothingToConsume();
           return false;
    }
    
  2. 将TraceSegment转换为SegmentObject,通过grpc传输给Server端
    在这里插入图片描述

束语

  本篇文章通过业务方法内发起http调用示例来debug SkyWalking的链路是如何形成以及怎样传递Server端。后续会分析Server端如何处理SegmentObject

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值