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  }