| package opentracing |
| |
| import "time" |
| |
| // Tracer is a simple, thin interface for Span creation and SpanContext |
| // propagation. |
| type Tracer interface { |
| |
| // Create, start, and return a new Span with the given `operationName` and |
| // incorporate the given StartSpanOption `opts`. (Note that `opts` borrows |
| // from the "functional options" pattern, per |
| // http://dave.cheney.net/2014/10/17/functional-options-for-friendly-apis) |
| // |
| // A Span with no SpanReference options (e.g., opentracing.ChildOf() or |
| // opentracing.FollowsFrom()) becomes the root of its own trace. |
| // |
| // Examples: |
| // |
| // var tracer opentracing.Tracer = ... |
| // |
| // // The root-span case: |
| // sp := tracer.StartSpan("GetFeed") |
| // |
| // // The vanilla child span case: |
| // sp := tracer.StartSpan( |
| // "GetFeed", |
| // opentracing.ChildOf(parentSpan.Context())) |
| // |
| // // All the bells and whistles: |
| // sp := tracer.StartSpan( |
| // "GetFeed", |
| // opentracing.ChildOf(parentSpan.Context()), |
| // opentracing.Tag{"user_agent", loggedReq.UserAgent}, |
| // opentracing.StartTime(loggedReq.Timestamp), |
| // ) |
| // |
| StartSpan(operationName string, opts ...StartSpanOption) Span |
| |
| // Inject() takes the `sm` SpanContext instance and injects it for |
| // propagation within `carrier`. The actual type of `carrier` depends on |
| // the value of `format`. |
| // |
| // OpenTracing defines a common set of `format` values (see BuiltinFormat), |
| // and each has an expected carrier type. |
| // |
| // Other packages may declare their own `format` values, much like the keys |
| // used by `context.Context` (see https://godoc.org/context#WithValue). |
| // |
| // Example usage (sans error handling): |
| // |
| // carrier := opentracing.HTTPHeadersCarrier(httpReq.Header) |
| // err := tracer.Inject( |
| // span.Context(), |
| // opentracing.HTTPHeaders, |
| // carrier) |
| // |
| // NOTE: All opentracing.Tracer implementations MUST support all |
| // BuiltinFormats. |
| // |
| // Implementations may return opentracing.ErrUnsupportedFormat if `format` |
| // is not supported by (or not known by) the implementation. |
| // |
| // Implementations may return opentracing.ErrInvalidCarrier or any other |
| // implementation-specific error if the format is supported but injection |
| // fails anyway. |
| // |
| // See Tracer.Extract(). |
| Inject(sm SpanContext, format interface{}, carrier interface{}) error |
| |
| // Extract() returns a SpanContext instance given `format` and `carrier`. |
| // |
| // OpenTracing defines a common set of `format` values (see BuiltinFormat), |
| // and each has an expected carrier type. |
| // |
| // Other packages may declare their own `format` values, much like the keys |
| // used by `context.Context` (see |
| // https://godoc.org/golang.org/x/net/context#WithValue). |
| // |
| // Example usage (with StartSpan): |
| // |
| // |
| // carrier := opentracing.HTTPHeadersCarrier(httpReq.Header) |
| // clientContext, err := tracer.Extract(opentracing.HTTPHeaders, carrier) |
| // |
| // // ... assuming the ultimate goal here is to resume the trace with a |
| // // server-side Span: |
| // var serverSpan opentracing.Span |
| // if err == nil { |
| // span = tracer.StartSpan( |
| // rpcMethodName, ext.RPCServerOption(clientContext)) |
| // } else { |
| // span = tracer.StartSpan(rpcMethodName) |
| // } |
| // |
| // |
| // NOTE: All opentracing.Tracer implementations MUST support all |
| // BuiltinFormats. |
| // |
| // Return values: |
| // - A successful Extract returns a SpanContext instance and a nil error |
| // - If there was simply no SpanContext to extract in `carrier`, Extract() |
| // returns (nil, opentracing.ErrSpanContextNotFound) |
| // - If `format` is unsupported or unrecognized, Extract() returns (nil, |
| // opentracing.ErrUnsupportedFormat) |
| // - If there are more fundamental problems with the `carrier` object, |
| // Extract() may return opentracing.ErrInvalidCarrier, |
| // opentracing.ErrSpanContextCorrupted, or implementation-specific |
| // errors. |
| // |
| // See Tracer.Inject(). |
| Extract(format interface{}, carrier interface{}) (SpanContext, error) |
| } |
| |
| // StartSpanOptions allows Tracer.StartSpan() callers and implementors a |
| // mechanism to override the start timestamp, specify Span References, and make |
| // a single Tag or multiple Tags available at Span start time. |
| // |
| // StartSpan() callers should look at the StartSpanOption interface and |
| // implementations available in this package. |
| // |
| // Tracer implementations can convert a slice of `StartSpanOption` instances |
| // into a `StartSpanOptions` struct like so: |
| // |
| // func StartSpan(opName string, opts ...opentracing.StartSpanOption) { |
| // sso := opentracing.StartSpanOptions{} |
| // for _, o := range opts { |
| // o.Apply(&sso) |
| // } |
| // ... |
| // } |
| // |
| type StartSpanOptions struct { |
| // Zero or more causal references to other Spans (via their SpanContext). |
| // If empty, start a "root" Span (i.e., start a new trace). |
| References []SpanReference |
| |
| // StartTime overrides the Span's start time, or implicitly becomes |
| // time.Now() if StartTime.IsZero(). |
| StartTime time.Time |
| |
| // Tags may have zero or more entries; the restrictions on map values are |
| // identical to those for Span.SetTag(). May be nil. |
| // |
| // If specified, the caller hands off ownership of Tags at |
| // StartSpan() invocation time. |
| Tags map[string]interface{} |
| } |
| |
| // StartSpanOption instances (zero or more) may be passed to Tracer.StartSpan. |
| // |
| // StartSpanOption borrows from the "functional options" pattern, per |
| // http://dave.cheney.net/2014/10/17/functional-options-for-friendly-apis |
| type StartSpanOption interface { |
| Apply(*StartSpanOptions) |
| } |
| |
| // SpanReferenceType is an enum type describing different categories of |
| // relationships between two Spans. If Span-2 refers to Span-1, the |
| // SpanReferenceType describes Span-1 from Span-2's perspective. For example, |
| // ChildOfRef means that Span-1 created Span-2. |
| // |
| // NOTE: Span-1 and Span-2 do *not* necessarily depend on each other for |
| // completion; e.g., Span-2 may be part of a background job enqueued by Span-1, |
| // or Span-2 may be sitting in a distributed queue behind Span-1. |
| type SpanReferenceType int |
| |
| const ( |
| // ChildOfRef refers to a parent Span that caused *and* somehow depends |
| // upon the new child Span. Often (but not always), the parent Span cannot |
| // finish until the child Span does. |
| // |
| // An timing diagram for a ChildOfRef that's blocked on the new Span: |
| // |
| // [-Parent Span---------] |
| // [-Child Span----] |
| // |
| // See http://opentracing.io/spec/ |
| // |
| // See opentracing.ChildOf() |
| ChildOfRef SpanReferenceType = iota |
| |
| // FollowsFromRef refers to a parent Span that does not depend in any way |
| // on the result of the new child Span. For instance, one might use |
| // FollowsFromRefs to describe pipeline stages separated by queues, |
| // or a fire-and-forget cache insert at the tail end of a web request. |
| // |
| // A FollowsFromRef Span is part of the same logical trace as the new Span: |
| // i.e., the new Span is somehow caused by the work of its FollowsFromRef. |
| // |
| // All of the following could be valid timing diagrams for children that |
| // "FollowFrom" a parent. |
| // |
| // [-Parent Span-] [-Child Span-] |
| // |
| // |
| // [-Parent Span--] |
| // [-Child Span-] |
| // |
| // |
| // [-Parent Span-] |
| // [-Child Span-] |
| // |
| // See http://opentracing.io/spec/ |
| // |
| // See opentracing.FollowsFrom() |
| FollowsFromRef |
| ) |
| |
| // SpanReference is a StartSpanOption that pairs a SpanReferenceType and a |
| // referenced SpanContext. See the SpanReferenceType documentation for |
| // supported relationships. If SpanReference is created with |
| // ReferencedContext==nil, it has no effect. Thus it allows for a more concise |
| // syntax for starting spans: |
| // |
| // sc, _ := tracer.Extract(someFormat, someCarrier) |
| // span := tracer.StartSpan("operation", opentracing.ChildOf(sc)) |
| // |
| // The `ChildOf(sc)` option above will not panic if sc == nil, it will just |
| // not add the parent span reference to the options. |
| type SpanReference struct { |
| Type SpanReferenceType |
| ReferencedContext SpanContext |
| } |
| |
| // Apply satisfies the StartSpanOption interface. |
| func (r SpanReference) Apply(o *StartSpanOptions) { |
| if r.ReferencedContext != nil { |
| o.References = append(o.References, r) |
| } |
| } |
| |
| // ChildOf returns a StartSpanOption pointing to a dependent parent span. |
| // If sc == nil, the option has no effect. |
| // |
| // See ChildOfRef, SpanReference |
| func ChildOf(sc SpanContext) SpanReference { |
| return SpanReference{ |
| Type: ChildOfRef, |
| ReferencedContext: sc, |
| } |
| } |
| |
| // FollowsFrom returns a StartSpanOption pointing to a parent Span that caused |
| // the child Span but does not directly depend on its result in any way. |
| // If sc == nil, the option has no effect. |
| // |
| // See FollowsFromRef, SpanReference |
| func FollowsFrom(sc SpanContext) SpanReference { |
| return SpanReference{ |
| Type: FollowsFromRef, |
| ReferencedContext: sc, |
| } |
| } |
| |
| // StartTime is a StartSpanOption that sets an explicit start timestamp for the |
| // new Span. |
| type StartTime time.Time |
| |
| // Apply satisfies the StartSpanOption interface. |
| func (t StartTime) Apply(o *StartSpanOptions) { |
| o.StartTime = time.Time(t) |
| } |
| |
| // Tags are a generic map from an arbitrary string key to an opaque value type. |
| // The underlying tracing system is responsible for interpreting and |
| // serializing the values. |
| type Tags map[string]interface{} |
| |
| // Apply satisfies the StartSpanOption interface. |
| func (t Tags) Apply(o *StartSpanOptions) { |
| if o.Tags == nil { |
| o.Tags = make(map[string]interface{}) |
| } |
| for k, v := range t { |
| o.Tags[k] = v |
| } |
| } |
| |
| // Tag may be passed as a StartSpanOption to add a tag to new spans, |
| // or its Set method may be used to apply the tag to an existing Span, |
| // for example: |
| // |
| // tracer.StartSpan("opName", Tag{"Key", value}) |
| // |
| // or |
| // |
| // Tag{"key", value}.Set(span) |
| type Tag struct { |
| Key string |
| Value interface{} |
| } |
| |
| // Apply satisfies the StartSpanOption interface. |
| func (t Tag) Apply(o *StartSpanOptions) { |
| if o.Tags == nil { |
| o.Tags = make(map[string]interface{}) |
| } |
| o.Tags[t.Key] = t.Value |
| } |
| |
| // Set applies the tag to an existing Span. |
| func (t Tag) Set(s Span) { |
| s.SetTag(t.Key, t.Value) |
| } |