github.com/mier85/go-sensor@v1.30.1-0.20220920111756-9bf41b3bc7e0/tracer.go (about) 1 // (c) Copyright IBM Corp. 2021 2 // (c) Copyright Instana Inc. 2016 3 4 package instana 5 6 import ( 7 "context" 8 "time" 9 10 ot "github.com/opentracing/opentracing-go" 11 ) 12 13 const ( 14 // MaxLogsPerSpan The maximum number of logs allowed on a span. 15 MaxLogsPerSpan = 2 16 ) 17 18 var _ ot.Tracer = (*tracerS)(nil) 19 var _ Tracer = (*tracerS)(nil) 20 21 type tracerS struct { 22 recorder SpanRecorder 23 } 24 25 // NewTracer initializes a new tracer with default options 26 func NewTracer() *tracerS { 27 return NewTracerWithOptions(nil) 28 } 29 30 // NewTracerWithOptions initializes and configures a new tracer that collects and sends spans to the agent 31 func NewTracerWithOptions(options *Options) *tracerS { 32 return NewTracerWithEverything(options, nil) 33 } 34 35 // NewTracerWithEverything initializes and configures a new tracer. It uses instana.DefaultOptions() if nil 36 // is provided 37 func NewTracerWithEverything(options *Options, recorder SpanRecorder) *tracerS { 38 InitSensor(options) 39 40 if recorder == nil { 41 recorder = NewRecorder() 42 } 43 44 tracer := &tracerS{ 45 recorder: recorder, 46 } 47 48 return tracer 49 } 50 51 func (r *tracerS) Inject(spanContext ot.SpanContext, format interface{}, carrier interface{}) error { 52 switch format { 53 case ot.TextMap, ot.HTTPHeaders: 54 sc, ok := spanContext.(SpanContext) 55 if !ok { 56 return ot.ErrInvalidSpanContext 57 } 58 59 return injectTraceContext(sc, carrier) 60 } 61 62 return ot.ErrUnsupportedFormat 63 } 64 65 func (r *tracerS) Extract(format interface{}, carrier interface{}) (ot.SpanContext, error) { 66 switch format { 67 case ot.TextMap, ot.HTTPHeaders: 68 sc, err := extractTraceContext(carrier) 69 if err != nil { 70 return nil, err 71 } 72 73 return sc, nil 74 } 75 76 return nil, ot.ErrUnsupportedFormat 77 } 78 79 func (r *tracerS) StartSpan(operationName string, opts ...ot.StartSpanOption) ot.Span { 80 sso := ot.StartSpanOptions{} 81 for _, o := range opts { 82 o.Apply(&sso) 83 } 84 85 return r.StartSpanWithOptions(operationName, sso) 86 } 87 88 func (r *tracerS) StartSpanWithOptions(operationName string, opts ot.StartSpanOptions) ot.Span { 89 startTime := opts.StartTime 90 if startTime.IsZero() { 91 startTime = time.Now() 92 } 93 94 var corrData EUMCorrelationData 95 96 sc := NewRootSpanContext() 97 for _, ref := range opts.References { 98 if ref.Type == ot.ChildOfRef || ref.Type == ot.FollowsFromRef { 99 if parent, ok := ref.ReferencedContext.(SpanContext); ok { 100 corrData = parent.Correlation 101 sc = NewSpanContext(parent) 102 break 103 } 104 } 105 } 106 107 if tag, ok := opts.Tags[suppressTracingTag]; ok { 108 sc.Suppressed = tag.(bool) 109 delete(opts.Tags, suppressTracingTag) 110 } 111 112 return &spanS{ 113 context: sc, 114 tracer: r, 115 Service: sensor.options.Service, 116 Operation: operationName, 117 Start: startTime, 118 Duration: -1, 119 Correlation: corrData, 120 Tags: opts.Tags, 121 } 122 } 123 124 // Options returns current tracer options 125 func (r *tracerS) Options() TracerOptions { 126 if sensor.options == nil { 127 return DefaultTracerOptions() 128 } 129 130 return sensor.options.Tracer 131 } 132 133 // Flush forces sending any queued finished spans to the agent 134 func (r *tracerS) Flush(ctx context.Context) error { 135 if err := r.recorder.Flush(ctx); err != nil { 136 return err 137 } 138 139 return sensor.Agent().Flush(ctx) 140 }