1 // Copyright 2018, OpenCensus Authors
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
7 // http://www.apache.org/licenses/LICENSE-2.0
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
21 "go.opencensus.io/trace"
22 "go.opencensus.io/trace/propagation"
25 // Transport is an http.RoundTripper that instruments all outgoing requests with
26 // OpenCensus stats and tracing.
28 // The zero value is intended to be a useful default, but for
29 // now it's recommended that you explicitly set Propagation, since the default
30 // for this may change.
31 type Transport struct {
32 // Base may be set to wrap another http.RoundTripper that does the actual
33 // requests. By default http.DefaultTransport is used.
35 // If base HTTP roundtripper implements CancelRequest,
36 // the returned round tripper will be cancelable.
37 Base http.RoundTripper
39 // Propagation defines how traces are propagated. If unspecified, a default
40 // (currently B3 format) will be used.
41 Propagation propagation.HTTPFormat
43 // StartOptions are applied to the span started by this Transport around each
46 // StartOptions.SpanKind will always be set to trace.SpanKindClient
47 // for spans started by this transport.
48 StartOptions trace.StartOptions
50 // GetStartOptions allows to set start options per request. If set,
51 // StartOptions is going to be ignored.
52 GetStartOptions func(*http.Request) trace.StartOptions
54 // NameFromRequest holds the function to use for generating the span name
55 // from the information found in the outgoing HTTP Request. By default the
56 // name equals the URL Path.
57 FormatSpanName func(*http.Request) string
59 // NewClientTrace may be set to a function allowing the current *trace.Span
60 // to be annotated with HTTP request event information emitted by the
62 NewClientTrace func(*http.Request, *trace.Span) *httptrace.ClientTrace
64 // TODO: Implement tag propagation for HTTP.
67 // RoundTrip implements http.RoundTripper, delegating to Base and recording stats and traces for the request.
68 func (t *Transport) RoundTrip(req *http.Request) (*http.Response, error) {
70 if isHealthEndpoint(req.URL.Path) {
71 return rt.RoundTrip(req)
73 // TODO: remove excessive nesting of http.RoundTrippers here.
74 format := t.Propagation
76 format = defaultFormat
78 spanNameFormatter := t.FormatSpanName
79 if spanNameFormatter == nil {
80 spanNameFormatter = spanNameFromURL
83 startOpts := t.StartOptions
84 if t.GetStartOptions != nil {
85 startOpts = t.GetStartOptions(req)
91 startOptions: trace.StartOptions{
92 Sampler: startOpts.Sampler,
93 SpanKind: trace.SpanKindClient,
95 formatSpanName: spanNameFormatter,
96 newClientTrace: t.NewClientTrace,
98 rt = statsTransport{base: rt}
99 return rt.RoundTrip(req)
102 func (t *Transport) base() http.RoundTripper {
106 return http.DefaultTransport
109 // CancelRequest cancels an in-flight request by closing its connection.
110 func (t *Transport) CancelRequest(req *http.Request) {
111 type canceler interface {
112 CancelRequest(*http.Request)
114 if cr, ok := t.base().(canceler); ok {
115 cr.CancelRequest(req)