上一主题 下一主题
ScriptCat,新一代的脚本管理器脚本站,与全世界分享你的用户脚本油猴脚本开发指南教程目录
返回列表 发新帖
楼主: 李恒道 - 

opentracing Extract函数分析

[复制链接]
  • TA的每日心情
    慵懒
    2024-10-28 07:07
  • 签到天数: 193 天

    [LV.7]常住居民III

    712

    主题

    5959

    回帖

    6758

    积分

    管理员

    非物质文化遗产社会摇传承人

    积分
    6758

    荣誉开发者喜迎中秋油中2周年生态建设者

    发表于 2023-8-12 05:14:41 | 显示全部楼层 | 阅读模式

    看的是MockTracer的代码
    在https://github.com/opentracing/opentracing-go/blob/10b1cf09e00bdc84234b8c7a4b4d4e4afe64de87/mocktracer/mocktracer.go#L110

    首先根据format找到匹配的解压缩对象,调用Extract

    // Extract belongs to the Tracer interface.
    func (t *MockTracer) Extract(format interface{}, carrier interface{}) (opentracing.SpanContext, error) {
        extractor, ok := t.extractors[format]
        if !ok {
            return nil, opentracing.ErrUnsupportedFormat
        }
        return extractor.Extract(carrier)
    }

    我们看new生成部分

    这里看到注册了两个Extractor,分别是opentracing.TextMap和opentracing.HTTPHeaders

    // 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(map[interface{}]Injector),
            extractors:    make(map[interface{}]Extractor),
        }
    
        // 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
    }

    而注册的代码是

    可以看到是传入的第二个参数起到了作用

    // RegisterExtractor registers extractor for given format
    func (t *MockTracer) RegisterExtractor(format interface{}, extractor Extractor) {
        t.extractors[format] = extractor
    }

    所以我们应该看textPropagator或者httpPropagator,这里我们选择查看textPropagator

    textPropagator := new(TextMapPropagator)

    这里可以看到new了一个TextMapPropagator,我们继续往下翻

    可以看到Extract代码主要是将carrier断言为opentracing.TextMapReader,然后调用ForeachKey函数进行循环

    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(map[string]string)
                }
                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[lowerKey[len(mockTextMapBaggagePrefix):]] = safeVal
            }
            return nil
        })
        if rval.TraceID == 0 || rval.SpanID == 0 {
            return emptyContext, opentracing.ErrSpanContextNotFound
        }
        if err != nil {
            return emptyContext, err
        }
        return rval, nil
    }

    那么也就是说任何符合TextMapReader接口的都可以传入

    type TextMapReader interface {
        ForeachKey(handler func(key, val string) error) error
    }

    只要创造一个结构符合该接口即可调用Extract函数

    混的人。
    ------------------------------------------
    進撃!永遠の帝国の破壊虎---李恒道

    入驻了爱发电https://afdian.net/a/lihengdao666
    个人宣言:この世界で私に胜てる人とコードはまだ生まれていません。死ぬのが怖くなければ来てください。

    发表回复

    本版积分规则

    快速回复 返回顶部 返回列表