github.com/ethereum/go-ethereum@v1.16.1/p2p/metrics.go (about) 1 // Copyright 2015 The go-ethereum Authors 2 // This file is part of the go-ethereum library. 3 // 4 // The go-ethereum library is free software: you can redistribute it and/or modify 5 // it under the terms of the GNU Lesser General Public License as published by 6 // the Free Software Foundation, either version 3 of the License, or 7 // (at your option) any later version. 8 // 9 // The go-ethereum library is distributed in the hope that it will be useful, 10 // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 // GNU Lesser General Public License for more details. 13 // 14 // You should have received a copy of the GNU Lesser General Public License 15 // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>. 16 17 // Contains the meters and timers used by the networking layer. 18 19 package p2p 20 21 import ( 22 "errors" 23 "net" 24 25 "github.com/ethereum/go-ethereum/metrics" 26 ) 27 28 const ( 29 // HandleHistName is the prefix of the per-packet serving time histograms. 30 HandleHistName = "p2p/handle" 31 32 // ingressMeterName is the prefix of the per-packet inbound metrics. 33 ingressMeterName = "p2p/ingress" 34 35 // egressMeterName is the prefix of the per-packet outbound metrics. 36 egressMeterName = "p2p/egress" 37 ) 38 39 var ( 40 activePeerGauge = metrics.NewRegisteredGauge("p2p/peers", nil) 41 activeInboundPeerGauge = metrics.NewRegisteredGauge("p2p/peers/inbound", nil) 42 activeOutboundPeerGauge = metrics.NewRegisteredGauge("p2p/peers/outbound", nil) 43 44 ingressTrafficMeter = metrics.NewRegisteredMeter("p2p/ingress", nil) 45 egressTrafficMeter = metrics.NewRegisteredMeter("p2p/egress", nil) 46 47 // general ingress/egress connection meters 48 serveMeter = metrics.NewRegisteredMeter("p2p/serves", nil) 49 serveSuccessMeter = metrics.NewRegisteredMeter("p2p/serves/success", nil) 50 dialMeter = metrics.NewRegisteredMeter("p2p/dials", nil) 51 dialSuccessMeter = metrics.NewRegisteredMeter("p2p/dials/success", nil) 52 dialConnectionError = metrics.NewRegisteredMeter("p2p/dials/error/connection", nil) // dial timeout; no route to host; connection refused; network is unreachable 53 54 // count peers that stayed connected for at least 1 min 55 serve1MinSuccessMeter = metrics.NewRegisteredMeter("p2p/serves/success/1min", nil) 56 dial1MinSuccessMeter = metrics.NewRegisteredMeter("p2p/dials/success/1min", nil) 57 58 // handshake error meters 59 dialTooManyPeers = metrics.NewRegisteredMeter("p2p/dials/error/saturated", nil) 60 dialAlreadyConnected = metrics.NewRegisteredMeter("p2p/dials/error/known", nil) 61 dialSelf = metrics.NewRegisteredMeter("p2p/dials/error/self", nil) 62 dialUselessPeer = metrics.NewRegisteredMeter("p2p/dials/error/useless", nil) 63 dialUnexpectedIdentity = metrics.NewRegisteredMeter("p2p/dials/error/id/unexpected", nil) 64 dialEncHandshakeError = metrics.NewRegisteredMeter("p2p/dials/error/rlpx/enc", nil) // EOF; connection reset during handshake; message too big; i/o timeout 65 dialProtoHandshakeError = metrics.NewRegisteredMeter("p2p/dials/error/rlpx/proto", nil) // EOF 66 67 // capture the rest of errors that are not handled by the above meters 68 dialOtherError = metrics.NewRegisteredMeter("p2p/dials/error/other", nil) 69 70 // handshake error meters for inbound connections 71 serveTooManyPeers = metrics.NewRegisteredMeter("p2p/serves/error/saturated", nil) 72 serveAlreadyConnected = metrics.NewRegisteredMeter("p2p/serves/error/known", nil) 73 serveSelf = metrics.NewRegisteredMeter("p2p/serves/error/self", nil) 74 serveUselessPeer = metrics.NewRegisteredMeter("p2p/serves/error/useless", nil) 75 serveUnexpectedIdentity = metrics.NewRegisteredMeter("p2p/serves/error/id/unexpected", nil) 76 serveEncHandshakeError = metrics.NewRegisteredMeter("p2p/serves/error/rlpx/enc", nil) //EOF; connection reset during handshake; (message too big?) 77 serveProtoHandshakeError = metrics.NewRegisteredMeter("p2p/serves/error/rlpx/proto", nil) 78 79 // capture the rest of errors that are not handled by the above meters 80 serveOtherError = metrics.NewRegisteredMeter("p2p/serves/error/other", nil) 81 ) 82 83 // markDialError matches errors that occur while setting up a dial connection to the 84 // corresponding meter. We don't maintain meters for evert possible error, just for 85 // the most interesting ones. 86 func markDialError(err error) { 87 if !metrics.Enabled() { 88 return 89 } 90 91 var reason DiscReason 92 var handshakeErr *protoHandshakeError 93 d := errors.As(err, &reason) 94 switch { 95 case d && reason == DiscTooManyPeers: 96 dialTooManyPeers.Mark(1) 97 case d && reason == DiscAlreadyConnected: 98 dialAlreadyConnected.Mark(1) 99 case d && reason == DiscSelf: 100 dialSelf.Mark(1) 101 case d && reason == DiscUselessPeer: 102 dialUselessPeer.Mark(1) 103 case d && reason == DiscUnexpectedIdentity: 104 dialUnexpectedIdentity.Mark(1) 105 case errors.As(err, &handshakeErr): 106 dialProtoHandshakeError.Mark(1) 107 case errors.Is(err, errEncHandshakeError): 108 dialEncHandshakeError.Mark(1) 109 default: 110 dialOtherError.Mark(1) 111 } 112 } 113 114 // markServeError matches errors that occur while serving an inbound connection 115 // to the corresponding meter. 116 func markServeError(err error) { 117 if !metrics.Enabled() { 118 return 119 } 120 121 var reason DiscReason 122 var handshakeErr *protoHandshakeError 123 d := errors.As(err, &reason) 124 switch { 125 case d && reason == DiscTooManyPeers: 126 serveTooManyPeers.Mark(1) 127 case d && reason == DiscAlreadyConnected: 128 serveAlreadyConnected.Mark(1) 129 case d && reason == DiscSelf: 130 serveSelf.Mark(1) 131 case d && reason == DiscUselessPeer: 132 serveUselessPeer.Mark(1) 133 case d && reason == DiscUnexpectedIdentity: 134 serveUnexpectedIdentity.Mark(1) 135 case errors.As(err, &handshakeErr): 136 serveProtoHandshakeError.Mark(1) 137 case errors.Is(err, errEncHandshakeError): 138 serveEncHandshakeError.Mark(1) 139 default: 140 serveOtherError.Mark(1) 141 } 142 } 143 144 // meteredConn is a wrapper around a net.Conn that meters both the 145 // inbound and outbound network traffic. 146 type meteredConn struct { 147 net.Conn 148 } 149 150 // newMeteredConn creates a new metered connection, bumps the ingress or egress 151 // connection meter and also increases the metered peer count. If the metrics 152 // system is disabled, function returns the original connection. 153 func newMeteredConn(conn net.Conn) net.Conn { 154 if !metrics.Enabled() { 155 return conn 156 } 157 return &meteredConn{Conn: conn} 158 } 159 160 // Read delegates a network read to the underlying connection, bumping the common 161 // and the peer ingress traffic meters along the way. 162 func (c *meteredConn) Read(b []byte) (n int, err error) { 163 n, err = c.Conn.Read(b) 164 ingressTrafficMeter.Mark(int64(n)) 165 return n, err 166 } 167 168 // Write delegates a network write to the underlying connection, bumping the common 169 // and the peer egress traffic meters along the way. 170 func (c *meteredConn) Write(b []byte) (n int, err error) { 171 n, err = c.Conn.Write(b) 172 egressTrafficMeter.Mark(int64(n)) 173 return n, err 174 }