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