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  }