From 6d7ff6acea32b19b7c23c411748925a24873de9a Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?P=C3=A9ter=20Szil=C3=A1gyi?= <peterke@gmail.com>
Date: Fri, 26 Mar 2021 14:00:06 +0200
Subject: [PATCH] eth/protocols, metrics, p2p: add handler performance metrics

---
 eth/protocols/eth/handler.go  | 10 +++++++++-
 eth/protocols/snap/handler.go | 10 ++++++++++
 metrics/histogram.go          |  9 +++++++++
 p2p/metrics.go                | 11 ++++++++++-
 4 files changed, 38 insertions(+), 2 deletions(-)

diff --git a/eth/protocols/eth/handler.go b/eth/protocols/eth/handler.go
index 64648ed41..de5a38dcc 100644
--- a/eth/protocols/eth/handler.go
+++ b/eth/protocols/eth/handler.go
@@ -24,6 +24,7 @@ import (
 	"github.com/ethereum/go-ethereum/common"
 	"github.com/ethereum/go-ethereum/core"
 	"github.com/ethereum/go-ethereum/core/types"
+	"github.com/ethereum/go-ethereum/metrics"
 	"github.com/ethereum/go-ethereum/p2p"
 	"github.com/ethereum/go-ethereum/p2p/enode"
 	"github.com/ethereum/go-ethereum/p2p/enr"
@@ -241,7 +242,14 @@ func handleMessage(backend Backend, peer *Peer) error {
 	} else if peer.Version() >= ETH66 {
 		handlers = eth66
 	}
-
+	// Track the emount of time it takes to serve the request and run the handler
+	if metrics.Enabled {
+		h := fmt.Sprintf("%s/%s/%d/%#02x", p2p.HandleHistName, ProtocolName, peer.Version(), msg.Code)
+		defer func(start time.Time) {
+			sampler := func() metrics.Sample { return metrics.NewExpDecaySample(1028, 0.015) }
+			metrics.GetOrRegisterHistogramLazy(h, nil, sampler).Update(time.Since(start).Microseconds())
+		}(time.Now())
+	}
 	if handler := handlers[msg.Code]; handler != nil {
 		return handler(backend, msg, peer)
 	}
diff --git a/eth/protocols/snap/handler.go b/eth/protocols/snap/handler.go
index 37e84839a..6622cd871 100644
--- a/eth/protocols/snap/handler.go
+++ b/eth/protocols/snap/handler.go
@@ -19,12 +19,14 @@ package snap
 import (
 	"bytes"
 	"fmt"
+	"time"
 
 	"github.com/ethereum/go-ethereum/common"
 	"github.com/ethereum/go-ethereum/core"
 	"github.com/ethereum/go-ethereum/core/state"
 	"github.com/ethereum/go-ethereum/light"
 	"github.com/ethereum/go-ethereum/log"
+	"github.com/ethereum/go-ethereum/metrics"
 	"github.com/ethereum/go-ethereum/p2p"
 	"github.com/ethereum/go-ethereum/p2p/enode"
 	"github.com/ethereum/go-ethereum/p2p/enr"
@@ -128,6 +130,14 @@ func handleMessage(backend Backend, peer *Peer) error {
 	}
 	defer msg.Discard()
 
+	// Track the emount of time it takes to serve the request and run the handler
+	if metrics.Enabled {
+		h := fmt.Sprintf("%s/%s/%d/%#02x", p2p.HandleHistName, ProtocolName, peer.Version(), msg.Code)
+		defer func(start time.Time) {
+			sampler := func() metrics.Sample { return metrics.NewExpDecaySample(1028, 0.015) }
+			metrics.GetOrRegisterHistogramLazy(h, nil, sampler).Update(time.Since(start).Microseconds())
+		}(time.Now())
+	}
 	// Handle the message depending on its contents
 	switch {
 	case msg.Code == GetAccountRangeMsg:
diff --git a/metrics/histogram.go b/metrics/histogram.go
index 46f3bbd2f..2c54ce8b4 100644
--- a/metrics/histogram.go
+++ b/metrics/histogram.go
@@ -26,6 +26,15 @@ func GetOrRegisterHistogram(name string, r Registry, s Sample) Histogram {
 	return r.GetOrRegister(name, func() Histogram { return NewHistogram(s) }).(Histogram)
 }
 
+// GetOrRegisterHistogramLazy returns an existing Histogram or constructs and
+// registers a new StandardHistogram.
+func GetOrRegisterHistogramLazy(name string, r Registry, s func() Sample) Histogram {
+	if nil == r {
+		r = DefaultRegistry
+	}
+	return r.GetOrRegister(name, func() Histogram { return NewHistogram(s()) }).(Histogram)
+}
+
 // NewHistogram constructs a new StandardHistogram from a Sample.
 func NewHistogram(s Sample) Histogram {
 	if !Enabled {
diff --git a/p2p/metrics.go b/p2p/metrics.go
index 44946473f..be0d2f495 100644
--- a/p2p/metrics.go
+++ b/p2p/metrics.go
@@ -25,8 +25,17 @@ import (
 )
 
 const (
+	// ingressMeterName is the prefix of the per-packet inbound metrics.
 	ingressMeterName = "p2p/ingress"
-	egressMeterName  = "p2p/egress"
+
+	// egressMeterName is the prefix of the per-packet outbound metrics.
+	egressMeterName = "p2p/egress"
+
+	// HandleHistName is the prefix of the per-packet serving time histograms.
+	HandleHistName = "p2p/handle"
+
+	// WaitHistName is the prefix of the per-packet (req only) waiting time histograms.
+	WaitHistName = "p2p/wait"
 )
 
 var (
-- 
GitLab