-
Notifications
You must be signed in to change notification settings - Fork 9
/
Copy pathclient.go
137 lines (127 loc) · 4.07 KB
/
client.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
package promhttp
import (
"net/http"
"github.com/prometheus/client_golang/prometheus"
pph "github.com/prometheus/client_golang/prometheus/promhttp"
)
// Client embeds original http Client.
// It allow to creates its copy that will be instrumented for given recipient.
type Client struct {
*http.Client
Registerer prometheus.Registerer
Namespace string
}
// ForRecipient allocates new client based on base one with incomingInstrumentation.
// Given recipient is used as a constant label.
func (c *Client) ForRecipient(recipient string) (*http.Client, error) {
return instrumentClientWithConstLabels(c.Namespace, c.Client, c.Registerer, map[string]string{
"recipient": recipient,
})
}
func instrumentClientWithConstLabels(namespace string, c *http.Client, reg prometheus.Registerer, constLabels map[string]string) (*http.Client, error) {
i := &outgoingInstrumentation{
requests: prometheus.NewCounterVec(
prometheus.CounterOpts{
Namespace: namespace,
Subsystem: subsystemHTTPOutgoing,
Name: "requests_total",
Help: "A counter for outgoing requests from the wrapped client.",
ConstLabels: constLabels,
},
[]string{"code", "method"},
),
duration: prometheus.NewHistogramVec(
prometheus.HistogramOpts{
Namespace: namespace,
Subsystem: subsystemHTTPOutgoing,
Name: "request_duration_histogram_seconds",
Help: "A histogram of outgoing request latencies.",
Buckets: prometheus.DefBuckets,
ConstLabels: constLabels,
},
[]string{"method"},
),
dnsDuration: prometheus.NewHistogramVec(
prometheus.HistogramOpts{
Namespace: namespace,
Subsystem: subsystemHTTPOutgoing,
Name: "dns_duration_histogram_seconds",
Help: "Trace dns latency histogram.",
Buckets: []float64{.005, .01, .025, .05},
ConstLabels: constLabels,
},
[]string{"event"},
),
tlsDuration: prometheus.NewHistogramVec(
prometheus.HistogramOpts{
Namespace: namespace,
Subsystem: subsystemHTTPOutgoing,
Name: "tls_duration_histogram_seconds",
Help: "Trace tls latency histogram.",
Buckets: []float64{.05, .1, .25, .5},
ConstLabels: constLabels,
},
[]string{"event"},
),
inflight: prometheus.NewGauge(prometheus.GaugeOpts{
Namespace: namespace,
Subsystem: subsystemHTTPOutgoing,
Name: "in_flight_requests",
Help: "A gauge of in-flight outgoing requests for the wrapped client.",
ConstLabels: constLabels,
}),
}
trace := &pph.InstrumentTrace{
DNSStart: func(t float64) {
i.dnsDuration.WithLabelValues("dns_start").Observe(t)
},
DNSDone: func(t float64) {
i.dnsDuration.WithLabelValues("dns_done").Observe(t)
},
TLSHandshakeStart: func(t float64) {
i.tlsDuration.WithLabelValues("tls_handshake_start").Observe(t)
},
TLSHandshakeDone: func(t float64) {
i.tlsDuration.WithLabelValues("tls_handshake_done").Observe(t)
},
}
transport := c.Transport
if transport == nil {
transport = http.DefaultTransport
}
return &http.Client{
CheckRedirect: c.CheckRedirect,
Jar: c.Jar,
Timeout: c.Timeout,
Transport: pph.InstrumentRoundTripperInFlight(i.inflight,
pph.InstrumentRoundTripperCounter(i.requests,
pph.InstrumentRoundTripperTrace(trace,
pph.InstrumentRoundTripperDuration(i.duration, transport),
),
),
),
}, reg.Register(i)
}
type outgoingInstrumentation struct {
duration *prometheus.HistogramVec
requests *prometheus.CounterVec
dnsDuration *prometheus.HistogramVec
tlsDuration *prometheus.HistogramVec
inflight prometheus.Gauge
}
// Describe implements prometheus.Collector interface.
func (i *outgoingInstrumentation) Describe(in chan<- *prometheus.Desc) {
i.duration.Describe(in)
i.requests.Describe(in)
i.dnsDuration.Describe(in)
i.tlsDuration.Describe(in)
i.inflight.Describe(in)
}
// Collect implements prometheus.Collector interface.
func (i *outgoingInstrumentation) Collect(in chan<- prometheus.Metric) {
i.duration.Collect(in)
i.requests.Collect(in)
i.dnsDuration.Collect(in)
i.tlsDuration.Collect(in)
i.inflight.Collect(in)
}