opentracing-go原始碼閱讀——資訊攜帶
Propagation
- 跨程式的 trace 資訊傳輸通過 SpanContext 傳遞 baggage 資訊,把 baggage 儲存到 context 上下文中,則需要 key:value, 這個 key 決定了 value 值和 value 型別;
- key:value 儲存到 context 中,需要藉助於讀寫操作;
notice: 這個借鑑了io.Reader和io.Writer等思想,通過組合模式使得實現變得更加靈活
- 目前支援三種 key 值,對應三種 value 值型別,分別是:byte 流、TextMap 和 http.Header;其中後兩者都是 map 結構;只是 RPC 或者 Web 時,用 http.Header,其他使用 TextMap 或者 byte 流;
Baggage 讀寫
目前支援三種型別的 value,BuiltinFormat={Binary=0, TextMap=1, HTTPHeaders=2}, 對於第一種位元流方式,直接通過io.Reader
和io.Writer
方式即可;
對於後兩者的讀寫操作:
type TextMapWriter interface {
Set(key, val string)
}
type TextMapReader interface {
ForeachKey(handler func(key, value string) error) error
}
從 TextMapReader 來看,ForeachKey 的傳參型別是一個函式,使得讀取交給了具體的 trace 系統實現,靈活度高;
Baggage 的 TextMap 和 Http.Header 兩種儲存方法,分別實現了上面兩個介面:
// TextMap
type TextMapCarrier map[string]string
func (c TextMapCarrier) ForeachKey(handler func(key, val string) error) error{
for k, v := range c{
if err := handler(k, v); err!=nil{
return err
}
}
return nil
}
func (c TextMapCarrier) Set(key, val string){
c[key] = val
}
// Http.Header
type HTTPHeadersCarrier http.Header
func (c HTTPHeadersCarrier) Set(key, val string){
h:= http.Header(c)
h.Add(key, val)
}
func (c HTTPHeadersCarrier) ForeachKey(handler func(key, value string) error) error{
for k, vals:= range c{
for _, v := range vals{
if err:= handler(k, v); err !=nil{
return errr
}
}
}
return nil
}
ext/tags
根據 OpenTracing 標準,《OpenTracing APIs》中的資料約定模組,已經在標準中整合了一些常用的 Span Tag。在 opentracing-go 庫中,也就整合了這一部分子集,如:
SpanKind:"span.kind" 代表有關RPC、WEB、訊息釋出與訂閱等關係;這類Span Tag值={"Client", "Server", "Producer", "Consumer"}
第三方庫或者元件 Component: "component"; 這類span tag值表示呼叫的第三方庫或者元件名稱;
取樣率:SamplingPriority: "sampling.priority"; 這類span tag值大於或者等於0,當value>0時,儘量保留這條trace;否則,丟棄這條trace;
peer:這類span tag表示對等的相關資訊,也即呼叫方上游或者下游的相關服務資訊;具體有:
PeerService: "peer.service"; tag值為服務名;
PeerAddress: "peer.address"; tag值為服務連線地址;
PeerHostName:"peer.hostname"; tag值為主機名;
PeerHostIPv4, PeerHostIPv6: "peer.ipv4"和"peer.ipv6"; tag值為IP地址
PeerPort: "peer.port";tag值為服務埠;
HTTP相關tags列表:
HTTPUrl: "http.url"; tag值為http url;
HTTPMethod:"http.method"; tag值為http.method={"get", "post", "delete", "head", ...};
HTTPStatusCode: "http.status_code"; tag值為http.status_code={403, 404, 200, 502, ...};
DB相關tags列表:
DBInstance: "db.instance", tag值為db例項名稱;
DBStatement:"db.statement", tag值為db sql語句;
DBType: "db.type", tag值為db type = {"redis", "mysql", "progresql", ...};
DBUser: "db.user", tag值為訪問db的使用者名稱
// 這裡不給出DBPassword是因為,passwd屬於非常敏感資訊;
// message bus 訊息匯流排tag:
MessageBusDestination: "message_bus.detination", tag值為address;
訊息匯流排,我還不太瞭解;
// error tag: 表示span執行單元過程是否有業務系統發生錯誤,true|false
Error: "error", tag值:true|false;
我們注意到,當跟蹤某一類 tag A 時,如果這類 tag 存在多個指標;這 A.a, A.b, ..., A.z 等方式是非常友好的,便於識別含義,且不會衝突;
上面的這些 tag 都會有相應的讀寫操作:Set, 但是目前沒有發現 Tag 讀取操作, 大多數 tag set 操作類似於:
func (tag xxxTagName) Set(span opentracing.Span, value xxtype){
span.Set(string(tag), value)
}
這裡說明一點: 對於已知的 TagName 和可列舉的 value,直接使用 StartSpanOptions 中的 Apply 方法即可,如:span.kind; 其他的通過 TagName 型別自帶的 Set 實現儲存,這些 tag 資料都是儲存在 StartSpanOptions 的 tags 中
參考資料
更多原創文章乾貨分享,請關注公眾號
- 加微信實戰群請加微信(註明:實戰群):gocnio
相關文章
- opentracing-go原始碼閱讀一Go原始碼
- opentracing-go原始碼閱讀——Log儲存(完結篇)Go原始碼
- 【原始碼閱讀】AndPermission原始碼閱讀原始碼
- 【原始碼閱讀】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原始碼閱讀原始碼
- 【原始碼閱讀】Glide原始碼閱讀之load方法(二)原始碼IDE
- PostgreSQL 原始碼解讀(3)- 如何閱讀原始碼SQL原始碼
- 利用HERE Document攜帶C原始碼原始碼
- JDK原始碼閱讀:Object類閱讀筆記JDK原始碼Object筆記
- Laravel 原始碼閱讀 - QueueLaravel原始碼
- Vollery原始碼閱讀(—)原始碼
- 使用OpenGrok閱讀原始碼原始碼
- 如何閱讀Java原始碼?Java原始碼
- buffer 原始碼包閱讀原始碼
- 原始碼閱讀技巧篇原始碼
- 如何閱讀框架原始碼框架原始碼
- 再談原始碼閱讀原始碼
- Laravel 原始碼閱讀 - EloquentLaravel原始碼
- 如何閱讀jdk原始碼?JDK原始碼
- express 原始碼閱讀(全)Express原始碼
- Vuex原始碼閱讀分析Vue原始碼
- React原始碼閱讀:setStateReact原始碼
- ArrayList原始碼閱讀(增)原始碼
- ThreadLocal原始碼閱讀thread原始碼