github.com/annchain/OG@v0.0.9/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 "net" 23 "sync" 24 "sync/atomic" 25 "time" 26 27 "github.com/annchain/OG/metrics" 28 "github.com/annchain/OG/p2p/onode" 29 ) 30 31 const ( 32 MetricsInboundConnects = "p2p/InboundConnects" // Name for the registered inbound connects meter 33 MetricsInboundTraffic = "p2p/InboundTraffic" // Name for the registered inbound traffic meter 34 MetricsOutboundConnects = "p2p/OutboundConnects" // Name for the registered outbound connects meter 35 MetricsOutboundTraffic = "p2p/OutboundTraffic" // Name for the registered outbound traffic meter 36 37 MeteredPeerLimit = 1024 // This amount of peers are individually metered 38 ) 39 40 var ( 41 ingressConnectMeter = metrics.NewRegisteredMeter(MetricsInboundConnects, nil) // Meter counting the ingress connections 42 ingressTrafficMeter = metrics.NewRegisteredMeter(MetricsInboundTraffic, nil) // Meter metering the cumulative ingress traffic 43 egressConnectMeter = metrics.NewRegisteredMeter(MetricsOutboundConnects, nil) // Meter counting the egress connections 44 egressTrafficMeter = metrics.NewRegisteredMeter(MetricsOutboundTraffic, nil) // Meter metering the cumulative egress traffic 45 46 //PeerIngressRegistry = metrics.NewPrefixedChildRegistry(metrics.EphemeralRegistry, MetricsInboundTraffic+"/") // Registry containing the peer ingress 47 //PeerEgressRegistry = metrics.NewPrefixedChildRegistry(metrics.EphemeralRegistry, MetricsOutboundTraffic+"/") // Registry containing the peer egress 48 49 //meteredPeerFeed event.Feed // Event feed for peer metrics 50 meteredPeerCount int32 // Actually stored peer connection count 51 ) 52 53 // MeteredPeerEventType is the type of peer events emitted by a metered connection. 54 type MeteredPeerEventType int 55 56 const ( 57 // PeerConnected is the type of event emitted when a peer successfully 58 // made the handshake. 59 PeerConnected MeteredPeerEventType = iota 60 61 // PeerDisconnected is the type of event emitted when a peer disconnects. 62 PeerDisconnected 63 64 // PeerHandshakeFailed is the type of event emitted when a peer fails to 65 // make the handshake or disconnects before the handshake. 66 PeerHandshakeFailed 67 ) 68 69 // MeteredPeerEvent is an event emitted when peers connect or disconnect. 70 type MeteredPeerEvent struct { 71 Type MeteredPeerEventType // Type of peer event 72 IP net.IP // IP address of the peer 73 ID onode.ID // NodeID of the peer 74 Elapsed time.Duration // Time elapsed between the connection and the handshake/disconnection 75 Ingress uint64 // Ingress count at the moment of the event 76 Egress uint64 // Egress count at the moment of the event 77 } 78 79 // SubscribeMeteredPeerEvent registers a subscription for peer life-cycle events 80 // if metrics collection is enabled. 81 /* 82 func SubscribeMeteredPeerEvent(ch chan<- MeteredPeerEvent) event.Subscription { 83 return meteredPeerFeed.Subscribe(ch) 84 } 85 86 */ 87 88 // meteredConn is a wrapper around a net.Conn that meters both the 89 // inbound and outbound network traffic. 90 type meteredConn struct { 91 net.Conn // Network connection to wrap with metering 92 93 connected time.Time // Connection time of the peer 94 ip net.IP // IP address of the peer 95 id onode.ID // NodeID of the peer 96 97 // trafficMetered denotes if the peer is registered in the traffic registries. 98 // Its value is true if the metered peer count doesn't reach the limit in the 99 // moment of the peer's connection. 100 trafficMetered bool 101 ingressMeter metrics.Meter // Meter for the read bytes of the peer 102 egressMeter metrics.Meter // Meter for the written bytes of the peer 103 104 lock sync.RWMutex // Lock protecting the metered connection's internals 105 } 106 107 // newMeteredConn creates a new metered connection, bumps the ingress or egress 108 // connection meter and also increases the metered peer count. If the metrics 109 // system is disabled or the IP address is unspecified, this function returns 110 // the original object. 111 func newMeteredConn(conn net.Conn, ingress bool, ip net.IP) net.Conn { 112 // Short circuit if metrics are disabled 113 if !metrics.Enabled { 114 return conn 115 } 116 if ip.IsUnspecified() { 117 log.Warn("Sender IP is unspecified") 118 return conn 119 } 120 // Bump the connection counters and wrap the connection 121 if ingress { 122 ingressConnectMeter.Mark(1) 123 } else { 124 egressConnectMeter.Mark(1) 125 } 126 return &meteredConn{ 127 Conn: conn, 128 ip: ip, 129 connected: time.Now(), 130 } 131 } 132 133 // Read delegates a network read to the underlying connection, bumping the common 134 // and the peer ingress traffic meters along the way. 135 func (c *meteredConn) Read(b []byte) (n int, err error) { 136 n, err = c.Conn.Read(b) 137 ingressTrafficMeter.Mark(int64(n)) 138 c.lock.RLock() 139 if c.trafficMetered { 140 c.ingressMeter.Mark(int64(n)) 141 } 142 c.lock.RUnlock() 143 return n, err 144 } 145 146 // Write delegates a network write to the underlying connection, bumping the common 147 // and the peer egress traffic meters along the way. 148 func (c *meteredConn) Write(b []byte) (n int, err error) { 149 n, err = c.Conn.Write(b) 150 egressTrafficMeter.Mark(int64(n)) 151 c.lock.RLock() 152 if c.trafficMetered { 153 c.egressMeter.Mark(int64(n)) 154 } 155 c.lock.RUnlock() 156 return n, err 157 } 158 159 // handshakeDone is called when a peer handshake is done. Registers the peer to 160 // the ingress and the egress traffic registries using the peer's IP and node ID, 161 // also emits connect event. 162 func (c *meteredConn) handshakeDone(id onode.ID) { 163 if atomic.AddInt32(&meteredPeerCount, 1) >= MeteredPeerLimit { 164 // Don't register the peer in the traffic registries. 165 atomic.AddInt32(&meteredPeerCount, -1) 166 c.lock.Lock() 167 c.id, c.trafficMetered = id, false 168 c.lock.Unlock() 169 log.Warn("Metered peer count reached the limit") 170 } else { 171 //key := fmt.Sprintf("%s/%s", c.ip, id.String()) 172 c.lock.Lock() 173 c.id, c.trafficMetered = id, true 174 //c.ingressMeter = metrics.NewRegisteredMeter(key, PeerIngressRegistry) 175 //c.egressMeter = metrics.NewRegisteredMeter(key, PeerEgressRegistry) 176 c.lock.Unlock() 177 } 178 //meteredPeerFeed.Send(MeteredPeerEvent{ 179 // Type: PeerConnected, 180 //IP: c.ip, 181 //ID: id, 182 //Elapsed: time.Since(c.connected), 183 //}) 184 } 185 186 // Close delegates a close operation to the underlying connection, unregisters 187 // the peer from the traffic registries and emits close event. 188 func (c *meteredConn) Close() error { 189 err := c.Conn.Close() 190 c.lock.RLock() 191 if c.id == (onode.ID{}) { 192 // If the peer disconnects before the handshake. 193 c.lock.RUnlock() 194 //meteredPeerFeed.Send(MeteredPeerEvent{ 195 // Type: PeerHandshakeFailed, 196 // IP: c.ip, 197 // Elapsed: time.Since(c.connected), 198 //}) 199 return err 200 } 201 //id := c.id 202 if !c.trafficMetered { 203 // If the peer isn't registered in the traffic registries. 204 c.lock.RUnlock() 205 //meteredPeerFeed.Send(MeteredPeerEvent{ 206 // Type: PeerDisconnected, 207 //// IP: c.ip, 208 // ID: id, 209 //}) 210 return err 211 } 212 //ingress, egress := uint64(c.ingressMeter.Count()), uint64(c.egressMeter.Count()) 213 c.lock.RUnlock() 214 215 // Decrement the metered peer count 216 atomic.AddInt32(&meteredPeerCount, -1) 217 218 // Unregister the peer from the traffic registries 219 //key := fmt.Sprintf("%s/%s", c.ip, id) 220 //PeerIngressRegistry.Unregister(key) 221 //PeerEgressRegistry.Unregister(key) 222 223 //meteredPeerFeed.Send(MeteredPeerEvent{ 224 //Type: PeerDisconnected, 225 //IP: c.ip, 226 //ID: id, 227 //Ingress: ingress, 228 //Egress: egress, 229 //}) 230 return err 231 }