basictracer-go原始碼閱讀——SpanRecorder與wire

cdh0805010118發表於2018-07-05

SpanRecorder

SpanRecorder 介面用於 Span 的儲存,也就是擔任 Collector 和 Storage 的職責。它向廠商開放了自定義實現自己的 Collector 和 Storage 服務或者元件;儲存資料={TraceID, SpanID, Sampled, Baggage};

type SpanRecorder interface {
    RecordSpan(span RawSpan)
}

basictracer-go 內部已經實現了一個基於記憶體的 SpanRecorder。SpanRecorder 具體實現賦值是在初始化 globaltracer 時指定的,也即 tracer.options.SpanRecorder 變數值;

基於記憶體的 SpanRecorder 實現:

type InMemorySpanRecorder struct {
    sync.RWMutex
    spans []RawSpan
}

func NewInMemoryRecorder() *InMemorySpanRecorder {
    return new(InMemorySpanRecorder)
}

// 對RawSpan進行收集和儲存工作
func (r *InMemorySpanRecorder) RecordSpan(span RawSpan) {
    r.Lock()
    defer r.Unlock()
    r.spans = append(r.spans, span)
}

// 獲取[]RawSpan的快照,因為瞬時乾淨列表, 只是如果要併發獲取[]RawSpan以及廠商實現不限制記憶體的話,則記憶體猛增。
func (r *InMemorySpanRecorder) GetSpans() []RawSpan {
    r.RLock()
    defer r.RUnlock()
    spans := make([]RawSpan, len(r.spans))
    copy(spans, r.spans)
    return spans
}

// 存在GetSpans和GetSampledSpans兩種方法,主要是因為:
// Tracer和Span都存在Sampled,之間存在一定的關係
// 1. 當Tracer設定這個tracer需要儘量儲存下來時,Tracer.Sampled=true,不用理會Span.Sampled值
// 2. 當Tracer.Sampled=false時,則可以根據span執行單元情況,選擇是否要進行Span保留;
func (r *InMemorySpanRecorder) GetSampledSpans() []RawSpan {
    ... // 所以這個是用來保留取樣的Span, 與Tracer無關
}

// 清空[]RawSpan記憶體儲存
func (r *InMemorySpanRecorder) Reset(){
    r.Lock()
    defer r.Unlock()
    r.spans = nil
}

util

主要用來生成隨機數, 賦值給 TraceID 和 SpanID 值;

wire

wire 為 binaryPropagator 網路傳輸的協議資料流,該協議為 google 的 protobuffer,在 grpc 中廣泛使用。

// bp協議資料格式
message TracerState {
    fixed64 trace_id = 1;
    fixed64 span_id = 2;
    bool sampled =3;
    map<string, string> baggage_items = 4;
}

該協議的資料格式在《basictracer-go 原始碼閱讀——event&propagation》的 binaryPropagator 中通過 Inject 和 Extract 方法說明過。

同時,TracerState 也實現了 DelegatingCarrier 介面,這個在 accessPropagator 中給廠商開放了自定義實現 Carrier 的資料儲存和轉換;這裡不再贅述了。

參考資料

basictracer-go

更多原創文章乾貨分享,請關注公眾號
  • basictracer-go原始碼閱讀——SpanRecorder與wire
  • 加微信實戰群請加微信(註明:實戰群):gocnio

相關文章