basictracer-go原始碼閱讀——examples(完結)
在服務啟動時,開啟兩個 goroutine,一個為 client,終端輸入發出 web 請求;一個為 http server,監聽埠為 8080。這裡不用瀏覽器或者其他做 client 的原因是,需要 client 端建立 trace,這樣才能夠在 client/server 跨程式形成呼叫鏈。 client 直接回車,則結束程式。
在啟動兩個 goroutine 之前,初始化了 global tracer, 並指定了 Collector 和 Storage 於一身的 TrivialRecorder. 它的 RecordSpan 方法只是輸出到終端的 Span 所有相關資訊:操作名、建立時間、生命週期時間、日誌列表長度、上下文攜帶資訊和日誌列表中的每行日誌
其中:dapprish/random.go 沒有作用。
Server
該服務啟動了 http 的 8080 埠服務,接受所有請求,http 服務的網路傳輸資料 Carrier 是採用的 TextMapPropagation 協議
它會在每個請求到來時,會根據 Client 的 SpanContext 資訊建立一個名稱為"ServerSpan"的 Span。這個 DEMO 健壯性差,容易 panic 的原因在於:
如果非下面的Client請求,而是其他web請求進來的,則不會帶有Carrier的網路傳輸資料,則在TextMapPropagation的Extract解析時,報ErrSpanContextNotFound錯誤, 則在server中直接panic掉
獲取 request body 資料流後,通過 Span.Logs 記錄請求資料,並通過 span.Finish 方法儲存 RawSpan 資料={TraceID、SpanID、Sampled 和 Baggage}
Client
client 通過終端輸入傳送 web http POST 請求,它首先建立名稱為"getInput"的 Span, 並在 span 的 logs 中記錄 ctx、user text、返回 response 等內容;以及攜帶除了 TraceID、SpanID、Sampled 和 Baggage{"User": 當前終端登入使用者名稱}, 當 span 生命週期結束時,通過 span.Finish 方法儲存 RawSpan 資訊到記憶體中。
輸入"hello,world",執行結果如下所示:
Enter text (empty string to exit): hello,world
RecordSpan: serverSpan[2018-07-05 14:19:44.151121569 +0800 CST m=+7.236240362, 57.771µs us] --> 1 logs. context: {5671206282793949525 9024173529197870936 false map[user:chenchao]}; baggage: map[user:chenchao]
log 0 @ 2018-07-05 14:19:44.151178152 +0800 CST m=+7.236296945: [request body:hello,world]
RecordSpan: getInput[2018-07-05 14:19:36.916512195 +0800 CST m=+0.001382988, 7.235279179s us] --> 3 logs. context: {5671206282793949525 978135273461507120 false map[User:chenchao]}; baggage: map[User:chenchao]
log 0 @ 2018-07-05 14:19:36.916526835 +0800 CST m=+0.001397628: [ctx:context.Background.WithValue(opentracing.contextKey{}, &basictracer.spanImpl{tracer:(*basictracer.tracerImpl)(0xc4201340c0), event:(func(basictracer.SpanEvent))(nil), Mutex:sync.Mutex{state:1, sema:0x0}, raw:basictracer.RawSpan{Context:basictracer.SpanContext{TraceID:0x4eb42c111de59955, SpanID:0xd9308d94cf3e430, Sampled:false, Baggage:map[string]string{"User":"chenchao"}}, ParentSpanID:0x0, Operation:"getInput", Start:time.Time{wall:0xbec78bfe36a0ddc3, ext:1382988, loc:(*time.Location)(0x14960c0)}, Duration:7235279179, Tags:opentracing.Tags(nil), Logs:[]opentracing.LogRecord{opentracing.LogRecord{Timestamp:time.Time{wall:0xbec78bfe36a116f3, ext:1397628, loc:(*time.Location)(0x14960c0)}, Fields:[]log.Field{log.Field{key:"ctx", fieldType:10, numericVal:0, stringVal:"", interfaceVal:(*context.valueCtx)(0xc4200a6f00)}}}, opentracing.LogRecord{Timestamp:time.Time{wall:0xbec78c0008cf8373, ext:7232936124, loc:(*time.Location)(0x14960c0)}, Fields:[]log.Field{log.Field{key:"user text", fieldType:0, numericVal:0, stringVal:"hello,world", interfaceVal:interface {}(nil)}}}, opentracing.LogRecord{Timestamp:time.Time{wall:0xbec78c0009085b42, ext:7236661387, loc:(*time.Location)(0x14960c0)}, Fields:[]log.Field{log.Field{key:"response", fieldType:10, numericVal:0, stringVal:"", interfaceVal:(*http.Response)(0xc42018a090)}}}}}, numDroppedLogs:0})]
log 1 @ 2018-07-05 14:19:44.147817331 +0800 CST m=+7.232936124: [user text:hello,world]
log 2 @ 2018-07-05 14:19:44.151542594 +0800 CST m=+7.236661387: [response:&{200 OK 200 HTTP/1.1 1
1 map[Date:[Thu, 05 Jul 2018 06:19:44 GMT] Content-Length:[0]] {} 0 [] false false map[] 0xc42014c000
<nil>}]
總結
opentracing-go 庫是對 OpenTracing 標準的程式碼正規化表達,而 basictracer-go 是對前者的最小子集擴充套件和實現,理論上這個 basictracer-go 已經可以進行業務開發和使用了,但是這個庫還非常弱,主要表現在:collector 和 storage 基於一身,且還是基於記憶體的,沒有 dashboard UI 支援,無法用於生產。雖然無法用於生產,但是 Span 的實現,Carrier 的支援已經做得很好了,同時這個庫希望廠商採用 OpenTracing 標準實現時,可以把它作為中間層或者元件使用,因為它對廠商開放了一些介面自定義實現,例如:Carrier 的 AccessPropagation(IPC/RPC 資料轉換和儲存),SpanRecord 介面(RawSpan 資訊儲存)。但是廠商也可以完全自己基於 opentracing-go 設計一套完整的分散式跟蹤系統,不用再在 opentracing-go 和廠商中間加一層 basictracer-go。
- 加微信實戰群請加微信(註明:實戰群):gocnio
相關文章
- basictracer-go原始碼閱讀二——SpanGo原始碼
- basictracer-go原始碼閱讀——SpanRecorder與wireGo原始碼
- basictracer-go原始碼閱讀——event&propagationGo原始碼
- opentracing-go原始碼閱讀——Log儲存(完結篇)Go原始碼
- 【原始碼閱讀】AndPermission原始碼閱讀原始碼
- ConcurrentHashMap 原始碼閱讀小結HashMap原始碼
- 【原始碼閱讀】Glide原始碼閱讀之with方法(一)原始碼IDE
- 【原始碼閱讀】Glide原始碼閱讀之into方法(三)原始碼IDE
- ReactorKit原始碼閱讀React原始碼
- AQS原始碼閱讀AQS原始碼
- CountDownLatch原始碼閱讀CountDownLatch原始碼
- HashMap 原始碼閱讀HashMap原始碼
- delta原始碼閱讀原始碼
- 原始碼閱讀-HashMap原始碼HashMap
- NGINX原始碼閱讀Nginx原始碼
- Mux 原始碼閱讀UX原始碼
- HashMap原始碼閱讀HashMap原始碼
- fuzz原始碼閱讀原始碼
- RunLoop 原始碼閱讀OOP原始碼
- express 原始碼閱讀Express原始碼
- muduo原始碼閱讀原始碼
- stack原始碼閱讀原始碼
- Nacos2.X原始碼閱讀總結原始碼
- 【原始碼閱讀】Glide原始碼閱讀之load方法(二)原始碼IDE
- PostgreSQL 原始碼解讀(3)- 如何閱讀原始碼SQL原始碼
- System.Collections.Generic 原始碼閱讀總結原始碼
- JDK原始碼閱讀:Object類閱讀筆記JDK原始碼Object筆記
- Laravel 原始碼閱讀 - QueueLaravel原始碼
- Vollery原始碼閱讀(—)原始碼
- 使用OpenGrok閱讀原始碼原始碼
- 如何閱讀Java原始碼?Java原始碼
- buffer 原始碼包閱讀原始碼
- 原始碼閱讀技巧篇原始碼
- 如何閱讀框架原始碼框架原始碼
- 再談原始碼閱讀原始碼
- Laravel 原始碼閱讀 - EloquentLaravel原始碼
- 如何閱讀jdk原始碼?JDK原始碼
- express 原始碼閱讀(全)Express原始碼