forked from cerc-io/plugeth
p2p, p2p/discover: add dial metrics (#27621)
This PR adds metrics for p2p dialing, which gives us visibility into the quality of the dial candidates returned by our discovery methods.
This commit is contained in:
@@ -17,6 +17,7 @@
|
||||
package discover
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net"
|
||||
|
||||
"github.com/ethereum/go-ethereum/metrics"
|
||||
@@ -32,10 +33,17 @@ const (
|
||||
)
|
||||
|
||||
var (
|
||||
bucketsCounter []metrics.Counter
|
||||
ingressTrafficMeter = metrics.NewRegisteredMeter(ingressMeterName, nil)
|
||||
egressTrafficMeter = metrics.NewRegisteredMeter(egressMeterName, nil)
|
||||
)
|
||||
|
||||
func init() {
|
||||
for i := 0; i < nBuckets; i++ {
|
||||
bucketsCounter = append(bucketsCounter, metrics.NewRegisteredCounter(fmt.Sprintf("%s/bucket/%d/count", moduleName, i), nil))
|
||||
}
|
||||
}
|
||||
|
||||
// meteredConn is a wrapper around a net.UDPConn that meters both the
|
||||
// inbound and outbound network traffic.
|
||||
type meteredUdpConn struct {
|
||||
|
||||
+32
-4
@@ -34,6 +34,7 @@ import (
|
||||
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
"github.com/ethereum/go-ethereum/log"
|
||||
"github.com/ethereum/go-ethereum/metrics"
|
||||
"github.com/ethereum/go-ethereum/p2p/enode"
|
||||
"github.com/ethereum/go-ethereum/p2p/netutil"
|
||||
)
|
||||
@@ -80,7 +81,8 @@ type Table struct {
|
||||
closeReq chan struct{}
|
||||
closed chan struct{}
|
||||
|
||||
nodeAddedHook func(*node) // for testing
|
||||
nodeAddedHook func(*bucket, *node)
|
||||
nodeRemovedHook func(*bucket, *node)
|
||||
}
|
||||
|
||||
// transport is implemented by the UDP transports.
|
||||
@@ -98,6 +100,7 @@ type bucket struct {
|
||||
entries []*node // live entries, sorted by time of last contact
|
||||
replacements []*node // recently seen nodes to be used if revalidation fails
|
||||
ips netutil.DistinctNetSet
|
||||
index int
|
||||
}
|
||||
|
||||
func newTable(t transport, db *enode.DB, cfg Config) (*Table, error) {
|
||||
@@ -119,7 +122,8 @@ func newTable(t transport, db *enode.DB, cfg Config) (*Table, error) {
|
||||
}
|
||||
for i := range tab.buckets {
|
||||
tab.buckets[i] = &bucket{
|
||||
ips: netutil.DistinctNetSet{Subnet: bucketSubnet, Limit: bucketIPLimit},
|
||||
index: i,
|
||||
ips: netutil.DistinctNetSet{Subnet: bucketSubnet, Limit: bucketIPLimit},
|
||||
}
|
||||
}
|
||||
tab.seedRand()
|
||||
@@ -128,6 +132,22 @@ func newTable(t transport, db *enode.DB, cfg Config) (*Table, error) {
|
||||
return tab, nil
|
||||
}
|
||||
|
||||
func newMeteredTable(t transport, db *enode.DB, cfg Config) (*Table, error) {
|
||||
tab, err := newTable(t, db, cfg)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if metrics.Enabled {
|
||||
tab.nodeAddedHook = func(b *bucket, n *node) {
|
||||
bucketsCounter[b.index].Inc(1)
|
||||
}
|
||||
tab.nodeRemovedHook = func(b *bucket, n *node) {
|
||||
bucketsCounter[b.index].Dec(1)
|
||||
}
|
||||
}
|
||||
return tab, nil
|
||||
}
|
||||
|
||||
// Nodes returns all nodes contained in the table.
|
||||
func (tab *Table) Nodes() []*enode.Node {
|
||||
if !tab.isInitDone() {
|
||||
@@ -495,7 +515,7 @@ func (tab *Table) addSeenNode(n *node) {
|
||||
n.addedAt = time.Now()
|
||||
|
||||
if tab.nodeAddedHook != nil {
|
||||
tab.nodeAddedHook(n)
|
||||
tab.nodeAddedHook(b, n)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -539,7 +559,7 @@ func (tab *Table) addVerifiedNode(n *node) {
|
||||
n.addedAt = time.Now()
|
||||
|
||||
if tab.nodeAddedHook != nil {
|
||||
tab.nodeAddedHook(n)
|
||||
tab.nodeAddedHook(b, n)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -638,8 +658,16 @@ func (tab *Table) bumpInBucket(b *bucket, n *node) bool {
|
||||
}
|
||||
|
||||
func (tab *Table) deleteInBucket(b *bucket, n *node) {
|
||||
// Check if the node is actually in the bucket so the removed hook
|
||||
// isn't called multiple times for the same node.
|
||||
if !contains(b.entries, n.ID()) {
|
||||
return
|
||||
}
|
||||
b.entries = deleteNode(b.entries, n)
|
||||
tab.removeIP(b, n.IP())
|
||||
if tab.nodeRemovedHook != nil {
|
||||
tab.nodeRemovedHook(b, n)
|
||||
}
|
||||
}
|
||||
|
||||
func contains(ns []*node, id enode.ID) bool {
|
||||
|
||||
@@ -142,7 +142,7 @@ func ListenV4(c UDPConn, ln *enode.LocalNode, cfg Config) (*UDPv4, error) {
|
||||
log: cfg.Log,
|
||||
}
|
||||
|
||||
tab, err := newTable(t, ln.Database(), cfg)
|
||||
tab, err := newMeteredTable(t, ln.Database(), cfg)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -394,7 +394,7 @@ func TestUDPv4_pingMatchIP(t *testing.T) {
|
||||
func TestUDPv4_successfulPing(t *testing.T) {
|
||||
test := newUDPTest(t)
|
||||
added := make(chan *node, 1)
|
||||
test.table.nodeAddedHook = func(n *node) { added <- n }
|
||||
test.table.nodeAddedHook = func(b *bucket, n *node) { added <- n }
|
||||
defer test.close()
|
||||
|
||||
// The remote side sends a ping packet to initiate the exchange.
|
||||
|
||||
@@ -174,7 +174,7 @@ func newUDPv5(conn UDPConn, ln *enode.LocalNode, cfg Config) (*UDPv5, error) {
|
||||
cancelCloseCtx: cancelCloseCtx,
|
||||
}
|
||||
t.talk = newTalkSystem(t)
|
||||
tab, err := newTable(t, t.db, cfg)
|
||||
tab, err := newMeteredTable(t, t.db, cfg)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user