/
propagation.go
177 lines (153 loc) · 4.49 KB
/
propagation.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
package trace
import (
errs "errors"
"net/http"
"google.golang.org/grpc/metadata"
)
var (
// ErrUnsupportedFormat occurs when the `format` passed to Tracer.Inject() or
// Tracer.Extract() is not recognized by the Tracer implementation.
ErrUnsupportedFormat = errs.New("trace: Unknown or unsupported Inject/Extract format")
// ErrTraceNotFound occurs when the `carrier` passed to
// Tracer.Extract() is valid and uncorrupted but has insufficient
// information to extract a Trace.
ErrTraceNotFound = errs.New("trace: Trace not found in Extract carrier")
// ErrInvalidTrace errors occur when Tracer.Inject() is asked to
// operate on a Trace which it is not prepared to handle (for
// example, since it was created by a different tracer implementation).
ErrInvalidTrace = errs.New("trace: Trace 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 = errs.New("trace: Invalid Inject/Extract carrier")
// ErrTraceCorrupted occurs when the `carrier` passed to
// Tracer.Extract() is of the expected type but is corrupted.
ErrTraceCorrupted = errs.New("trace: Trace data corrupted in Extract carrier")
)
// BuiltinFormat is used to demarcate the values within package `trace`
// that are intended for use with the Tracer.Inject() and Tracer.Extract()
// methods.
type BuiltinFormat byte
// support format list
const (
// HTTPFormat represents Trace as HTTP header string pairs.
//
// the HTTPFormat 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).
//
// the carrier must be a `http.Header`.
HTTPFormat BuiltinFormat = iota
// GRPCFormat represents Trace as gRPC metadata.
//
// the carrier must be a `google.golang.org/grpc/metadata.MD`.
GRPCFormat
)
// Carrier propagator must convert generic interface{} to something this
// implement Carrier interface, Trace can use Carrier to represents itself.
type Carrier interface {
Set(key, val string)
Get(key string) string
}
// propagator is responsible for injecting and extracting `Trace` instances
// from a format-specific "carrier"
type propagator interface {
Inject(carrier interface{}) (Carrier, error)
Extract(carrier interface{}) (Carrier, error)
}
type httpPropagator struct{}
type httpCarrier http.Header
func (h httpCarrier) Set(key, val string) {
http.Header(h).Set(key, val)
}
func (h httpCarrier) Get(key string) string {
return http.Header(h).Get(key)
}
func (httpPropagator) Inject(carrier interface{}) (Carrier, error) {
header, ok := carrier.(http.Header)
if !ok {
return nil, ErrInvalidCarrier
}
if header == nil {
return nil, ErrInvalidTrace
}
return httpCarrier(header), nil
}
func (httpPropagator) Extract(carrier interface{}) (Carrier, error) {
header, ok := carrier.(http.Header)
if !ok {
return nil, ErrInvalidCarrier
}
if header == nil {
return nil, ErrTraceNotFound
}
return httpCarrier(header), nil
}
const legacyGRPCKey = "trace"
type grpcPropagator struct{}
type grpcCarrier map[string][]string
func (g grpcCarrier) Get(key string) string {
if v, ok := g[key]; ok && len(v) > 0 {
return v[0]
}
// ts := g[legacyGRPCKey]
// if len(ts) != 8 {
// return ""
// }
// switch key {
// case KeyTraceID:
// return ts[0]
// case KeyTraceSpanID:
// return ts[1]
// case KeyTraceParentID:
// return ts[2]
// case KeyTraceLevel:
// return ts[3]
// case KeyTraceSampled:
// return ts[4]
// case KeyTraceCaller:
// return ts[5]
// }
return ""
}
func (g grpcCarrier) Set(key, val string) {
// ts := make([]string, 8)
// g[legacyGRPCKey] = ts
// switch key {
// case KeyTraceID:
// ts[0] = val
// case KeyTraceSpanID:
// ts[1] = val
// case KeyTraceParentID:
// ts[2] = val
// case KeyTraceLevel:
// ts[3] = val
// case KeyTraceSampled:
// ts[4] = val
// case KeyTraceCaller:
// ts[5] = val
// default:
g[key] = append(g[key], val)
// }
}
func (grpcPropagator) Inject(carrier interface{}) (Carrier, error) {
md, ok := carrier.(metadata.MD)
if !ok {
return nil, ErrInvalidCarrier
}
if md == nil {
return nil, ErrInvalidTrace
}
return grpcCarrier(md), nil
}
func (grpcPropagator) Extract(carrier interface{}) (Carrier, error) {
md, ok := carrier.(metadata.MD)
if !ok {
return nil, ErrInvalidCarrier
}
if md == nil {
return nil, ErrTraceNotFound
}
return grpcCarrier(md), nil
}