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  }