github.com/pure-x-eth/consensus_tm@v0.0.0-20230502163723-e3c2ff987250/p2p/metrics.go (about) 1 package p2p 2 3 import ( 4 "fmt" 5 "reflect" 6 "regexp" 7 "sync" 8 9 "github.com/go-kit/kit/metrics" 10 "github.com/go-kit/kit/metrics/discard" 11 "github.com/go-kit/kit/metrics/prometheus" 12 stdprometheus "github.com/prometheus/client_golang/prometheus" 13 ) 14 15 const ( 16 // MetricsSubsystem is a subsystem shared by all metrics exposed by this 17 // package. 18 MetricsSubsystem = "p2p" 19 ) 20 21 var ( 22 // valueToLabelRegexp is used to find the golang package name and type name 23 // so that the name can be turned into a prometheus label where the characters 24 // in the label do not include prometheus special characters such as '*' and '.'. 25 valueToLabelRegexp = regexp.MustCompile(`\*?(\w+)\.(.*)`) 26 ) 27 28 // Metrics contains metrics exposed by this package. 29 type Metrics struct { 30 // Number of peers. 31 Peers metrics.Gauge 32 // Number of bytes received from a given peer. 33 PeerReceiveBytesTotal metrics.Counter 34 // Number of bytes sent to a given peer. 35 PeerSendBytesTotal metrics.Counter 36 // Pending bytes to be sent to a given peer. 37 PeerPendingSendBytes metrics.Gauge 38 // Number of transactions submitted by each peer. 39 NumTxs metrics.Gauge 40 // Number of bytes of each message type received. 41 MessageReceiveBytesTotal metrics.Counter 42 // Number of bytes of each message type sent. 43 MessageSendBytesTotal metrics.Counter 44 } 45 46 // PrometheusMetrics returns Metrics build using Prometheus client library. 47 // Optionally, labels can be provided along with their values ("foo", 48 // "fooValue"). 49 func PrometheusMetrics(namespace string, labelsAndValues ...string) *Metrics { 50 labels := []string{} 51 for i := 0; i < len(labelsAndValues); i += 2 { 52 labels = append(labels, labelsAndValues[i]) 53 } 54 return &Metrics{ 55 Peers: prometheus.NewGaugeFrom(stdprometheus.GaugeOpts{ 56 Namespace: namespace, 57 Subsystem: MetricsSubsystem, 58 Name: "peers", 59 Help: "Number of peers.", 60 }, labels).With(labelsAndValues...), 61 PeerReceiveBytesTotal: prometheus.NewCounterFrom(stdprometheus.CounterOpts{ 62 Namespace: namespace, 63 Subsystem: MetricsSubsystem, 64 Name: "peer_receive_bytes_total", 65 Help: "Number of bytes received from a given peer.", 66 }, append(labels, "peer_id", "chID")).With(labelsAndValues...), 67 PeerSendBytesTotal: prometheus.NewCounterFrom(stdprometheus.CounterOpts{ 68 Namespace: namespace, 69 Subsystem: MetricsSubsystem, 70 Name: "peer_send_bytes_total", 71 Help: "Number of bytes sent to a given peer.", 72 }, append(labels, "peer_id", "chID")).With(labelsAndValues...), 73 PeerPendingSendBytes: prometheus.NewGaugeFrom(stdprometheus.GaugeOpts{ 74 Namespace: namespace, 75 Subsystem: MetricsSubsystem, 76 Name: "peer_pending_send_bytes", 77 Help: "Pending bytes to be sent to a given peer.", 78 }, append(labels, "peer_id")).With(labelsAndValues...), 79 NumTxs: prometheus.NewGaugeFrom(stdprometheus.GaugeOpts{ 80 Namespace: namespace, 81 Subsystem: MetricsSubsystem, 82 Name: "num_txs", 83 Help: "Number of transactions submitted by each peer.", 84 }, append(labels, "peer_id")).With(labelsAndValues...), 85 MessageReceiveBytesTotal: prometheus.NewCounterFrom(stdprometheus.CounterOpts{ 86 Namespace: namespace, 87 Subsystem: MetricsSubsystem, 88 Name: "message_receive_bytes_total", 89 Help: "Number of bytes of each message type received.", 90 }, append(labels, "message_type")).With(labelsAndValues...), 91 MessageSendBytesTotal: prometheus.NewCounterFrom(stdprometheus.CounterOpts{ 92 Namespace: namespace, 93 Subsystem: MetricsSubsystem, 94 Name: "message_send_bytes_total", 95 Help: "Number of bytes of each message type sent.", 96 }, append(labels, "message_type")).With(labelsAndValues...), 97 } 98 } 99 100 func NopMetrics() *Metrics { 101 return &Metrics{ 102 Peers: discard.NewGauge(), 103 PeerReceiveBytesTotal: discard.NewCounter(), 104 PeerSendBytesTotal: discard.NewCounter(), 105 PeerPendingSendBytes: discard.NewGauge(), 106 NumTxs: discard.NewGauge(), 107 MessageReceiveBytesTotal: discard.NewCounter(), 108 MessageSendBytesTotal: discard.NewCounter(), 109 } 110 } 111 112 type metricsLabelCache struct { 113 mtx *sync.RWMutex 114 messageLabelNames map[reflect.Type]string 115 } 116 117 // ValueToMetricLabel is a method that is used to produce a prometheus label value of the golang 118 // type that is passed in. 119 // This method uses a map on the Metrics struct so that each label name only needs 120 // to be produced once to prevent expensive string operations. 121 func (m *metricsLabelCache) ValueToMetricLabel(i interface{}) string { 122 t := reflect.TypeOf(i) 123 m.mtx.RLock() 124 125 if s, ok := m.messageLabelNames[t]; ok { 126 m.mtx.RUnlock() 127 return s 128 } 129 m.mtx.RUnlock() 130 131 s := t.String() 132 ss := valueToLabelRegexp.FindStringSubmatch(s) 133 l := fmt.Sprintf("%s_%s", ss[1], ss[2]) 134 m.mtx.Lock() 135 defer m.mtx.Unlock() 136 m.messageLabelNames[t] = l 137 return l 138 } 139 140 func newMetricsLabelCache() *metricsLabelCache { 141 return &metricsLabelCache{ 142 mtx: &sync.RWMutex{}, 143 messageLabelNames: map[reflect.Type]string{}, 144 } 145 }