...

Source file src/github.com/opentracing/opentracing-go/tracer.go

Documentation: github.com/opentracing/opentracing-go

     1  package opentracing
     2  
     3  import "time"
     4  
     5  // Tracer is a simple, thin interface for Span creation and SpanContext
     6  // propagation.
     7  type Tracer interface {
     8  
     9  	// Create, start, and return a new Span with the given `operationName` and
    10  	// incorporate the given StartSpanOption `opts`. (Note that `opts` borrows
    11  	// from the "functional options" pattern, per
    12  	// http://dave.cheney.net/2014/10/17/functional-options-for-friendly-apis)
    13  	//
    14  	// A Span with no SpanReference options (e.g., opentracing.ChildOf() or
    15  	// opentracing.FollowsFrom()) becomes the root of its own trace.
    16  	//
    17  	// Examples:
    18  	//
    19  	//     var tracer opentracing.Tracer = ...
    20  	//
    21  	//     // The root-span case:
    22  	//     sp := tracer.StartSpan("GetFeed")
    23  	//
    24  	//     // The vanilla child span case:
    25  	//     sp := tracer.StartSpan(
    26  	//         "GetFeed",
    27  	//         opentracing.ChildOf(parentSpan.Context()))
    28  	//
    29  	//     // All the bells and whistles:
    30  	//     sp := tracer.StartSpan(
    31  	//         "GetFeed",
    32  	//         opentracing.ChildOf(parentSpan.Context()),
    33  	//         opentracing.Tag{"user_agent", loggedReq.UserAgent},
    34  	//         opentracing.StartTime(loggedReq.Timestamp),
    35  	//     )
    36  	//
    37  	StartSpan(operationName string, opts ...StartSpanOption) Span
    38  
    39  	// Inject() takes the `sm` SpanContext instance and injects it for
    40  	// propagation within `carrier`. The actual type of `carrier` depends on
    41  	// the value of `format`.
    42  	//
    43  	// OpenTracing defines a common set of `format` values (see BuiltinFormat),
    44  	// and each has an expected carrier type.
    45  	//
    46  	// Other packages may declare their own `format` values, much like the keys
    47  	// used by `context.Context` (see https://godoc.org/context#WithValue).
    48  	//
    49  	// Example usage (sans error handling):
    50  	//
    51  	//     carrier := opentracing.HTTPHeadersCarrier(httpReq.Header)
    52  	//     err := tracer.Inject(
    53  	//         span.Context(),
    54  	//         opentracing.HTTPHeaders,
    55  	//         carrier)
    56  	//
    57  	// NOTE: All opentracing.Tracer implementations MUST support all
    58  	// BuiltinFormats.
    59  	//
    60  	// Implementations may return opentracing.ErrUnsupportedFormat if `format`
    61  	// is not supported by (or not known by) the implementation.
    62  	//
    63  	// Implementations may return opentracing.ErrInvalidCarrier or any other
    64  	// implementation-specific error if the format is supported but injection
    65  	// fails anyway.
    66  	//
    67  	// See Tracer.Extract().
    68  	Inject(sm SpanContext, format interface{}, carrier interface{}) error
    69  
    70  	// Extract() returns a SpanContext instance given `format` and `carrier`.
    71  	//
    72  	// OpenTracing defines a common set of `format` values (see BuiltinFormat),
    73  	// and each has an expected carrier type.
    74  	//
    75  	// Other packages may declare their own `format` values, much like the keys
    76  	// used by `context.Context` (see
    77  	// https://godoc.org/golang.org/x/net/context#WithValue).
    78  	//
    79  	// Example usage (with StartSpan):
    80  	//
    81  	//
    82  	//     carrier := opentracing.HTTPHeadersCarrier(httpReq.Header)
    83  	//     clientContext, err := tracer.Extract(opentracing.HTTPHeaders, carrier)
    84  	//
    85  	//     // ... assuming the ultimate goal here is to resume the trace with a
    86  	//     // server-side Span:
    87  	//     var serverSpan opentracing.Span
    88  	//     if err == nil {
    89  	//         span = tracer.StartSpan(
    90  	//             rpcMethodName, ext.RPCServerOption(clientContext))
    91  	//     } else {
    92  	//         span = tracer.StartSpan(rpcMethodName)
    93  	//     }
    94  	//
    95  	//
    96  	// NOTE: All opentracing.Tracer implementations MUST support all
    97  	// BuiltinFormats.
    98  	//
    99  	// Return values:
   100  	//  - A successful Extract returns a SpanContext instance and a nil error
   101  	//  - If there was simply no SpanContext to extract in `carrier`, Extract()
   102  	//    returns (nil, opentracing.ErrSpanContextNotFound)
   103  	//  - If `format` is unsupported or unrecognized, Extract() returns (nil,
   104  	//    opentracing.ErrUnsupportedFormat)
   105  	//  - If there are more fundamental problems with the `carrier` object,
   106  	//    Extract() may return opentracing.ErrInvalidCarrier,
   107  	//    opentracing.ErrSpanContextCorrupted, or implementation-specific
   108  	//    errors.
   109  	//
   110  	// See Tracer.Inject().
   111  	Extract(format interface{}, carrier interface{}) (SpanContext, error)
   112  }
   113  
   114  // StartSpanOptions allows Tracer.StartSpan() callers and implementors a
   115  // mechanism to override the start timestamp, specify Span References, and make
   116  // a single Tag or multiple Tags available at Span start time.
   117  //
   118  // StartSpan() callers should look at the StartSpanOption interface and
   119  // implementations available in this package.
   120  //
   121  // Tracer implementations can convert a slice of `StartSpanOption` instances
   122  // into a `StartSpanOptions` struct like so:
   123  //
   124  //     func StartSpan(opName string, opts ...opentracing.StartSpanOption) {
   125  //         sso := opentracing.StartSpanOptions{}
   126  //         for _, o := range opts {
   127  //             o.Apply(&sso)
   128  //         }
   129  //         ...
   130  //     }
   131  //
   132  type StartSpanOptions struct {
   133  	// Zero or more causal references to other Spans (via their SpanContext).
   134  	// If empty, start a "root" Span (i.e., start a new trace).
   135  	References []SpanReference
   136  
   137  	// StartTime overrides the Span's start time, or implicitly becomes
   138  	// time.Now() if StartTime.IsZero().
   139  	StartTime time.Time
   140  
   141  	// Tags may have zero or more entries; the restrictions on map values are
   142  	// identical to those for Span.SetTag(). May be nil.
   143  	//
   144  	// If specified, the caller hands off ownership of Tags at
   145  	// StartSpan() invocation time.
   146  	Tags map[string]interface{}
   147  }
   148  
   149  // StartSpanOption instances (zero or more) may be passed to Tracer.StartSpan.
   150  //
   151  // StartSpanOption borrows from the "functional options" pattern, per
   152  // http://dave.cheney.net/2014/10/17/functional-options-for-friendly-apis
   153  type StartSpanOption interface {
   154  	Apply(*StartSpanOptions)
   155  }
   156  
   157  // SpanReferenceType is an enum type describing different categories of
   158  // relationships between two Spans. If Span-2 refers to Span-1, the
   159  // SpanReferenceType describes Span-1 from Span-2's perspective. For example,
   160  // ChildOfRef means that Span-1 created Span-2.
   161  //
   162  // NOTE: Span-1 and Span-2 do *not* necessarily depend on each other for
   163  // completion; e.g., Span-2 may be part of a background job enqueued by Span-1,
   164  // or Span-2 may be sitting in a distributed queue behind Span-1.
   165  type SpanReferenceType int
   166  
   167  const (
   168  	// ChildOfRef refers to a parent Span that caused *and* somehow depends
   169  	// upon the new child Span. Often (but not always), the parent Span cannot
   170  	// finish until the child Span does.
   171  	//
   172  	// An timing diagram for a ChildOfRef that's blocked on the new Span:
   173  	//
   174  	//     [-Parent Span---------]
   175  	//          [-Child Span----]
   176  	//
   177  	// See http://opentracing.io/spec/
   178  	//
   179  	// See opentracing.ChildOf()
   180  	ChildOfRef SpanReferenceType = iota
   181  
   182  	// FollowsFromRef refers to a parent Span that does not depend in any way
   183  	// on the result of the new child Span. For instance, one might use
   184  	// FollowsFromRefs to describe pipeline stages separated by queues,
   185  	// or a fire-and-forget cache insert at the tail end of a web request.
   186  	//
   187  	// A FollowsFromRef Span is part of the same logical trace as the new Span:
   188  	// i.e., the new Span is somehow caused by the work of its FollowsFromRef.
   189  	//
   190  	// All of the following could be valid timing diagrams for children that
   191  	// "FollowFrom" a parent.
   192  	//
   193  	//     [-Parent Span-]  [-Child Span-]
   194  	//
   195  	//
   196  	//     [-Parent Span--]
   197  	//      [-Child Span-]
   198  	//
   199  	//
   200  	//     [-Parent Span-]
   201  	//                 [-Child Span-]
   202  	//
   203  	// See http://opentracing.io/spec/
   204  	//
   205  	// See opentracing.FollowsFrom()
   206  	FollowsFromRef
   207  )
   208  
   209  // SpanReference is a StartSpanOption that pairs a SpanReferenceType and a
   210  // referenced SpanContext. See the SpanReferenceType documentation for
   211  // supported relationships.  If SpanReference is created with
   212  // ReferencedContext==nil, it has no effect. Thus it allows for a more concise
   213  // syntax for starting spans:
   214  //
   215  //     sc, _ := tracer.Extract(someFormat, someCarrier)
   216  //     span := tracer.StartSpan("operation", opentracing.ChildOf(sc))
   217  //
   218  // The `ChildOf(sc)` option above will not panic if sc == nil, it will just
   219  // not add the parent span reference to the options.
   220  type SpanReference struct {
   221  	Type              SpanReferenceType
   222  	ReferencedContext SpanContext
   223  }
   224  
   225  // Apply satisfies the StartSpanOption interface.
   226  func (r SpanReference) Apply(o *StartSpanOptions) {
   227  	if r.ReferencedContext != nil {
   228  		o.References = append(o.References, r)
   229  	}
   230  }
   231  
   232  // ChildOf returns a StartSpanOption pointing to a dependent parent span.
   233  // If sc == nil, the option has no effect.
   234  //
   235  // See ChildOfRef, SpanReference
   236  func ChildOf(sc SpanContext) SpanReference {
   237  	return SpanReference{
   238  		Type:              ChildOfRef,
   239  		ReferencedContext: sc,
   240  	}
   241  }
   242  
   243  // FollowsFrom returns a StartSpanOption pointing to a parent Span that caused
   244  // the child Span but does not directly depend on its result in any way.
   245  // If sc == nil, the option has no effect.
   246  //
   247  // See FollowsFromRef, SpanReference
   248  func FollowsFrom(sc SpanContext) SpanReference {
   249  	return SpanReference{
   250  		Type:              FollowsFromRef,
   251  		ReferencedContext: sc,
   252  	}
   253  }
   254  
   255  // StartTime is a StartSpanOption that sets an explicit start timestamp for the
   256  // new Span.
   257  type StartTime time.Time
   258  
   259  // Apply satisfies the StartSpanOption interface.
   260  func (t StartTime) Apply(o *StartSpanOptions) {
   261  	o.StartTime = time.Time(t)
   262  }
   263  
   264  // Tags are a generic map from an arbitrary string key to an opaque value type.
   265  // The underlying tracing system is responsible for interpreting and
   266  // serializing the values.
   267  type Tags map[string]interface{}
   268  
   269  // Apply satisfies the StartSpanOption interface.
   270  func (t Tags) Apply(o *StartSpanOptions) {
   271  	if o.Tags == nil {
   272  		o.Tags = make(map[string]interface{})
   273  	}
   274  	for k, v := range t {
   275  		o.Tags[k] = v
   276  	}
   277  }
   278  
   279  // Tag may be passed as a StartSpanOption to add a tag to new spans,
   280  // or its Set method may be used to apply the tag to an existing Span,
   281  // for example:
   282  //
   283  // tracer.StartSpan("opName", Tag{"Key", value})
   284  //
   285  //   or
   286  //
   287  // Tag{"key", value}.Set(span)
   288  type Tag struct {
   289  	Key   string
   290  	Value interface{}
   291  }
   292  
   293  // Apply satisfies the StartSpanOption interface.
   294  func (t Tag) Apply(o *StartSpanOptions) {
   295  	if o.Tags == nil {
   296  		o.Tags = make(map[string]interface{})
   297  	}
   298  	o.Tags[t.Key] = t.Value
   299  }
   300  
   301  // Set applies the tag to an existing Span.
   302  func (t Tag) Set(s Span) {
   303  	s.SetTag(t.Key, t.Value)
   304  }
   305  

View as plain text