-
Notifications
You must be signed in to change notification settings - Fork 286
/
prometheus.md
297 lines (236 loc) · 8.34 KB
/
prometheus.md
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
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
---
description: Prometheus metrics middleware
---
# Prometheus
:::note
Echo community contribution
:::
Prometheus middleware generates metrics for HTTP requests.
There are 2 versions of Prometheus middleware:
- latest (recommended) https://github.com/labstack/echo-contrib/blob/master/echoprometheus.go
- old (deprecated) https://github.com/labstack/echo-contrib/blob/master/prometheus/prometheus.go)
Migration guide from old to newer middleware can found [here](https://github.com/labstack/echo-contrib/blob/master/echoprometheus/README.md).
## Usage
- Add needed module `go get -u github.com/labstack/echo-contrib`
- Add Prometheus middleware and metrics serving route
```go
e := echo.New()
e.Use(echoprometheus.NewMiddleware("myapp")) // adds middleware to gather metrics
e.GET("/metrics", echoprometheus.NewHandler()) // adds route to serve gathered metrics
```
## Examples
Serve metric from the same server as where metrics is gathered
```go
package main
import (
"errors"
"github.com/labstack/echo-contrib/echoprometheus"
"github.com/labstack/echo/v4"
"log"
"net/http"
)
func main() {
e := echo.New()
e.Use(echoprometheus.NewMiddleware("myapp")) // adds middleware to gather metrics
e.GET("/metrics", echoprometheus.NewHandler()) // adds route to serve gathered metrics
e.GET("/hello", func(c echo.Context) error {
return c.String(http.StatusOK, "hello")
})
if err := e.Start(":8080"); err != nil && !errors.Is(err, http.ErrServerClosed) {
log.Fatal(err)
}
}
```
Serve metrics on a separate port
```go
func main() {
app := echo.New() // this Echo instance will serve route on port 8080
app.Use(echoprometheus.NewMiddleware("myapp")) // adds middleware to gather metrics
go func() {
metrics := echo.New() // this Echo will run on separate port 8081
metrics.GET("/metrics", echoprometheus.NewHandler()) // adds route to serve gathered metrics
if err := metrics.Start(":8081"); err != nil && !errors.Is(err, http.ErrServerClosed) {
log.Fatal(err)
}
}()
app.GET("/hello", func(c echo.Context) error {
return c.String(http.StatusOK, "hello")
})
if err := app.Start(":8080"); err != nil && !errors.Is(err, http.ErrServerClosed) {
log.Fatal(err)
}
}
```
*Sample output (for first example)*
```bash
curl http://localhost:8080/metrics
# HELP echo_request_duration_seconds The HTTP request latencies in seconds.
# TYPE echo_request_duration_seconds summary
echo_request_duration_seconds_sum 0.41086482
echo_request_duration_seconds_count 1
# HELP echo_request_size_bytes The HTTP request sizes in bytes.
# TYPE echo_request_size_bytes summary
echo_request_size_bytes_sum 56
echo_request_size_bytes_count 1
# HELP echo_requests_total How many HTTP requests processed, partitioned by status code and HTTP method.
# TYPE echo_requests_total counter
echo_requests_total{code="200",host="localhost:8080",method="GET",url="/"} 1
# HELP echo_response_size_bytes The HTTP response sizes in bytes.
# TYPE echo_response_size_bytes summary
echo_response_size_bytes_sum 61
echo_response_size_bytes_count 1
...
```
## Custom Configuration
### Serving custom Prometheus Metrics
*Usage*
Using custom metrics with Prometheus default registry:
```go
package main
import (
"errors"
"github.com/labstack/echo-contrib/echoprometheus"
"github.com/labstack/echo/v4"
"github.com/prometheus/client_golang/prometheus"
"log"
"net/http"
)
func main() {
e := echo.New()
customCounter := prometheus.NewCounter( // create new counter metric. This is replacement for `prometheus.Metric` struct
prometheus.CounterOpts{
Name: "custom_requests_total",
Help: "How many HTTP requests processed, partitioned by status code and HTTP method.",
},
)
if err := prometheus.Register(customCounter); err != nil { // register your new counter metric with default metrics registry
log.Fatal(err)
}
e.Use(echoprometheus.NewMiddlewareWithConfig(echoprometheus.MiddlewareConfig{
AfterNext: func(c echo.Context, err error) {
customCounter.Inc() // use our custom metric in middleware. after every request increment the counter
},
}))
e.GET("/metrics", echoprometheus.NewHandler()) // register route for getting gathered metrics
if err := e.Start(":8080"); err != nil && !errors.Is(err, http.ErrServerClosed) {
log.Fatal(err)
}
}
```
or create your own registry and register custom metrics with that:
```go
package main
import (
"errors"
"github.com/labstack/echo-contrib/echoprometheus"
"github.com/labstack/echo/v4"
"github.com/prometheus/client_golang/prometheus"
"log"
"net/http"
)
func main() {
e := echo.New()
customRegistry := prometheus.NewRegistry() // create custom registry for your custom metrics
customCounter := prometheus.NewCounter( // create new counter metric. This is replacement for `prometheus.Metric` struct
prometheus.CounterOpts{
Name: "custom_requests_total",
Help: "How many HTTP requests processed, partitioned by status code and HTTP method.",
},
)
if err := customRegistry.Register(customCounter); err != nil { // register your new counter metric with metrics registry
log.Fatal(err)
}
e.Use(echoprometheus.NewMiddlewareWithConfig(echoprometheus.MiddlewareConfig{
AfterNext: func(c echo.Context, err error) {
customCounter.Inc() // use our custom metric in middleware. after every request increment the counter
},
Registerer: customRegistry, // use our custom registry instead of default Prometheus registry
}))
e.GET("/metrics", echoprometheus.NewHandlerWithConfig(echoprometheus.HandlerConfig{Gatherer: customRegistry})) // register route for getting gathered metrics data from our custom Registry
if err := e.Start(":8080"); err != nil && !errors.Is(err, http.ErrServerClosed) {
log.Fatal(err)
}
}
```
### Skipping URL(s)
*Usage*
A middleware skipper can be passed to avoid generating metrics to certain URL(s)
```go
package main
import (
"errors"
"github.com/labstack/echo-contrib/echoprometheus"
"github.com/labstack/echo/v4"
"log"
"net/http"
"strings"
)
func main() {
e := echo.New()
mwConfig := echoprometheus.MiddlewareConfig{
Skipper: func(c echo.Context) bool {
return strings.HasPrefix(c.Path(), "/testurl")
}, // does not gather metrics metrics on routes starting with `/testurl`
}
e.Use(echoprometheus.NewMiddlewareWithConfig(mwConfig)) // adds middleware to gather metrics
e.GET("/metrics", echoprometheus.NewHandler()) // adds route to serve gathered metrics
e.GET("/", func(c echo.Context) error {
return c.String(http.StatusOK, "Hello, World!")
})
if err := e.Start(":8080"); err != nil && !errors.Is(err, http.ErrServerClosed) {
log.Fatal(err)
}
}
```
## Complex Scenarios
Example: modify default `echoprometheus` metrics definitions
```go
package main
import (
"errors"
"github.com/labstack/echo-contrib/echoprometheus"
"github.com/labstack/echo/v4"
"github.com/prometheus/client_golang/prometheus"
"log"
"net/http"
)
func main() {
e := echo.New()
e.Use(echoprometheus.NewMiddlewareWithConfig(echoprometheus.MiddlewareConfig{
// labels of default metrics can be modified or added with `LabelFuncs` function
LabelFuncs: map[string]echoprometheus.LabelValueFunc{
"scheme": func(c echo.Context, err error) string { // additional custom label
return c.Scheme()
},
"host": func(c echo.Context, err error) string { // overrides default 'host' label value
return "y_" + c.Request().Host
},
},
// The `echoprometheus` middleware registers the following metrics by default:
// - Histogram: request_duration_seconds
// - Histogram: response_size_bytes
// - Histogram: request_size_bytes
// - Counter: requests_total
// which can be modified with `HistogramOptsFunc` and `CounterOptsFunc` functions
HistogramOptsFunc: func(opts prometheus.HistogramOpts) prometheus.HistogramOpts {
if opts.Name == "request_duration_seconds" {
opts.Buckets = []float64{1000.0, 10_000.0, 100_000.0, 1_000_000.0} // 1KB ,10KB, 100KB, 1MB
}
return opts
},
CounterOptsFunc: func(opts prometheus.CounterOpts) prometheus.CounterOpts {
if opts.Name == "requests_total" {
opts.ConstLabels = prometheus.Labels{"my_const": "123"}
}
return opts
},
})) // adds middleware to gather metrics
e.GET("/metrics", echoprometheus.NewHandler()) // adds route to serve gathered metrics
e.GET("/hello", func(c echo.Context) error {
return c.String(http.StatusOK, "hello")
})
if err := e.Start(":8080"); err != nil && !errors.Is(err, http.ErrServerClosed) {
log.Fatal(err)
}
}
```