go.uber.org/yarpc@v1.72.1/transport/tchannel/options.go (about)

     1  // Copyright (c) 2022 Uber Technologies, Inc.
     2  //
     3  // Permission is hereby granted, free of charge, to any person obtaining a copy
     4  // of this software and associated documentation files (the "Software"), to deal
     5  // in the Software without restriction, including without limitation the rights
     6  // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
     7  // copies of the Software, and to permit persons to whom the Software is
     8  // furnished to do so, subject to the following conditions:
     9  //
    10  // The above copyright notice and this permission notice shall be included in
    11  // all copies or substantial portions of the Software.
    12  //
    13  // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
    14  // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
    15  // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
    16  // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
    17  // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
    18  // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
    19  // THE SOFTWARE.
    20  
    21  package tchannel
    22  
    23  import (
    24  	"context"
    25  	"crypto/tls"
    26  	"net"
    27  	"time"
    28  
    29  	"github.com/opentracing/opentracing-go"
    30  	"github.com/uber/tchannel-go"
    31  	"go.uber.org/net/metrics"
    32  	backoffapi "go.uber.org/yarpc/api/backoff"
    33  	yarpctls "go.uber.org/yarpc/api/transport/tls"
    34  	"go.uber.org/yarpc/internal/backoff"
    35  	"go.uber.org/zap"
    36  )
    37  
    38  // Option allows customizing the YARPC TChannel transport.
    39  // TransportSpec() accepts any TransportOption, and may in the future also
    40  // accept inbound and outbound options.
    41  type Option interface {
    42  	tchannelOption()
    43  }
    44  
    45  var _ Option = (TransportOption)(nil)
    46  
    47  // transportOptions is suitable for conveying options to TChannel transport
    48  // constructors (NewTransport and NewChannelTransport).
    49  // At time of writing, there is only a ChannelTransport constructor, which
    50  // supports options like WithChannel that only apply to this constructor form.
    51  // The transportOptions should also be suitable, albeit with extraneous properties,
    52  // if used for NewTransport, which will return a Transport suitable for YARPC
    53  // peer lists.
    54  // TODO update above when NewTransport is real.
    55  type transportOptions struct {
    56  	ch                             Channel
    57  	tracer                         opentracing.Tracer
    58  	logger                         *zap.Logger
    59  	meter                          *metrics.Scope
    60  	addr                           string
    61  	listener                       net.Listener
    62  	dialer                         func(ctx context.Context, network, hostPort string) (net.Conn, error)
    63  	name                           string
    64  	connTimeout                    time.Duration
    65  	connBackoffStrategy            backoffapi.Strategy
    66  	originalHeaders                bool
    67  	nativeTChannelMethods          NativeTChannelMethods
    68  	excludeServiceHeaderInResponse bool
    69  	inboundTLSConfig               *tls.Config
    70  	inboundTLSMode                 *yarpctls.Mode
    71  	outboundTLSConfigProvider      yarpctls.OutboundTLSConfigProvider
    72  }
    73  
    74  // newTransportOptions constructs the default transport options struct
    75  func newTransportOptions() transportOptions {
    76  	return transportOptions{
    77  		tracer:              opentracing.GlobalTracer(),
    78  		connTimeout:         defaultConnTimeout,
    79  		connBackoffStrategy: backoff.DefaultExponential,
    80  	}
    81  }
    82  
    83  // TransportOption customizes the behavior of a TChannel Transport.
    84  type TransportOption func(*transportOptions)
    85  
    86  // TransportOption makes all TransportOptions recognizeable as Option so
    87  // TransportSpec will accept them.
    88  func (TransportOption) tchannelOption() {}
    89  
    90  // Tracer specifies the request tracer used for RPCs passing through the
    91  // TChannel transport.
    92  func Tracer(tracer opentracing.Tracer) TransportOption {
    93  	return func(t *transportOptions) {
    94  		t.tracer = tracer
    95  	}
    96  }
    97  
    98  // Logger sets a logger to use for internal logging.
    99  //
   100  // The default is to not write any logs.
   101  func Logger(logger *zap.Logger) TransportOption {
   102  	return func(t *transportOptions) {
   103  		t.logger = logger
   104  	}
   105  }
   106  
   107  // Meter sets a meter to use for transport metrics.
   108  //
   109  // The default is to not emit any transport metrics.
   110  func Meter(meter *metrics.Scope) TransportOption {
   111  	return func(t *transportOptions) {
   112  		t.meter = meter
   113  	}
   114  }
   115  
   116  // OutboundTLSConfigProvider returns a TransportOption that provides the
   117  // outbound TLS config provider.
   118  func OutboundTLSConfigProvider(provider yarpctls.OutboundTLSConfigProvider) TransportOption {
   119  	return func(transportOptions *transportOptions) {
   120  		transportOptions.outboundTLSConfigProvider = provider
   121  	}
   122  }
   123  
   124  // WithChannel specifies the TChannel Channel to use to send and receive YARPC
   125  // requests. The instance may already have handlers registered against it;
   126  // these will be left unchanged.
   127  //
   128  // If this option is not passed, the Transport will build and manage its own
   129  // Channel. The behavior of that TChannel may be customized using the
   130  // ListenAddr and ServiceName options.
   131  //
   132  // This option is disallowed for NewTransport and transports constructed with
   133  // the YARPC configuration system.
   134  func WithChannel(ch Channel) TransportOption {
   135  	return func(options *transportOptions) {
   136  		options.ch = ch
   137  	}
   138  }
   139  
   140  // ListenAddr specifies the port the TChannel should listen on.  This defaults
   141  // to ":0" (all interfaces, OS-assigned port).
   142  //
   143  // 	transport := NewChannelTransport(ServiceName("myservice"), ListenAddr(":4040"))
   144  //
   145  // This option has no effect if WithChannel was used and the TChannel was
   146  // already listening, and it is disallowed for transports constructed with the
   147  // YARPC configuration system.
   148  func ListenAddr(addr string) TransportOption {
   149  	return func(options *transportOptions) {
   150  		options.addr = addr
   151  	}
   152  }
   153  
   154  // Listener sets a net.Listener to use for the channel. This only applies to
   155  // NewTransport (will not work with NewChannelTransport).
   156  //
   157  // The default is to depend on the ListenAddr (no-op).
   158  func Listener(l net.Listener) TransportOption {
   159  	return func(t *transportOptions) {
   160  		t.listener = l
   161  	}
   162  }
   163  
   164  // Dialer sets a dialer function for outbound calls.
   165  //
   166  // The function signature matches the net.Dialer DialContext method.
   167  // https://golang.org/pkg/net/#Dialer.DialContext
   168  func Dialer(dialer func(ctx context.Context, network, hostPort string) (net.Conn, error)) TransportOption {
   169  	return func(t *transportOptions) {
   170  		t.dialer = dialer
   171  	}
   172  }
   173  
   174  // ServiceName informs the NewChannelTransport constructor which service
   175  // name to use if it needs to construct a root Channel object, as when called
   176  // without the WithChannel option.
   177  //
   178  // ServiceName specifies the name of the current service for the YARPC-owned
   179  // TChannel Channel. If the WithChannel option is not specified, the TChannel
   180  // Transport will build its own TChannel Chanel and use this name for that
   181  // Channel.
   182  //
   183  // This option has no effect if WithChannel was used, and it is disallowed for
   184  // transports constructed with the YARPC configuration system.
   185  func ServiceName(name string) TransportOption {
   186  	return func(options *transportOptions) {
   187  		options.name = name
   188  	}
   189  }
   190  
   191  // ConnTimeout specifies the time that TChannel will wait for a
   192  // connection attempt to any retained peer.
   193  //
   194  // The default is half of a second.
   195  func ConnTimeout(d time.Duration) TransportOption {
   196  	return func(options *transportOptions) {
   197  		options.connTimeout = d
   198  	}
   199  }
   200  
   201  // ConnBackoff specifies the connection backoff strategy for delays between
   202  // connection attempts for each peer.
   203  //
   204  // ConnBackoff accepts a function that creates new backoff instances.
   205  // The transport uses this to make referentially independent backoff instances
   206  // that will not be shared across goroutines.
   207  //
   208  // The backoff instance is a function that accepts connection attempts and
   209  // returns a duration.
   210  //
   211  // The default is exponential backoff starting with 10ms fully jittered,
   212  // doubling each attempt, with a maximum interval of 30s.
   213  func ConnBackoff(s backoffapi.Strategy) TransportOption {
   214  	return func(options *transportOptions) {
   215  		options.connBackoffStrategy = s
   216  	}
   217  }
   218  
   219  // OriginalHeaders specifies whether to forward headers without canonicalizing them
   220  func OriginalHeaders() TransportOption {
   221  	return func(options *transportOptions) {
   222  		options.originalHeaders = true
   223  	}
   224  }
   225  
   226  // NativeTChannelMethods interface exposes methods which returns all
   227  // the native TChannel methods and list of method names whose requests must
   228  // be handled by the provided TChannel handlers.
   229  type NativeTChannelMethods interface {
   230  	// Methods returns a map of all the native handlers by method name.
   231  	Methods() map[string]tchannel.Handler
   232  
   233  	// SkipMethodNames returns a list of method names whose requests must be
   234  	// handled by the provide TChannel handlers.
   235  	SkipMethodNames() []string
   236  }
   237  
   238  // WithNativeTChannelMethods specifies the list of methods whose requests must
   239  // be handled by the provided native TChannel method handlers.
   240  //
   241  // Requests with other methods will be handled by the Yarpc router.
   242  // This is useful for gradual migration.
   243  func WithNativeTChannelMethods(nativeMethods NativeTChannelMethods) TransportOption {
   244  	return func(option *transportOptions) {
   245  		option.nativeTChannelMethods = nativeMethods
   246  	}
   247  }
   248  
   249  // ExcludeServiceHeaderInResponse stop adding the $rpc$-service response header for inbounds
   250  func ExcludeServiceHeaderInResponse() TransportOption {
   251  	return func(option *transportOptions) {
   252  		option.excludeServiceHeaderInResponse = true
   253  	}
   254  }
   255  
   256  // InboundTLSMode return TransportOption that sets inbound TLS mode.
   257  // It must be noted that TLS configuration must be passed separately using
   258  // option InboundTLSConfiguration.
   259  func InboundTLSMode(mode yarpctls.Mode) TransportOption {
   260  	return func(option *transportOptions) {
   261  		option.inboundTLSMode = &mode
   262  	}
   263  }
   264  
   265  // InboundTLSConfiguration returns TransportOption that provides the TLS
   266  // configuration used for setting up TLS inbound.
   267  func InboundTLSConfiguration(tlsConfig *tls.Config) TransportOption {
   268  	return func(option *transportOptions) {
   269  		option.inboundTLSConfig = tlsConfig
   270  	}
   271  }