skywalking golang客户端源码解析

7亮 · · 205 次点击 · · 开始浏览    

源码地址

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
}

源码解析

暂略


有疑问加站长微信联系(非本文作者)

本文来自:简书

感谢作者:7亮

查看原文:skywalking golang客户端源码解析

入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:701969077

205 次点击  
加入收藏 微博
暂无回复
添加一条新回复 (您需要 登录 后才能回复 没有账号 ?)
  • 请尽量让自己的回复能够对别人有帮助
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`
  • 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
  • 图片支持拖拽、截图粘贴等方式上传