blob: b0c275eb05e4d5fb457f9fc723d83e502f5d0979 [file] [log] [blame]
Takahiro Suzukid7bf8202020-12-17 20:21:59 +09001package opentracing
2
3import (
4 "errors"
5 "net/http"
6)
7
8///////////////////////////////////////////////////////////////////////////////
9// CORE PROPAGATION INTERFACES:
10///////////////////////////////////////////////////////////////////////////////
11
12var (
13 // ErrUnsupportedFormat occurs when the `format` passed to Tracer.Inject() or
14 // Tracer.Extract() is not recognized by the Tracer implementation.
15 ErrUnsupportedFormat = errors.New("opentracing: Unknown or unsupported Inject/Extract format")
16
17 // ErrSpanContextNotFound occurs when the `carrier` passed to
18 // Tracer.Extract() is valid and uncorrupted but has insufficient
19 // information to extract a SpanContext.
20 ErrSpanContextNotFound = errors.New("opentracing: SpanContext not found in Extract carrier")
21
22 // ErrInvalidSpanContext errors occur when Tracer.Inject() is asked to
23 // operate on a SpanContext which it is not prepared to handle (for
24 // example, since it was created by a different tracer implementation).
25 ErrInvalidSpanContext = errors.New("opentracing: SpanContext type incompatible with tracer")
26
27 // ErrInvalidCarrier errors occur when Tracer.Inject() or Tracer.Extract()
28 // implementations expect a different type of `carrier` than they are
29 // given.
30 ErrInvalidCarrier = errors.New("opentracing: Invalid Inject/Extract carrier")
31
32 // ErrSpanContextCorrupted occurs when the `carrier` passed to
33 // Tracer.Extract() is of the expected type but is corrupted.
34 ErrSpanContextCorrupted = errors.New("opentracing: SpanContext data corrupted in Extract carrier")
35)
36
37///////////////////////////////////////////////////////////////////////////////
38// BUILTIN PROPAGATION FORMATS:
39///////////////////////////////////////////////////////////////////////////////
40
41// BuiltinFormat is used to demarcate the values within package `opentracing`
42// that are intended for use with the Tracer.Inject() and Tracer.Extract()
43// methods.
44type BuiltinFormat byte
45
46const (
47 // Binary represents SpanContexts as opaque binary data.
48 //
49 // For Tracer.Inject(): the carrier must be an `io.Writer`.
50 //
51 // For Tracer.Extract(): the carrier must be an `io.Reader`.
52 Binary BuiltinFormat = iota
53
54 // TextMap represents SpanContexts as key:value string pairs.
55 //
56 // Unlike HTTPHeaders, the TextMap format does not restrict the key or
57 // value character sets in any way.
58 //
59 // For Tracer.Inject(): the carrier must be a `TextMapWriter`.
60 //
61 // For Tracer.Extract(): the carrier must be a `TextMapReader`.
62 TextMap
63
64 // HTTPHeaders represents SpanContexts as HTTP header string pairs.
65 //
66 // Unlike TextMap, the HTTPHeaders format requires that the keys and values
67 // be valid as HTTP headers as-is (i.e., character casing may be unstable
68 // and special characters are disallowed in keys, values should be
69 // URL-escaped, etc).
70 //
71 // For Tracer.Inject(): the carrier must be a `TextMapWriter`.
72 //
73 // For Tracer.Extract(): the carrier must be a `TextMapReader`.
74 //
75 // See HTTPHeadersCarrier for an implementation of both TextMapWriter
76 // and TextMapReader that defers to an http.Header instance for storage.
77 // For example, Inject():
78 //
79 // carrier := opentracing.HTTPHeadersCarrier(httpReq.Header)
80 // err := span.Tracer().Inject(
81 // span.Context(), opentracing.HTTPHeaders, carrier)
82 //
83 // Or Extract():
84 //
85 // carrier := opentracing.HTTPHeadersCarrier(httpReq.Header)
86 // clientContext, err := tracer.Extract(
87 // opentracing.HTTPHeaders, carrier)
88 //
89 HTTPHeaders
90)
91
92// TextMapWriter is the Inject() carrier for the TextMap builtin format. With
93// it, the caller can encode a SpanContext for propagation as entries in a map
94// of unicode strings.
95type TextMapWriter interface {
96 // Set a key:value pair to the carrier. Multiple calls to Set() for the
97 // same key leads to undefined behavior.
98 //
99 // NOTE: The backing store for the TextMapWriter may contain data unrelated
100 // to SpanContext. As such, Inject() and Extract() implementations that
101 // call the TextMapWriter and TextMapReader interfaces must agree on a
102 // prefix or other convention to distinguish their own key:value pairs.
103 Set(key, val string)
104}
105
106// TextMapReader is the Extract() carrier for the TextMap builtin format. With it,
107// the caller can decode a propagated SpanContext as entries in a map of
108// unicode strings.
109type TextMapReader interface {
110 // ForeachKey returns TextMap contents via repeated calls to the `handler`
111 // function. If any call to `handler` returns a non-nil error, ForeachKey
112 // terminates and returns that error.
113 //
114 // NOTE: The backing store for the TextMapReader may contain data unrelated
115 // to SpanContext. As such, Inject() and Extract() implementations that
116 // call the TextMapWriter and TextMapReader interfaces must agree on a
117 // prefix or other convention to distinguish their own key:value pairs.
118 //
119 // The "foreach" callback pattern reduces unnecessary copying in some cases
120 // and also allows implementations to hold locks while the map is read.
121 ForeachKey(handler func(key, val string) error) error
122}
123
124// TextMapCarrier allows the use of regular map[string]string
125// as both TextMapWriter and TextMapReader.
126type TextMapCarrier map[string]string
127
128// ForeachKey conforms to the TextMapReader interface.
129func (c TextMapCarrier) ForeachKey(handler func(key, val string) error) error {
130 for k, v := range c {
131 if err := handler(k, v); err != nil {
132 return err
133 }
134 }
135 return nil
136}
137
138// Set implements Set() of opentracing.TextMapWriter
139func (c TextMapCarrier) Set(key, val string) {
140 c[key] = val
141}
142
143// HTTPHeadersCarrier satisfies both TextMapWriter and TextMapReader.
144//
145// Example usage for server side:
146//
147// carrier := opentracing.HTTPHeadersCarrier(httpReq.Header)
148// clientContext, err := tracer.Extract(opentracing.HTTPHeaders, carrier)
149//
150// Example usage for client side:
151//
152// carrier := opentracing.HTTPHeadersCarrier(httpReq.Header)
153// err := tracer.Inject(
154// span.Context(),
155// opentracing.HTTPHeaders,
156// carrier)
157//
158type HTTPHeadersCarrier http.Header
159
160// Set conforms to the TextMapWriter interface.
161func (c HTTPHeadersCarrier) Set(key, val string) {
162 h := http.Header(c)
163 h.Set(key, val)
164}
165
166// ForeachKey conforms to the TextMapReader interface.
167func (c HTTPHeadersCarrier) ForeachKey(handler func(key, val string) error) error {
168 for k, vals := range c {
169 for _, v := range vals {
170 if err := handler(k, v); err != nil {
171 return err
172 }
173 }
174 }
175 return nil
176}