@@ -167,15 +167,12 @@ func HandlerFor(reg prometheus.Gatherer, opts HandlerOpts) http.Handler {
167
167
168
168
enc := expfmt .NewEncoder (w , contentType )
169
169
170
- var lastErr error
171
-
172
170
// handleError handles the error according to opts.ErrorHandling
173
171
// and returns true if we have to abort after the handling.
174
172
handleError := func (err error ) bool {
175
173
if err == nil {
176
174
return false
177
175
}
178
- lastErr = err
179
176
if opts .ErrorLog != nil {
180
177
opts .ErrorLog .Println ("error encoding and sending metric family:" , err )
181
178
}
@@ -184,7 +181,10 @@ func HandlerFor(reg prometheus.Gatherer, opts HandlerOpts) http.Handler {
184
181
case PanicOnError :
185
182
panic (err )
186
183
case HTTPErrorOnError :
187
- httpError (rsp , err )
184
+ // We cannot really send an HTTP error at this
185
+ // point because we most likely have written
186
+ // something to rsp already. But at least we can
187
+ // stop sending.
188
188
return true
189
189
}
190
190
// Do nothing in all other cases, including ContinueOnError.
@@ -202,10 +202,6 @@ func HandlerFor(reg prometheus.Gatherer, opts HandlerOpts) http.Handler {
202
202
return
203
203
}
204
204
}
205
-
206
- if lastErr != nil {
207
- httpError (rsp , lastErr )
208
- }
209
205
})
210
206
211
207
if opts .Timeout <= 0 {
@@ -276,7 +272,12 @@ type HandlerErrorHandling int
276
272
// errors are encountered.
277
273
const (
278
274
// Serve an HTTP status code 500 upon the first error
279
- // encountered. Report the error message in the body.
275
+ // encountered. Report the error message in the body. Note that HTTP
276
+ // errors cannot be served anymore once the beginning of a regular
277
+ // payload has been sent. Thus, in the (unlikely) case that encoding the
278
+ // payload into the negotiated wire format fails, serving the response
279
+ // will simply be aborted. Set an ErrorLog in HandlerOpts to detect
280
+ // those errors.
280
281
HTTPErrorOnError HandlerErrorHandling = iota
281
282
// Ignore errors and try to serve as many metrics as possible. However,
282
283
// if no metrics can be served, serve an HTTP status code 500 and the
@@ -365,11 +366,9 @@ func gzipAccepted(header http.Header) bool {
365
366
}
366
367
367
368
// httpError removes any content-encoding header and then calls http.Error with
368
- // the provided error and http.StatusInternalServerErrer. Error contents is
369
- // supposed to be uncompressed plain text. However, same as with a plain
370
- // http.Error, any header settings will be void if the header has already been
371
- // sent. The error message will still be written to the writer, but it will
372
- // probably be of limited use.
369
+ // the provided error and http.StatusInternalServerError. Error contents is
370
+ // supposed to be uncompressed plain text. Same as with a plain http.Error, this
371
+ // must not be called if the header or any payload has already been sent.
373
372
func httpError (rsp http.ResponseWriter , err error ) {
374
373
rsp .Header ().Del (contentEncodingHeader )
375
374
http .Error (
0 commit comments