@@ -84,10 +84,32 @@ func Handler() http.Handler {
84
84
// instrumentation. Use the InstrumentMetricHandler function to apply the same
85
85
// kind of instrumentation as it is used by the Handler function.
86
86
func HandlerFor (reg prometheus.Gatherer , opts HandlerOpts ) http.Handler {
87
- var inFlightSem chan struct {}
87
+ var (
88
+ inFlightSem chan struct {}
89
+ errCnt = prometheus .NewCounterVec (
90
+ prometheus.CounterOpts {
91
+ Name : "promhttp_metric_handler_errors_total" ,
92
+ Help : "Total number of internal errors encountered by the promhttp metric handler." ,
93
+ },
94
+ []string {"cause" },
95
+ )
96
+ )
97
+
88
98
if opts .MaxRequestsInFlight > 0 {
89
99
inFlightSem = make (chan struct {}, opts .MaxRequestsInFlight )
90
100
}
101
+ if opts .Registry != nil {
102
+ // Initialize all possibilites that can occur below.
103
+ errCnt .WithLabelValues ("gathering" )
104
+ errCnt .WithLabelValues ("encoding" )
105
+ if err := opts .Registry .Register (errCnt ); err != nil {
106
+ if are , ok := err .(prometheus.AlreadyRegisteredError ); ok {
107
+ errCnt = are .ExistingCollector .(* prometheus.CounterVec )
108
+ } else {
109
+ panic (err )
110
+ }
111
+ }
112
+ }
91
113
92
114
h := http .HandlerFunc (func (rsp http.ResponseWriter , req * http.Request ) {
93
115
if inFlightSem != nil {
@@ -106,6 +128,7 @@ func HandlerFor(reg prometheus.Gatherer, opts HandlerOpts) http.Handler {
106
128
if opts .ErrorLog != nil {
107
129
opts .ErrorLog .Println ("error gathering metrics:" , err )
108
130
}
131
+ errCnt .WithLabelValues ("gathering" ).Inc ()
109
132
switch opts .ErrorHandling {
110
133
case PanicOnError :
111
134
panic (err )
@@ -146,6 +169,7 @@ func HandlerFor(reg prometheus.Gatherer, opts HandlerOpts) http.Handler {
146
169
if opts .ErrorLog != nil {
147
170
opts .ErrorLog .Println ("error encoding and sending metric family:" , err )
148
171
}
172
+ errCnt .WithLabelValues ("encoding" ).Inc ()
149
173
switch opts .ErrorHandling {
150
174
case PanicOnError :
151
175
panic (err )
@@ -236,9 +260,12 @@ const (
236
260
// Ignore errors and try to serve as many metrics as possible. However,
237
261
// if no metrics can be served, serve an HTTP status code 500 and the
238
262
// last error message in the body. Only use this in deliberate "best
239
- // effort" metrics collection scenarios. It is recommended to at least
240
- // log errors (by providing an ErrorLog in HandlerOpts) to not mask
241
- // errors completely.
263
+ // effort" metrics collection scenarios. In this case, it is highly
264
+ // recommended to provide other means of detecting errors: By setting an
265
+ // ErrorLog in HandlerOpts, the errors are logged. By providing a
266
+ // Registry in HandlerOpts, the exposed metrics include an error counter
267
+ // "promhttp_metric_handler_errors_total", which can be used for
268
+ // alerts.
242
269
ContinueOnError
243
270
// Panic upon the first error encountered (useful for "crash only" apps).
244
271
PanicOnError
@@ -261,6 +288,18 @@ type HandlerOpts struct {
261
288
// logged regardless of the configured ErrorHandling provided ErrorLog
262
289
// is not nil.
263
290
ErrorHandling HandlerErrorHandling
291
+ // If Registry is not nil, it is used to register a metric
292
+ // "promhttp_metric_handler_errors_total", partitioned by "cause". A
293
+ // failed registration causes a panic. Note that this error counter is
294
+ // different from the instrumentation you get from the various
295
+ // InstrumentHandler... helpers. It counts errors that don't necessarily
296
+ // result in a non-2xx HTTP status code. There are two typical cases:
297
+ // (1) Encoding errors that only happen after streaming of the HTTP body
298
+ // has already started (and the status code 200 has been sent). This
299
+ // should only happen with custom collectors. (2) Collection errors with
300
+ // no effect on the HTTP status code because ErrorHandling is set to
301
+ // ContinueOnError.
302
+ Registry prometheus.Registerer
264
303
// If DisableCompression is true, the handler will never compress the
265
304
// response, even if requested by the client.
266
305
DisableCompression bool
0 commit comments