forked from slok/go-http-metrics
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathprometheus.go
120 lines (99 loc) · 3.89 KB
/
prometheus.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
package prometheus
import (
"context"
"time"
"github.com/prometheus/client_golang/prometheus"
"github.com/slok/go-http-metrics/metrics"
)
// Config has the dependencies and values of the recorder.
type Config struct {
// Prefix is the prefix that will be set on the metrics, by default it will be empty.
Prefix string
// DurationBuckets are the buckets used by Prometheus for the HTTP request duration metrics,
// by default uses Prometheus default buckets (from 5ms to 10s).
DurationBuckets []float64
// SizeBuckets are the buckets used by Prometheus for the HTTP response size metrics,
// by default uses a exponential buckets from 100B to 1GB.
SizeBuckets []float64
// Registry is the registry that will be used by the recorder to store the metrics,
// if the default registry is not used then it will use the default one.
Registry prometheus.Registerer
// HandlerIDLabel is the name that will be set to the handler ID label, by default is `handler`.
HandlerIDLabel string
// StatusCodeLabel is the name that will be set to the status code label, by default is `code`.
StatusCodeLabel string
// MethodLabel is the name that will be set to the method label, by default is `method`.
MethodLabel string
// ServiceLabel is the name that will be set to the service label, by default is `service`.
ServiceLabel string
}
func (c *Config) defaults() {
if len(c.DurationBuckets) == 0 {
c.DurationBuckets = prometheus.DefBuckets
}
if len(c.SizeBuckets) == 0 {
c.SizeBuckets = prometheus.ExponentialBuckets(100, 10, 8)
}
if c.Registry == nil {
c.Registry = prometheus.DefaultRegisterer
}
if c.HandlerIDLabel == "" {
c.HandlerIDLabel = "handler"
}
if c.StatusCodeLabel == "" {
c.StatusCodeLabel = "code"
}
if c.MethodLabel == "" {
c.MethodLabel = "method"
}
if c.ServiceLabel == "" {
c.ServiceLabel = "service"
}
}
type recorder struct {
httpRequestDurHistogram *prometheus.HistogramVec
httpResponseSizeHistogram *prometheus.HistogramVec
httpRequestsInflight *prometheus.GaugeVec
}
// NewRecorder returns a new metrics recorder that implements the recorder
// using Prometheus as the backend.
func NewRecorder(cfg Config) metrics.Recorder {
cfg.defaults()
r := &recorder{
httpRequestDurHistogram: prometheus.NewHistogramVec(prometheus.HistogramOpts{
Namespace: cfg.Prefix,
Subsystem: "http",
Name: "request_duration_seconds",
Help: "The latency of the HTTP requests.",
Buckets: cfg.DurationBuckets,
}, []string{cfg.ServiceLabel, cfg.HandlerIDLabel, cfg.MethodLabel, cfg.StatusCodeLabel}),
httpResponseSizeHistogram: prometheus.NewHistogramVec(prometheus.HistogramOpts{
Namespace: cfg.Prefix,
Subsystem: "http",
Name: "response_size_bytes",
Help: "The size of the HTTP responses.",
Buckets: cfg.SizeBuckets,
}, []string{cfg.ServiceLabel, cfg.HandlerIDLabel, cfg.MethodLabel, cfg.StatusCodeLabel}),
httpRequestsInflight: prometheus.NewGaugeVec(prometheus.GaugeOpts{
Namespace: cfg.Prefix,
Subsystem: "http",
Name: "requests_inflight",
Help: "The number of inflight requests being handled at the same time.",
}, []string{cfg.ServiceLabel, cfg.HandlerIDLabel}),
}
cfg.Registry.MustRegister(
r.httpRequestDurHistogram,
r.httpResponseSizeHistogram,
r.httpRequestsInflight,
)
return r
}
func (r recorder) ObserveHTTPRequestDuration(_ context.Context, p metrics.HTTPReqProperties, duration time.Duration) {
r.httpRequestDurHistogram.WithLabelValues(p.Service, p.ID, p.Method, p.Code).Observe(duration.Seconds())
}
func (r recorder) ObserveHTTPResponseSize(_ context.Context, p metrics.HTTPReqProperties, sizeBytes int64) {
r.httpResponseSizeHistogram.WithLabelValues(p.Service, p.ID, p.Method, p.Code).Observe(float64(sizeBytes))
}
func (r recorder) AddInflightRequests(_ context.Context, p metrics.HTTPProperties, quantity int) {
r.httpRequestsInflight.WithLabelValues(p.Service, p.ID).Add(float64(quantity))
}