opentracing Extract函数分析
看的是MockTracer的代码在https://github.com/opentracing/opentracing-go/blob/10b1cf09e00bdc84234b8c7a4b4d4e4afe64de87/mocktracer/mocktracer.go#L110
首先根据format找到匹配的解压缩对象,调用Extract
```go
// Extract belongs to the Tracer interface.
func (t *MockTracer) Extract(format interface{}, carrier interface{}) (opentracing.SpanContext, error) {
extractor, ok := t.extractors
if !ok {
return nil, opentracing.ErrUnsupportedFormat
}
return extractor.Extract(carrier)
}
```
我们看new生成部分
这里看到注册了两个Extractor,分别是opentracing.TextMap和opentracing.HTTPHeaders
```go
// New returns a MockTracer opentracing.Tracer implementation that's intended
// to facilitate tests of OpenTracing instrumentation.
func New() *MockTracer {
t := &MockTracer{
finishedSpans: []*MockSpan{},
startedSpans:[]*MockSpan{},
injectors: make(mapInjector),
extractors: make(mapExtractor),
}
// register default injectors/extractors
textPropagator := new(TextMapPropagator)
t.RegisterInjector(opentracing.TextMap, textPropagator)
t.RegisterExtractor(opentracing.TextMap, textPropagator)
httpPropagator := &TextMapPropagator{HTTPHeaders: true}
t.RegisterInjector(opentracing.HTTPHeaders, httpPropagator)
t.RegisterExtractor(opentracing.HTTPHeaders, httpPropagator)
return t
}
```
而注册的代码是
可以看到是传入的第二个参数起到了作用
```go
// RegisterExtractor registers extractor for given format
func (t *MockTracer) RegisterExtractor(format interface{}, extractor Extractor) {
t.extractors = extractor
}
```
所以我们应该看textPropagator或者httpPropagator,这里我们选择查看textPropagator
```go
textPropagator := new(TextMapPropagator)
```
这里可以看到new了一个TextMapPropagator,我们继续往下翻
可以看到Extract代码主要是将carrier断言为opentracing.TextMapReader,然后调用ForeachKey函数进行循环
```go
func (t *TextMapPropagator) Extract(carrier interface{}) (MockSpanContext, error) {
reader, ok := carrier.(opentracing.TextMapReader)
if !ok {
return emptyContext, opentracing.ErrInvalidCarrier
}
rval := MockSpanContext{0, 0, true, nil}
err := reader.ForeachKey(func(key, val string) error {
lowerKey := strings.ToLower(key)
switch {
case lowerKey == mockTextMapIdsPrefix+"traceid":
// Ids:
i, err := strconv.Atoi(val)
if err != nil {
return err
}
rval.TraceID = i
case lowerKey == mockTextMapIdsPrefix+"spanid":
// Ids:
i, err := strconv.Atoi(val)
if err != nil {
return err
}
rval.SpanID = i
case lowerKey == mockTextMapIdsPrefix+"sampled":
b, err := strconv.ParseBool(val)
if err != nil {
return err
}
rval.Sampled = b
case strings.HasPrefix(lowerKey, mockTextMapBaggagePrefix):
// Baggage:
if rval.Baggage == nil {
rval.Baggage = make(mapstring)
}
safeVal := val
if t.HTTPHeaders {
// unescape errors are ignored, nothing can be done
if rawVal, err := url.QueryUnescape(val); err == nil {
safeVal = rawVal
}
}
rval.Baggage] = safeVal
}
return nil
})
if rval.TraceID == 0 || rval.SpanID == 0 {
return emptyContext, opentracing.ErrSpanContextNotFound
}
if err != nil {
return emptyContext, err
}
return rval, nil
}
```
那么也就是说任何符合TextMapReader接口的都可以传入
```go
type TextMapReader interface {
ForeachKey(handler func(key, val string) error) error
}
```
只要创造一个结构符合该接口即可调用Extract函数
页:
[1]