skywalking golang客户端源码解析

源码地址

  • go sdk:https://github.com/SkyAPM/go2sky
  • plugin:https://github.com/SkyAPM/go2sky-plugins 提供了go http、go-restful、gin等框架的trace接入插件,用于服务端和客户端的trace span创建。

go sdk的基本特性

  • 客户端和服务端使用grpc双向stream通信。
  • 可以设置采样率。默认都会上报。
  • 可以自定义logger。
  • 可以自定义上报的缓冲通道长度,默认30000
  • 可以自定义服务实例上报的属性字段。
  • 可以自定义服务实例标识,默认uuid@ipv4。进程重启会发生变化,不建议使用uuid,需要自定义覆盖。
  • 可以自定义trace上报的reporter,除grpcReporter以外都是mock、debug、logger等reporter,不能用于生产环境。如果grpcReporter无法满足需要,可以基于接口重写。
  • 提供gin、go-restful、go http server的trace插件和go http client的trace功能。
  • 一个进程内的同一个trace链路上的多个span(父子span)构成一个segment上报的。不是单个span挨个上报。逻辑上看,一个逻辑segment包含多个父子span,构成一个SegmentObject上报到服务端。

数据结构

spanContext是span的上下文。跨进程通信需要将此对象序列化到协议中,然后从协议中反序列化出此对象。

type SpanContext struct {
    TraceID               string `json:"trace_id"`                //traceId
    ParentSegmentID       string `json:"parent_segment_id"`       //父segmentId
    ParentService         string `json:"parent_service"`          //父service
    ParentServiceInstance string `json:"parent_service_instance"` //父实例
    ParentEndpoint        string `json:"parent_endpoint"`         //父endpoint
    AddressUsedAtClient   string `json:"address_used_at_client"`
    ParentSpanID          int32  `json:"parent_span_id"`          //父spanId
    Sample                int8   `json:"sample"`                  
}

defaultSpan记录span基本信息。持有tracer、时间和spanContext等信息。实现span接口。

type defaultSpan struct {
    Refs          []*propagation.SpanContext    //跨进程通信用的span上下文。
    tracer        *Tracer                       //上报trace用的client封装对象。
    StartTime     time.Time    //span起始时间
    EndTime       time.Time    //span结束时间
    OperationName string       //span操作名称。http是/method/uri
    Peer          string       //span对端地址
    Layer         v3.SpanLayer //span的用途。有数据库、rpc、http、mq、缓存。
    ComponentID   int32        //创建span的组件ID。比如5005是http client;5004是http server。
    Tags          []*common.KeyStringValuePair //span键值对
    Logs          []*v3.Log    //span核心日志
    IsError       bool         //span是否有错误,一般http code不等于200,rpc超时都需要标记error。
    SpanType      SpanType    //span类型。入口端用entry、调用端用exit。 
}

segmentContext是segment上下文,主要用于生成spanId,记录同一个链路父子span的个数等。

  • 每个span都有一个自己的segmentContext对象。记录当前spanId、父spanId。
  • 同一个进程的同一个链路的不同span(即父子span)的segmentContext对象不同,但共用一个spanId生成器、共用同一个segmentId、共用一个collect收集器、共用一个refNum字段。可以说,同一个进程的同一个链路的父子span共用同一个逻辑segmentContext。
type SegmentContext struct {
    TraceID         string //链路唯一Id。如果从协议中解析出SpanContext,则延续使用。没有则随机生成UUID。
    SegmentID       string //段Id。随机生成。父子span共用一个segmentId
    SpanID          int32  //关联的spanId
    ParentSpanID    int32  //关联的span的父spanId
    ParentSegmentID string //父段id,就是自身ID。
    collect         chan<- ReportedSpan //上报span的channel通道。父子span共用一个channel通道。
    refNum          *int32 //当前segment包含多少个span。
    spanIDGenerator *int32 //同一个segment下spanId的生成器,atomic自增。
    FirstSpan       Span `json:"-"`
}

segmentSpanImpl组合defaultSpan和SegmentContext,该对象是真正意义的span。

type segmentSpanImpl struct {
    defaultSpan
    SegmentContext
}

rootSegmentSpan是根span,组合segmentSpanImpl,也就实现span接口。进程内每个trace链路上都有一个起始的根span,用于进程内当前链路上所有span的收尾上报。每个根span创建时会启动单独的协程,循环接收子span或监听trace链路结束信号。根span重新实现了span的End接口,当根span操作end,不仅结束当前根span(设置结束时间),还会往done channel发送信号,通知接收方开始上报当前链路的所有span对象。

type rootSegmentSpan struct {
    *segmentSpanImpl
    notify  <-chan ReportedSpan //接收segmentSpanImpl,和segmentSpanImpl中的collect是同一个数据通道,for循环不断读取。
    segment []ReportedSpan //同一个进程同一个链路的所有segmentSpan的聚合。
    doneCh  chan int32
}

源码解析

暂略

你可能感兴趣的:(skywalking golang客户端源码解析)