github.com/Finschia/ostracon@v1.1.5/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 // Added by Ostracon 46 // Number of abandoned peer messages 47 NumAbandonedPeerMsgs metrics.Counter 48 // Number of pooled peer messages 49 NumPooledPeerMsgs metrics.Gauge 50 } 51 52 // PrometheusMetrics returns Metrics build using Prometheus client library. 53 // Optionally, labels can be provided along with their values ("foo", 54 // "fooValue"). 55 func PrometheusMetrics(namespace string, labelsAndValues ...string) *Metrics { 56 labels := []string{} 57 for i := 0; i < len(labelsAndValues); i += 2 { 58 labels = append(labels, labelsAndValues[i]) 59 } 60 return &Metrics{ 61 Peers: prometheus.NewGaugeFrom(stdprometheus.GaugeOpts{ 62 Namespace: namespace, 63 Subsystem: MetricsSubsystem, 64 Name: "peers", 65 Help: "Number of peers.", 66 }, labels).With(labelsAndValues...), 67 PeerReceiveBytesTotal: prometheus.NewCounterFrom(stdprometheus.CounterOpts{ 68 Namespace: namespace, 69 Subsystem: MetricsSubsystem, 70 Name: "peer_receive_bytes_total", 71 Help: "Number of bytes received from a given peer.", 72 }, append(labels, "peer_id", "chID")).With(labelsAndValues...), 73 PeerSendBytesTotal: prometheus.NewCounterFrom(stdprometheus.CounterOpts{ 74 Namespace: namespace, 75 Subsystem: MetricsSubsystem, 76 Name: "peer_send_bytes_total", 77 Help: "Number of bytes sent to a given peer.", 78 }, append(labels, "peer_id", "chID")).With(labelsAndValues...), 79 PeerPendingSendBytes: prometheus.NewGaugeFrom(stdprometheus.GaugeOpts{ 80 Namespace: namespace, 81 Subsystem: MetricsSubsystem, 82 Name: "peer_pending_send_bytes", 83 Help: "Pending bytes to be sent to a given peer.", 84 }, append(labels, "peer_id")).With(labelsAndValues...), 85 NumTxs: prometheus.NewGaugeFrom(stdprometheus.GaugeOpts{ 86 Namespace: namespace, 87 Subsystem: MetricsSubsystem, 88 Name: "num_txs", 89 Help: "Number of transactions submitted by each peer.", 90 }, append(labels, "peer_id")).With(labelsAndValues...), 91 MessageReceiveBytesTotal: prometheus.NewCounterFrom(stdprometheus.CounterOpts{ 92 Namespace: namespace, 93 Subsystem: MetricsSubsystem, 94 Name: "message_receive_bytes_total", 95 Help: "Number of bytes of each message type received.", 96 }, append(labels, "message_type")).With(labelsAndValues...), 97 MessageSendBytesTotal: prometheus.NewCounterFrom(stdprometheus.CounterOpts{ 98 Namespace: namespace, 99 Subsystem: MetricsSubsystem, 100 Name: "message_send_bytes_total", 101 Help: "Number of bytes of each message type sent.", 102 }, append(labels, "message_type")).With(labelsAndValues...), 103 104 // Added by Ostracon 105 NumAbandonedPeerMsgs: prometheus.NewCounterFrom(stdprometheus.CounterOpts{ 106 Namespace: namespace, 107 Subsystem: MetricsSubsystem, 108 Name: "num_abandoned_peer_msgs", 109 Help: "Number of peer messages abandoned because of full channel", 110 }, append(labels, "peer_id", "chID")).With(labelsAndValues...), 111 NumPooledPeerMsgs: prometheus.NewGaugeFrom(stdprometheus.GaugeOpts{ 112 Namespace: namespace, 113 Subsystem: MetricsSubsystem, 114 Name: "num_pooled_peer_msgs", 115 Help: "Number of peer messages pooled currently", 116 }, append(labels, "peer_id", "chID")).With(labelsAndValues...), 117 } 118 } 119 120 func NopMetrics() *Metrics { 121 return &Metrics{ 122 Peers: discard.NewGauge(), 123 PeerReceiveBytesTotal: discard.NewCounter(), 124 PeerSendBytesTotal: discard.NewCounter(), 125 PeerPendingSendBytes: discard.NewGauge(), 126 NumTxs: discard.NewGauge(), 127 MessageReceiveBytesTotal: discard.NewCounter(), 128 MessageSendBytesTotal: discard.NewCounter(), 129 130 // Added by Ostracon 131 NumAbandonedPeerMsgs: discard.NewCounter(), 132 NumPooledPeerMsgs: discard.NewGauge(), 133 } 134 } 135 136 type metricsLabelCache struct { 137 mtx *sync.RWMutex 138 messageLabelNames map[reflect.Type]string 139 } 140 141 // ValueToMetricLabel is a method that is used to produce a prometheus label value of the golang 142 // type that is passed in. 143 // This method uses a map on the Metrics struct so that each label name only needs 144 // to be produced once to prevent expensive string operations. 145 func (m *metricsLabelCache) ValueToMetricLabel(i interface{}) string { 146 t := reflect.TypeOf(i) 147 m.mtx.RLock() 148 149 if s, ok := m.messageLabelNames[t]; ok { 150 m.mtx.RUnlock() 151 return s 152 } 153 m.mtx.RUnlock() 154 155 s := t.String() 156 ss := valueToLabelRegexp.FindStringSubmatch(s) 157 l := fmt.Sprintf("%s_%s", ss[1], ss[2]) 158 m.mtx.Lock() 159 defer m.mtx.Unlock() 160 m.messageLabelNames[t] = l 161 return l 162 } 163 164 func newMetricsLabelCache() *metricsLabelCache { 165 return &metricsLabelCache{ 166 mtx: &sync.RWMutex{}, 167 messageLabelNames: map[reflect.Type]string{}, 168 } 169 }