-
Notifications
You must be signed in to change notification settings - Fork 12
/
metrics.go
141 lines (121 loc) · 4.14 KB
/
metrics.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
package main
import (
"net/http"
"github.com/prometheus/client_golang/prometheus"
"github.com/prometheus/client_golang/prometheus/promhttp"
)
func registerVersionMetric(version string) {
m := prometheus.NewGauge(prometheus.GaugeOpts{
Namespace: "ipfs",
Subsystem: "rainbow",
Name: "info",
Help: "Information about rainbow instance.",
ConstLabels: prometheus.Labels{"version": version},
})
prometheus.MustRegister(m)
m.Set(1)
}
// Duration histograms use fixed definition here, as we don't want to break existing buckets if we need to add more.
var defaultDurationHistogramBuckets = []float64{0.05, 0.1, 0.25, 0.5, 1, 2, 5, 10, 30, 60, 120, 240, 480, 960, 1920}
// withHTTPMetrics collects metrics around HTTP request/response count, duration, and size
// per specific handler. Allows us to track them separately for /ipns and /ipfs.
func withHTTPMetrics(handler http.Handler, handlerName string, disableMetrics bool) http.Handler {
if disableMetrics {
return handler
}
opts := prometheus.HistogramOpts{
Namespace: "ipfs",
Subsystem: "http",
Buckets: defaultDurationHistogramBuckets,
ConstLabels: prometheus.Labels{"handler": handlerName},
}
labels := []string{"method", "code"}
reqWip := prometheus.NewGauge(
prometheus.GaugeOpts{
Namespace: opts.Namespace,
Subsystem: opts.Subsystem,
Name: "requests_inflight",
Help: "Tracks the number of HTTP client requests currently in progress.",
ConstLabels: opts.ConstLabels,
},
)
prometheus.MustRegister(reqWip)
reqCnt := prometheus.NewCounterVec(
prometheus.CounterOpts{
Namespace: opts.Namespace,
Subsystem: opts.Subsystem,
Name: "requests_total",
Help: "Total number of HTTP requests made.",
ConstLabels: opts.ConstLabels,
},
labels,
)
prometheus.MustRegister(reqCnt)
opts.Name = "request_duration_seconds"
opts.Help = "The HTTP request latencies in seconds. "
reqDurHist := prometheus.NewHistogramVec(opts, labels)
prometheus.MustRegister(reqDurHist)
opts.Name = "request_size_bytes"
opts.Help = "The HTTP request sizes in bytes."
reqSzHist := prometheus.NewHistogramVec(opts, labels)
prometheus.MustRegister(reqSzHist)
opts.Name = "response_size_bytes"
opts.Help = "The HTTP response sizes in bytes."
resSzHist := prometheus.NewHistogramVec(opts, labels)
prometheus.MustRegister(resSzHist)
handler = promhttp.InstrumentHandlerInFlight(reqWip, handler)
handler = promhttp.InstrumentHandlerCounter(reqCnt, handler)
handler = promhttp.InstrumentHandlerDuration(reqDurHist, handler)
handler = promhttp.InstrumentHandlerRequestSize(reqSzHist, handler)
handler = promhttp.InstrumentHandlerResponseSize(resSzHist, handler)
return handler
}
var peersTotalMetric = prometheus.NewDesc(
prometheus.BuildFQName("ipfs", "p2p", "peers_total"),
"Number of connected peers",
[]string{"transport"},
nil,
)
// IpfsNodeCollector collects peer metrics
type IpfsNodeCollector struct {
Node *Node
}
func (IpfsNodeCollector) Describe(ch chan<- *prometheus.Desc) {
ch <- peersTotalMetric
}
func (c IpfsNodeCollector) Collect(ch chan<- prometheus.Metric) {
for tr, val := range c.PeersTotalValues() {
ch <- prometheus.MustNewConstMetric(
peersTotalMetric,
prometheus.GaugeValue,
val,
tr,
)
}
}
func (c IpfsNodeCollector) PeersTotalValues() map[string]float64 {
vals := make(map[string]float64)
if c.Node.host == nil {
return vals
}
for _, peerID := range c.Node.host.Network().Peers() {
// Each peer may have more than one connection (see for an explanation
// https://github.com/libp2p/go-libp2p-swarm/commit/0538806), so we grab
// only one, the first (an arbitrary and non-deterministic choice), which
// according to ConnsToPeer is the oldest connection in the list
// (https://github.com/libp2p/go-libp2p-swarm/blob/v0.2.6/swarm.go#L362-L364).
conns := c.Node.host.Network().ConnsToPeer(peerID)
if len(conns) == 0 {
continue
}
tr := ""
for _, proto := range conns[0].RemoteMultiaddr().Protocols() {
tr = tr + "/" + proto.Name
}
vals[tr] = vals[tr] + 1
}
return vals
}
func registerIpfsNodeCollector(nd *Node) {
prometheus.MustRegister(&IpfsNodeCollector{Node: nd})
}