forked from tsenart/vegeta
-
Notifications
You must be signed in to change notification settings - Fork 0
/
prom.go
82 lines (74 loc) · 2.68 KB
/
prom.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
package prom
import (
"fmt"
"net/http"
"strconv"
"time"
"github.com/prometheus/client_golang/prometheus"
"github.com/prometheus/client_golang/prometheus/promhttp"
vegeta "github.com/tsenart/vegeta/v12/lib"
)
// Metrics encapsulates Prometheus metrics of an attack.
type Metrics struct {
requestLatencyHistogram *prometheus.HistogramVec
requestBytesInCounter *prometheus.CounterVec
requestBytesOutCounter *prometheus.CounterVec
requestFailCounter *prometheus.CounterVec
}
// NewMetrics returns a new Metrics instance that must be
// registered in a Prometheus registry with Register.
func NewMetrics() *Metrics {
baseLabels := []string{"method", "url", "status"}
return &Metrics{
requestLatencyHistogram: prometheus.NewHistogramVec(prometheus.HistogramOpts{
Name: "request_seconds",
Help: "Request latency",
Buckets: prometheus.DefBuckets,
}, baseLabels),
requestBytesInCounter: prometheus.NewCounterVec(prometheus.CounterOpts{
Name: "request_bytes_in",
Help: "Bytes received from servers as response to requests",
}, baseLabels),
requestBytesOutCounter: prometheus.NewCounterVec(prometheus.CounterOpts{
Name: "request_bytes_out",
Help: "Bytes sent to servers during requests",
}, baseLabels),
requestFailCounter: prometheus.NewCounterVec(prometheus.CounterOpts{
Name: "request_fail_count",
Help: "Count of failed requests",
}, append(baseLabels[:len(baseLabels):len(baseLabels)], "message")),
}
}
// Register registers all Prometheus metrics in r.
func (pm *Metrics) Register(r prometheus.Registerer) error {
for _, c := range []prometheus.Collector{
pm.requestLatencyHistogram,
pm.requestBytesInCounter,
pm.requestBytesOutCounter,
pm.requestFailCounter,
} {
if err := r.Register(c); err != nil {
return fmt.Errorf("failed to register metric %v: %w", c, err)
}
}
return nil
}
// Observe metrics given a vegeta.Result.
func (pm *Metrics) Observe(res *vegeta.Result) {
code := strconv.FormatUint(uint64(res.Code), 10)
pm.requestBytesInCounter.WithLabelValues(res.Method, res.URL, code).Add(float64(res.BytesIn))
pm.requestBytesOutCounter.WithLabelValues(res.Method, res.URL, code).Add(float64(res.BytesOut))
pm.requestLatencyHistogram.WithLabelValues(res.Method, res.URL, code).Observe(res.Latency.Seconds())
if res.Error != "" {
pm.requestFailCounter.WithLabelValues(res.Method, res.URL, code, res.Error)
}
}
// NewHandler returns a new http.Handler that exposes Prometheus
// metrics registed in r in the OpenMetrics format.
func NewHandler(r *prometheus.Registry, startTime time.Time) http.Handler {
return promhttp.HandlerFor(r, promhttp.HandlerOpts{
Registry: r,
EnableOpenMetrics: true,
ProcessStartTime: startTime,
})
}