mirror of https://github.com/docker/cli.git
177 lines
6.3 KiB
Go
177 lines
6.3 KiB
Go
|
package opentracing
|
||
|
|
||
|
import (
|
||
|
"errors"
|
||
|
"net/http"
|
||
|
)
|
||
|
|
||
|
///////////////////////////////////////////////////////////////////////////////
|
||
|
// CORE PROPAGATION INTERFACES:
|
||
|
///////////////////////////////////////////////////////////////////////////////
|
||
|
|
||
|
var (
|
||
|
// ErrUnsupportedFormat occurs when the `format` passed to Tracer.Inject() or
|
||
|
// Tracer.Extract() is not recognized by the Tracer implementation.
|
||
|
ErrUnsupportedFormat = errors.New("opentracing: Unknown or unsupported Inject/Extract format")
|
||
|
|
||
|
// ErrSpanContextNotFound occurs when the `carrier` passed to
|
||
|
// Tracer.Extract() is valid and uncorrupted but has insufficient
|
||
|
// information to extract a SpanContext.
|
||
|
ErrSpanContextNotFound = errors.New("opentracing: SpanContext not found in Extract carrier")
|
||
|
|
||
|
// ErrInvalidSpanContext errors occur when Tracer.Inject() is asked to
|
||
|
// operate on a SpanContext which it is not prepared to handle (for
|
||
|
// example, since it was created by a different tracer implementation).
|
||
|
ErrInvalidSpanContext = errors.New("opentracing: SpanContext type incompatible with tracer")
|
||
|
|
||
|
// ErrInvalidCarrier errors occur when Tracer.Inject() or Tracer.Extract()
|
||
|
// implementations expect a different type of `carrier` than they are
|
||
|
// given.
|
||
|
ErrInvalidCarrier = errors.New("opentracing: Invalid Inject/Extract carrier")
|
||
|
|
||
|
// ErrSpanContextCorrupted occurs when the `carrier` passed to
|
||
|
// Tracer.Extract() is of the expected type but is corrupted.
|
||
|
ErrSpanContextCorrupted = errors.New("opentracing: SpanContext data corrupted in Extract carrier")
|
||
|
)
|
||
|
|
||
|
///////////////////////////////////////////////////////////////////////////////
|
||
|
// BUILTIN PROPAGATION FORMATS:
|
||
|
///////////////////////////////////////////////////////////////////////////////
|
||
|
|
||
|
// BuiltinFormat is used to demarcate the values within package `opentracing`
|
||
|
// that are intended for use with the Tracer.Inject() and Tracer.Extract()
|
||
|
// methods.
|
||
|
type BuiltinFormat byte
|
||
|
|
||
|
const (
|
||
|
// Binary represents SpanContexts as opaque binary data.
|
||
|
//
|
||
|
// For Tracer.Inject(): the carrier must be an `io.Writer`.
|
||
|
//
|
||
|
// For Tracer.Extract(): the carrier must be an `io.Reader`.
|
||
|
Binary BuiltinFormat = iota
|
||
|
|
||
|
// TextMap represents SpanContexts as key:value string pairs.
|
||
|
//
|
||
|
// Unlike HTTPHeaders, the TextMap format does not restrict the key or
|
||
|
// value character sets in any way.
|
||
|
//
|
||
|
// For Tracer.Inject(): the carrier must be a `TextMapWriter`.
|
||
|
//
|
||
|
// For Tracer.Extract(): the carrier must be a `TextMapReader`.
|
||
|
TextMap
|
||
|
|
||
|
// HTTPHeaders represents SpanContexts as HTTP header string pairs.
|
||
|
//
|
||
|
// Unlike TextMap, the HTTPHeaders format requires that the keys and values
|
||
|
// be valid as HTTP headers as-is (i.e., character casing may be unstable
|
||
|
// and special characters are disallowed in keys, values should be
|
||
|
// URL-escaped, etc).
|
||
|
//
|
||
|
// For Tracer.Inject(): the carrier must be a `TextMapWriter`.
|
||
|
//
|
||
|
// For Tracer.Extract(): the carrier must be a `TextMapReader`.
|
||
|
//
|
||
|
// See HTTPHeadersCarrier for an implementation of both TextMapWriter
|
||
|
// and TextMapReader that defers to an http.Header instance for storage.
|
||
|
// For example, Inject():
|
||
|
//
|
||
|
// carrier := opentracing.HTTPHeadersCarrier(httpReq.Header)
|
||
|
// err := span.Tracer().Inject(
|
||
|
// span.Context(), opentracing.HTTPHeaders, carrier)
|
||
|
//
|
||
|
// Or Extract():
|
||
|
//
|
||
|
// carrier := opentracing.HTTPHeadersCarrier(httpReq.Header)
|
||
|
// clientContext, err := tracer.Extract(
|
||
|
// opentracing.HTTPHeaders, carrier)
|
||
|
//
|
||
|
HTTPHeaders
|
||
|
)
|
||
|
|
||
|
// TextMapWriter is the Inject() carrier for the TextMap builtin format. With
|
||
|
// it, the caller can encode a SpanContext for propagation as entries in a map
|
||
|
// of unicode strings.
|
||
|
type TextMapWriter interface {
|
||
|
// Set a key:value pair to the carrier. Multiple calls to Set() for the
|
||
|
// same key leads to undefined behavior.
|
||
|
//
|
||
|
// NOTE: The backing store for the TextMapWriter may contain data unrelated
|
||
|
// to SpanContext. As such, Inject() and Extract() implementations that
|
||
|
// call the TextMapWriter and TextMapReader interfaces must agree on a
|
||
|
// prefix or other convention to distinguish their own key:value pairs.
|
||
|
Set(key, val string)
|
||
|
}
|
||
|
|
||
|
// TextMapReader is the Extract() carrier for the TextMap builtin format. With it,
|
||
|
// the caller can decode a propagated SpanContext as entries in a map of
|
||
|
// unicode strings.
|
||
|
type TextMapReader interface {
|
||
|
// ForeachKey returns TextMap contents via repeated calls to the `handler`
|
||
|
// function. If any call to `handler` returns a non-nil error, ForeachKey
|
||
|
// terminates and returns that error.
|
||
|
//
|
||
|
// NOTE: The backing store for the TextMapReader may contain data unrelated
|
||
|
// to SpanContext. As such, Inject() and Extract() implementations that
|
||
|
// call the TextMapWriter and TextMapReader interfaces must agree on a
|
||
|
// prefix or other convention to distinguish their own key:value pairs.
|
||
|
//
|
||
|
// The "foreach" callback pattern reduces unnecessary copying in some cases
|
||
|
// and also allows implementations to hold locks while the map is read.
|
||
|
ForeachKey(handler func(key, val string) error) error
|
||
|
}
|
||
|
|
||
|
// TextMapCarrier allows the use of regular map[string]string
|
||
|
// as both TextMapWriter and TextMapReader.
|
||
|
type TextMapCarrier map[string]string
|
||
|
|
||
|
// ForeachKey conforms to the TextMapReader interface.
|
||
|
func (c TextMapCarrier) ForeachKey(handler func(key, val string) error) error {
|
||
|
for k, v := range c {
|
||
|
if err := handler(k, v); err != nil {
|
||
|
return err
|
||
|
}
|
||
|
}
|
||
|
return nil
|
||
|
}
|
||
|
|
||
|
// Set implements Set() of opentracing.TextMapWriter
|
||
|
func (c TextMapCarrier) Set(key, val string) {
|
||
|
c[key] = val
|
||
|
}
|
||
|
|
||
|
// HTTPHeadersCarrier satisfies both TextMapWriter and TextMapReader.
|
||
|
//
|
||
|
// Example usage for server side:
|
||
|
//
|
||
|
// carrier := opentracing.HTTPHeadersCarrier(httpReq.Header)
|
||
|
// clientContext, err := tracer.Extract(opentracing.HTTPHeaders, carrier)
|
||
|
//
|
||
|
// Example usage for client side:
|
||
|
//
|
||
|
// carrier := opentracing.HTTPHeadersCarrier(httpReq.Header)
|
||
|
// err := tracer.Inject(
|
||
|
// span.Context(),
|
||
|
// opentracing.HTTPHeaders,
|
||
|
// carrier)
|
||
|
//
|
||
|
type HTTPHeadersCarrier http.Header
|
||
|
|
||
|
// Set conforms to the TextMapWriter interface.
|
||
|
func (c HTTPHeadersCarrier) Set(key, val string) {
|
||
|
h := http.Header(c)
|
||
|
h.Add(key, val)
|
||
|
}
|
||
|
|
||
|
// ForeachKey conforms to the TextMapReader interface.
|
||
|
func (c HTTPHeadersCarrier) ForeachKey(handler func(key, val string) error) error {
|
||
|
for k, vals := range c {
|
||
|
for _, v := range vals {
|
||
|
if err := handler(k, v); err != nil {
|
||
|
return err
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
return nil
|
||
|
}
|