go.uber.org/yarpc@v1.72.1/transport/internal/tls/metrics/observer.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 metrics
    22  
    23  import (
    24  	"crypto/tls"
    25  
    26  	"go.uber.org/net/metrics"
    27  	yarpctls "go.uber.org/yarpc/api/transport/tls"
    28  	"go.uber.org/zap"
    29  )
    30  
    31  const (
    32  	_serviceTag   = "service"
    33  	_transportTag = "transport"
    34  	_versionTag   = "version"
    35  	_destTag      = "dest"
    36  	_directionTag = "direction"
    37  	_modeTag      = "mode"
    38  	_componentTag = "component"
    39  )
    40  
    41  // Params holds parameters needed for creating new observer.
    42  type Params struct {
    43  	Meter         *metrics.Scope
    44  	Logger        *zap.Logger
    45  	ServiceName   string // Name of the service.
    46  	TransportName string // Name of the transport.
    47  	Direction     string // Inbound or Outbound.
    48  	Dest          string // Name of the dest, only for outbound.
    49  	Mode          yarpctls.Mode
    50  }
    51  
    52  // Observer holds connection metrics.
    53  type Observer struct {
    54  	plaintextConnectionsCounter *metrics.Counter
    55  	tlsConnectionsCounter       *metrics.CounterVector
    56  	tlsFailuresCounter          *metrics.Counter
    57  }
    58  
    59  // NewObserver returns observer for emitting connection metrics.
    60  func NewObserver(p Params) *Observer {
    61  	tags := metrics.Tags{
    62  		_componentTag: "yarpc",
    63  		_serviceTag:   p.ServiceName,
    64  		_transportTag: p.TransportName,
    65  		_modeTag:      p.Mode.String(),
    66  		_directionTag: p.Direction,
    67  		_destTag:      p.Dest,
    68  	}
    69  
    70  	plaintextConns, err := p.Meter.Counter(metrics.Spec{
    71  		Name:      "plaintext_connections",
    72  		Help:      "Total number of plaintext connections established.",
    73  		ConstTags: tags,
    74  	})
    75  	if err != nil {
    76  		p.Logger.Error("failed to create plaintext connections counter", zap.Error(err))
    77  	}
    78  
    79  	tlsConns, err := p.Meter.CounterVector(metrics.Spec{
    80  		Name:      "tls_connections",
    81  		Help:      "Total number of TLS connections established.",
    82  		ConstTags: tags,
    83  		VarTags:   []string{_versionTag},
    84  	})
    85  	if err != nil {
    86  		p.Logger.Error("failed to create tls connections counter", zap.Error(err))
    87  	}
    88  
    89  	tlsHandshakeFailures, err := p.Meter.Counter(metrics.Spec{
    90  		Name:      "tls_handshake_failures",
    91  		Help:      "Total number of TLS handshake failures.",
    92  		ConstTags: tags,
    93  	})
    94  	if err != nil {
    95  		p.Logger.Error("failed to create tls handshake failures counter", zap.Error(err))
    96  	}
    97  
    98  	return &Observer{
    99  		tlsConnectionsCounter:       tlsConns,
   100  		tlsFailuresCounter:          tlsHandshakeFailures,
   101  		plaintextConnectionsCounter: plaintextConns,
   102  	}
   103  }
   104  
   105  // IncPlaintextConnections increments plaintext connections metric.
   106  func (o *Observer) IncPlaintextConnections() {
   107  	o.plaintextConnectionsCounter.Inc()
   108  }
   109  
   110  // IncTLSConnections increments TLS connections metric.
   111  func (o *Observer) IncTLSConnections(version uint16) {
   112  	o.tlsConnectionsCounter.MustGet(_versionTag, tlsVersionString(version)).Inc()
   113  }
   114  
   115  // IncTLSHandshakeFailures increments TLS handshake failures metric.
   116  func (o *Observer) IncTLSHandshakeFailures() {
   117  	o.tlsFailuresCounter.Inc()
   118  }
   119  
   120  func tlsVersionString(version uint16) string {
   121  	switch version {
   122  	case tls.VersionTLS10:
   123  		return "1.0"
   124  	case tls.VersionTLS11:
   125  		return "1.1"
   126  	case tls.VersionTLS12:
   127  		return "1.2"
   128  	case tls.VersionTLS13:
   129  		return "1.3"
   130  	default:
   131  		return "unknown"
   132  	}
   133  }