mirror of
https://github.com/rclone/rclone.git
synced 2024-11-29 20:04:52 +01:00
118 lines
3.6 KiB
Go
118 lines
3.6 KiB
Go
// 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
|
|
|
|
// GetStartOptions allows to set start options per request. If set,
|
|
// StartOptions is going to be ignored.
|
|
GetStartOptions func(*http.Request) 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
|
|
}
|
|
|
|
startOpts := t.StartOptions
|
|
if t.GetStartOptions != nil {
|
|
startOpts = t.GetStartOptions(req)
|
|
}
|
|
|
|
rt = &traceTransport{
|
|
base: rt,
|
|
format: format,
|
|
startOptions: trace.StartOptions{
|
|
Sampler: startOpts.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)
|
|
}
|
|
}
|