github.com/cockroachdb/cockroach@v20.2.0-alpha.1+incompatible/pkg/util/tracing/shadow.go (about) 1 // Copyright 2017 The Cockroach Authors. 2 // 3 // Use of this software is governed by the Business Source License 4 // included in the file licenses/BSL.txt. 5 // 6 // As of the Change Date specified in that file, in accordance with 7 // the Business Source License, use of this software will be governed 8 // by the Apache License, Version 2.0, included in the file 9 // licenses/APL.txt. 10 // 11 // A "shadow" tracer can be any opentracing.Tracer implementation that is used 12 // in addition to the normal functionality of our tracer. It works by attaching 13 // a shadow span to every span, and attaching a shadow context to every span 14 // context. When injecting a span context, we encapsulate the shadow context 15 // inside ours. 16 17 package tracing 18 19 import ( 20 "context" 21 "fmt" 22 "os" 23 "time" 24 25 "github.com/cockroachdb/cockroach/pkg/util" 26 "github.com/cockroachdb/cockroach/pkg/util/timeutil" 27 lightstep "github.com/lightstep/lightstep-tracer-go" 28 opentracing "github.com/opentracing/opentracing-go" 29 zipkin "github.com/openzipkin-contrib/zipkin-go-opentracing" 30 ) 31 32 type shadowTracerManager interface { 33 Name() string 34 Close(tr opentracing.Tracer) 35 } 36 37 type lightStepManager struct{} 38 39 func (lightStepManager) Name() string { 40 return "lightstep" 41 } 42 43 func (lightStepManager) Close(tr opentracing.Tracer) { 44 lightstep.Close(context.TODO(), tr) 45 } 46 47 type zipkinManager struct { 48 collector zipkin.Collector 49 } 50 51 func (*zipkinManager) Name() string { 52 return "zipkin" 53 } 54 55 func (m *zipkinManager) Close(tr opentracing.Tracer) { 56 _ = m.collector.Close() 57 } 58 59 type shadowTracer struct { 60 opentracing.Tracer 61 manager shadowTracerManager 62 } 63 64 func (st *shadowTracer) Typ() string { 65 return st.manager.Name() 66 } 67 68 func (st *shadowTracer) Close() { 69 st.manager.Close(st) 70 } 71 72 // linkShadowSpan creates and links a Shadow span to the passed-in span (i.e. 73 // fills in s.shadowTr and s.shadowSpan). This should only be called when 74 // shadow tracing is enabled. 75 // 76 // The Shadow span will have a parent if parentShadowCtx is not nil. 77 // parentType is ignored if parentShadowCtx is nil. 78 // 79 // The tags (including logTags) from s are copied to the Shadow span. 80 func linkShadowSpan( 81 s *span, 82 shadowTr *shadowTracer, 83 parentShadowCtx opentracing.SpanContext, 84 parentType opentracing.SpanReferenceType, 85 ) { 86 // Create the shadow lightstep span. 87 var opts []opentracing.StartSpanOption 88 // Replicate the options, using the lightstep context in the reference. 89 opts = append(opts, opentracing.StartTime(s.startTime)) 90 if s.logTags != nil { 91 opts = append(opts, LogTags(s.logTags)) 92 } 93 if s.mu.tags != nil { 94 opts = append(opts, s.mu.tags) 95 } 96 if parentShadowCtx != nil { 97 opts = append(opts, opentracing.SpanReference{ 98 Type: parentType, 99 ReferencedContext: parentShadowCtx, 100 }) 101 } 102 s.shadowTr = shadowTr 103 s.shadowSpan = shadowTr.StartSpan(s.operation, opts...) 104 } 105 106 func createLightStepTracer(token string) (shadowTracerManager, opentracing.Tracer) { 107 return lightStepManager{}, lightstep.NewTracer(lightstep.Options{ 108 AccessToken: token, 109 MaxLogsPerSpan: maxLogsPerSpan, 110 MaxBufferedSpans: 10000, 111 UseGRPC: true, 112 }) 113 } 114 115 var zipkinLogEveryN = util.Every(5 * time.Second) 116 117 func createZipkinTracer(collectorAddr string) (shadowTracerManager, opentracing.Tracer) { 118 // Create our HTTP collector. 119 collector, err := zipkin.NewHTTPCollector( 120 fmt.Sprintf("http://%s/api/v1/spans", collectorAddr), 121 zipkin.HTTPLogger(zipkin.LoggerFunc(func(keyvals ...interface{}) error { 122 if zipkinLogEveryN.ShouldProcess(timeutil.Now()) { 123 // These logs are from the collector (e.g. errors sending data, dropped 124 // traces). We can't use `log` from this package so print them to stderr. 125 toPrint := append([]interface{}{"Zipkin collector"}, keyvals...) 126 fmt.Fprintln(os.Stderr, toPrint) 127 } 128 return nil 129 })), 130 ) 131 if err != nil { 132 panic(err) 133 } 134 135 // Create our recorder. 136 recorder := zipkin.NewRecorder(collector, false /* debug */, "0.0.0.0:0", "cockroach") 137 138 // Create our tracer. 139 zipkinTr, err := zipkin.NewTracer(recorder) 140 if err != nil { 141 panic(err) 142 } 143 return &zipkinManager{collector: collector}, zipkinTr 144 }