Import upstream version 1.0.0+git20201217.1.08d136d
Debian Janitor
3 years ago
4 | 4 | - 1.14.x |
5 | 5 | - tip |
6 | 6 | |
7 | arch: | |
8 | - amd64 | |
9 | - ppc64le | |
10 | ||
7 | 11 | script: |
8 | 12 | - go test -v -cover -race ./... |
9 | 13 |
33 | 33 | type clientOptions struct { |
34 | 34 | operationName string |
35 | 35 | componentName string |
36 | urlTagFunc func(u *url.URL) string | |
36 | urlTagFunc func(u *url.URL) string | |
37 | 37 | disableClientTrace bool |
38 | 38 | disableInjectSpanContext bool |
39 | 39 | spanObserver func(span opentracing.Span, r *http.Request) |
148 | 148 | return err |
149 | 149 | } |
150 | 150 | |
151 | type writerCloseTracker struct { | |
152 | io.ReadWriteCloser | |
153 | sp opentracing.Span | |
154 | } | |
155 | ||
156 | func (c writerCloseTracker) Close() error { | |
157 | err := c.ReadWriteCloser.Close() | |
158 | c.sp.LogFields(log.String("event", "ClosedBody")) | |
159 | c.sp.Finish() | |
160 | return err | |
161 | } | |
162 | ||
151 | 163 | // TracerFromRequest retrieves the Tracer from the request. If the request does |
152 | 164 | // not have a Tracer it will return nil. |
153 | 165 | func TracerFromRequest(req *http.Request) *Tracer { |
173 | 185 | |
174 | 186 | ext.HTTPMethod.Set(tracer.sp, req.Method) |
175 | 187 | ext.HTTPUrl.Set(tracer.sp, tracer.opts.urlTagFunc(req.URL)) |
188 | ext.PeerAddress.Set(tracer.sp, req.URL.Host) | |
176 | 189 | tracer.opts.spanObserver(tracer.sp, req) |
177 | 190 | |
178 | 191 | if !tracer.opts.disableInjectSpanContext { |
193 | 206 | if req.Method == "HEAD" { |
194 | 207 | tracer.sp.Finish() |
195 | 208 | } else { |
196 | resp.Body = closeTracker{resp.Body, tracer.sp} | |
209 | readWriteCloser, ok := resp.Body.(io.ReadWriteCloser) | |
210 | if ok { | |
211 | resp.Body = writerCloseTracker{readWriteCloser, tracer.sp} | |
212 | } else { | |
213 | resp.Body = closeTracker{resp.Body, tracer.sp} | |
214 | } | |
197 | 215 | } |
198 | 216 | return resp, nil |
199 | 217 | } |
222 | 240 | } |
223 | 241 | |
224 | 242 | ctx := h.root.Context() |
225 | h.sp = h.tr.StartSpan("HTTP "+req.Method, opentracing.ChildOf(ctx)) | |
226 | ext.SpanKindRPCClient.Set(h.sp) | |
243 | h.sp = h.tr.StartSpan("HTTP "+req.Method, opentracing.ChildOf(ctx), ext.SpanKindRPCClient) | |
227 | 244 | |
228 | 245 | componentName := h.opts.componentName |
229 | 246 | if componentName == "" { |
265 | 282 | } |
266 | 283 | |
267 | 284 | func (h *Tracer) getConn(hostPort string) { |
268 | ext.HTTPUrl.Set(h.sp, hostPort) | |
269 | h.sp.LogFields(log.String("event", "GetConn")) | |
285 | h.sp.LogFields(log.String("event", "GetConn"), log.String("hostPort", hostPort)) | |
270 | 286 | } |
271 | 287 | |
272 | 288 | func (h *Tracer) gotConn(info httptrace.GotConnInfo) { |
0 | 0 | package nethttp |
1 | 1 | |
2 | 2 | import ( |
3 | "bytes" | |
4 | "fmt" | |
5 | "io" | |
3 | 6 | "net/http" |
4 | 7 | "net/http/httptest" |
5 | 8 | "net/url" |
134 | 137 | } |
135 | 138 | } |
136 | 139 | |
140 | func TestWriteCloserFromRequest(t *testing.T) { | |
141 | wait := make(chan bool, 0) | |
142 | srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { | |
143 | defer func() { | |
144 | wait <- true | |
145 | }() | |
146 | ||
147 | w.Header().Set("Upgrade", "websocket") | |
148 | w.Header().Set("Connection", "Upgrade") | |
149 | w.WriteHeader(http.StatusSwitchingProtocols) | |
150 | ||
151 | hijacker := w.(http.Hijacker) | |
152 | _, rw, err := hijacker.Hijack() | |
153 | ||
154 | if err != nil { | |
155 | t.Fatal("Failed to hijack connection") | |
156 | } | |
157 | ||
158 | line, _, err := rw.ReadLine() | |
159 | if string(line) != "ping" { | |
160 | t.Fatalf("Expected 'ping' received %q", string(line)) | |
161 | } | |
162 | ||
163 | if err != nil { | |
164 | t.Fatal(err) | |
165 | } | |
166 | })) | |
167 | ||
168 | var buf bytes.Buffer | |
169 | req, err := http.NewRequest("POST", srv.URL, &buf) | |
170 | req.Header.Set("Connection", "upgrade") | |
171 | req.Header.Set("Upgrade", "websocket") | |
172 | req.Proto = "HTTP/1.1" | |
173 | req.ProtoMajor = 1 | |
174 | req.ProtoMinor = 1 | |
175 | if err != nil { | |
176 | t.Fatal(err) | |
177 | } | |
178 | ||
179 | tr := &mocktracer.MockTracer{} | |
180 | req, _ = TraceRequest(tr, req) | |
181 | ||
182 | client := &http.Client{Transport: &Transport{}} | |
183 | resp, err := client.Do(req) | |
184 | if err != nil { | |
185 | t.Fatal(err) | |
186 | } | |
187 | ||
188 | rw, ok := resp.Body.(io.ReadWriteCloser) | |
189 | if !ok { | |
190 | t.Fatal("resp.Body is not a io.ReadWriteCloser") | |
191 | } | |
192 | ||
193 | fmt.Fprint(rw, "ping\n") | |
194 | <-wait | |
195 | rw.Close() | |
196 | } | |
197 | ||
137 | 198 | func TestInjectSpanContext(t *testing.T) { |
138 | 199 | tests := []struct { |
139 | 200 | name string |
226 | 287 | tag string |
227 | 288 | }{ |
228 | 289 | // These first cases fail early |
229 | {[]ClientOption{}, "/ok?token=a", srv.Listener.Addr().String()}, | |
230 | {[]ClientOption{URLTagFunc(fn)}, "/ok?token=c", srv.Listener.Addr().String()}, | |
290 | {[]ClientOption{}, "/ok?token=a", srv.URL + "/ok?token=a"}, | |
291 | {[]ClientOption{URLTagFunc(fn)}, "/ok?token=c", srv.URL + "/ok?token=*"}, | |
231 | 292 | // Disable ClientTrace to fire RoundTrip |
232 | 293 | {[]ClientOption{ClientTrace(false)}, "/ok?token=b", srv.URL + "/ok?token=b"}, |
233 | 294 | {[]ClientOption{ClientTrace(false), URLTagFunc(fn)}, "/ok?token=c", srv.URL + "/ok?token=*"}, |
250 | 311 | if got, want := tag, tt.tag; got != want { |
251 | 312 | t.Fatalf("got %s tag name, expected %s", got, want) |
252 | 313 | } |
253 | } | |
254 | }⏎ | |
314 | peerAddress, ok := clientSpan.Tags()["peer.address"] | |
315 | if !ok { | |
316 | t.Fatal("cannot find peer.address tag") | |
317 | } | |
318 | if peerAddress != srv.Listener.Addr().String() { | |
319 | t.Fatalf("got %s want %s in peer.address tag", peerAddress, srv.Listener.Addr().String()) | |
320 | } | |
321 | } | |
322 | } |