You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
108 lines
3.3 KiB
108 lines
3.3 KiB
6 years ago
|
// Copyright 2018, OpenCensus Authors
|
||
|
//
|
||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||
|
// you may not use this file except in compliance with the License.
|
||
|
// You may obtain a copy of the License at
|
||
|
//
|
||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||
|
//
|
||
|
// Unless required by applicable law or agreed to in writing, software
|
||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||
|
// See the License for the specific language governing permissions and
|
||
|
// limitations under the License.
|
||
|
|
||
|
package ochttp
|
||
|
|
||
|
import (
|
||
|
"net/http"
|
||
|
"net/http/httptrace"
|
||
|
|
||
|
"go.opencensus.io/trace"
|
||
|
"go.opencensus.io/trace/propagation"
|
||
|
)
|
||
|
|
||
|
// Transport is an http.RoundTripper that instruments all outgoing requests with
|
||
|
// OpenCensus stats and tracing.
|
||
|
//
|
||
|
// The zero value is intended to be a useful default, but for
|
||
|
// now it's recommended that you explicitly set Propagation, since the default
|
||
|
// for this may change.
|
||
|
type Transport struct {
|
||
|
// Base may be set to wrap another http.RoundTripper that does the actual
|
||
|
// requests. By default http.DefaultTransport is used.
|
||
|
//
|
||
|
// If base HTTP roundtripper implements CancelRequest,
|
||
|
// the returned round tripper will be cancelable.
|
||
|
Base http.RoundTripper
|
||
|
|
||
|
// Propagation defines how traces are propagated. If unspecified, a default
|
||
|
// (currently B3 format) will be used.
|
||
|
Propagation propagation.HTTPFormat
|
||
|
|
||
|
// StartOptions are applied to the span started by this Transport around each
|
||
|
// request.
|
||
|
//
|
||
|
// StartOptions.SpanKind will always be set to trace.SpanKindClient
|
||
|
// for spans started by this transport.
|
||
|
StartOptions trace.StartOptions
|
||
|
|
||
|
// NameFromRequest holds the function to use for generating the span name
|
||
|
// from the information found in the outgoing HTTP Request. By default the
|
||
|
// name equals the URL Path.
|
||
|
FormatSpanName func(*http.Request) string
|
||
|
|
||
|
// NewClientTrace may be set to a function allowing the current *trace.Span
|
||
|
// to be annotated with HTTP request event information emitted by the
|
||
|
// httptrace package.
|
||
|
NewClientTrace func(*http.Request, *trace.Span) *httptrace.ClientTrace
|
||
|
|
||
|
// TODO: Implement tag propagation for HTTP.
|
||
|
}
|
||
|
|
||
|
// RoundTrip implements http.RoundTripper, delegating to Base and recording stats and traces for the request.
|
||
|
func (t *Transport) RoundTrip(req *http.Request) (*http.Response, error) {
|
||
|
rt := t.base()
|
||
|
if isHealthEndpoint(req.URL.Path) {
|
||
|
return rt.RoundTrip(req)
|
||
|
}
|
||
|
// TODO: remove excessive nesting of http.RoundTrippers here.
|
||
|
format := t.Propagation
|
||
|
if format == nil {
|
||
|
format = defaultFormat
|
||
|
}
|
||
|
spanNameFormatter := t.FormatSpanName
|
||
|
if spanNameFormatter == nil {
|
||
|
spanNameFormatter = spanNameFromURL
|
||
|
}
|
||
|
rt = &traceTransport{
|
||
|
base: rt,
|
||
|
format: format,
|
||
|
startOptions: trace.StartOptions{
|
||
|
Sampler: t.StartOptions.Sampler,
|
||
|
SpanKind: trace.SpanKindClient,
|
||
|
},
|
||
|
formatSpanName: spanNameFormatter,
|
||
|
newClientTrace: t.NewClientTrace,
|
||
|
}
|
||
|
rt = statsTransport{base: rt}
|
||
|
return rt.RoundTrip(req)
|
||
|
}
|
||
|
|
||
|
func (t *Transport) base() http.RoundTripper {
|
||
|
if t.Base != nil {
|
||
|
return t.Base
|
||
|
}
|
||
|
return http.DefaultTransport
|
||
|
}
|
||
|
|
||
|
// CancelRequest cancels an in-flight request by closing its connection.
|
||
|
func (t *Transport) CancelRequest(req *http.Request) {
|
||
|
type canceler interface {
|
||
|
CancelRequest(*http.Request)
|
||
|
}
|
||
|
if cr, ok := t.base().(canceler); ok {
|
||
|
cr.CancelRequest(req)
|
||
|
}
|
||
|
}
|