MCPcopy
hub / github.com/caddyserver/caddy / ServeHTTP

Method ServeHTTP

modules/caddyhttp/metrics.go:314–385  ·  view source on GitHub ↗
(w http.ResponseWriter, r *http.Request)

Source from the content-addressed store, hash-verified

312}
313
314func (h *metricsInstrumentedRoute) ServeHTTP(w http.ResponseWriter, r *http.Request) error {
315 server := serverNameFromContext(r.Context())
316 labels := prometheus.Labels{"server": server, "handler": h.handler}
317 method := caddymetrics.SanitizeMethod(r.Method)
318 // the "code" value is set later, but initialized here to eliminate the possibility
319 // of a panic
320 statusLabels := prometheus.Labels{"server": server, "handler": h.handler, "method": method, "code": ""}
321
322 // Determine if this is an HTTPS request
323 isHTTPS := r.TLS != nil
324
325 if h.metrics.PerHost {
326 // Apply cardinality protection for host metrics
327 if h.metrics.shouldAllowHostMetrics(r.Host, isHTTPS) {
328 labels["host"] = strings.ToLower(r.Host)
329 statusLabels["host"] = strings.ToLower(r.Host)
330 } else {
331 // Use a catch-all label for unallowed hosts to prevent cardinality explosion
332 labels["host"] = "_other"
333 statusLabels["host"] = "_other"
334 }
335 }
336
337 inFlight := h.metrics.httpMetrics.requestInFlight.With(labels)
338 inFlight.Inc()
339 defer inFlight.Dec()
340
341 start := time.Now()
342
343 // This is a _bit_ of a hack - it depends on the ShouldBufferFunc always
344 // being called when the headers are written.
345 // Effectively the same behaviour as promhttp.InstrumentHandlerTimeToWriteHeader.
346 writeHeaderRecorder := ShouldBufferFunc(func(status int, header http.Header) bool {
347 statusLabels["code"] = caddymetrics.SanitizeCode(status)
348 ttfb := time.Since(start).Seconds()
349 h.metrics.httpMetrics.responseDuration.With(statusLabels).Observe(ttfb)
350 return false
351 })
352 wrec := NewResponseRecorder(w, nil, writeHeaderRecorder)
353 err := h.next.ServeHTTP(wrec, r)
354 dur := time.Since(start).Seconds()
355 h.metrics.httpMetrics.requestCount.With(labels).Inc()
356
357 observeRequest := func(status int) {
358 // If the code hasn't been set yet, and we didn't encounter an error, we're
359 // probably falling through with an empty handler.
360 if statusLabels["code"] == "" {
361 // we still sanitize it, even though it's likely to be 0. A 200 is
362 // returned on fallthrough so we want to reflect that.
363 statusLabels["code"] = caddymetrics.SanitizeCode(status)
364 }
365
366 h.metrics.httpMetrics.requestDuration.With(statusLabels).Observe(dur)
367 h.metrics.httpMetrics.requestSize.With(statusLabels).Observe(float64(computeApproximateRequestSize(r)))
368 h.metrics.httpMetrics.responseSize.With(statusLabels).Observe(float64(wrec.Size()))
369 }
370
371 if err != nil {

Callers

nothing calls this directly

Calls 9

SizeMethod · 0.95
StatusMethod · 0.95
serverNameFromContextFunction · 0.85
ShouldBufferFuncFuncType · 0.85
NewResponseRecorderFunction · 0.85
ServeHTTPMethod · 0.65
WithMethod · 0.45

Tested by

no test coverage detected