metrics/handler.go (92 lines of code) (raw):
package metrics
import (
"net/http"
"github.com/prometheus/client_golang/prometheus"
"github.com/prometheus/client_golang/prometheus/promhttp"
)
// Metric names for the recorded metrics.
// These are the conventional names prometheus uses for these metrics.
const (
httpInFlightRequestsMetricName = "in_flight_requests"
httpRequestsTotalMetricName = "requests_total"
httpRequestDurationSecondsMetricName = "request_duration_seconds"
httpRequestSizeBytesMetricName = "request_size_bytes"
httpResponseSizeBytesMetricName = "response_size_bytes"
httpTimeToWriteHeaderSecondsMetricName = "time_to_write_header_seconds"
)
// HandlerFactory creates handler middleware instances. Created by NewHandlerFactory.
type HandlerFactory func(next http.Handler, opts ...HandlerOption) http.Handler
// NewHandlerFactory will create a function for creating metric middlewares.
// The resulting function can be called multiple times to obtain multiple middleware
// instances.
// Each instance can be configured with different options that will be applied to the
// same underlying metrics.
func NewHandlerFactory(opts ...HandlerFactoryOption) HandlerFactory {
factoryConfig := applyHandlerFactoryOptions(opts)
var (
httpInFlightRequests = prometheus.NewGauge(prometheus.GaugeOpts{
Namespace: factoryConfig.namespace,
Subsystem: factoryConfig.subsystem,
Name: httpInFlightRequestsMetricName,
Help: "A gauge of requests currently being served by the http server.",
})
httpRequestsTotal = prometheus.NewCounterVec(
prometheus.CounterOpts{
Namespace: factoryConfig.namespace,
Subsystem: factoryConfig.subsystem,
Name: httpRequestsTotalMetricName,
Help: "A counter for requests to the http server.",
},
factoryConfig.labels,
)
httpRequestDurationSeconds = prometheus.NewHistogramVec(
prometheus.HistogramOpts{
Namespace: factoryConfig.namespace,
Subsystem: factoryConfig.subsystem,
Name: httpRequestDurationSecondsMetricName,
Help: "A histogram of latencies for requests to the http server.",
Buckets: factoryConfig.requestDurationBuckets,
},
factoryConfig.labels,
)
httpRequestSizeBytes = prometheus.NewHistogramVec(
prometheus.HistogramOpts{
Namespace: factoryConfig.namespace,
Subsystem: factoryConfig.subsystem,
Name: httpRequestSizeBytesMetricName,
Help: "A histogram of sizes of requests to the http server.",
Buckets: factoryConfig.byteSizeBuckets,
},
factoryConfig.labels,
)
httpResponseSizeBytes = prometheus.NewHistogramVec(
prometheus.HistogramOpts{
Namespace: factoryConfig.namespace,
Subsystem: factoryConfig.subsystem,
Name: httpResponseSizeBytesMetricName,
Help: "A histogram of response sizes for requests to the http server.",
Buckets: factoryConfig.byteSizeBuckets,
},
factoryConfig.labels,
)
httpTimeToWriteHeaderSeconds = prometheus.NewHistogramVec(
prometheus.HistogramOpts{
Namespace: factoryConfig.namespace,
Subsystem: factoryConfig.subsystem,
Name: httpTimeToWriteHeaderSecondsMetricName,
Help: "A histogram of request durations until the response headers are written.",
Buckets: factoryConfig.timeToWriteHeaderDurationBuckets,
},
factoryConfig.labels,
)
)
prometheus.MustRegister(httpInFlightRequests)
prometheus.MustRegister(httpRequestsTotal)
prometheus.MustRegister(httpRequestDurationSeconds)
prometheus.MustRegister(httpRequestSizeBytes)
prometheus.MustRegister(httpResponseSizeBytes)
prometheus.MustRegister(httpTimeToWriteHeaderSeconds)
return func(next http.Handler, handlerOpts ...HandlerOption) http.Handler {
handlerConfig, promOpts := applyHandlerOptions(handlerOpts)
handler := next
handler = promhttp.InstrumentHandlerCounter(handlerConfig.applyOptionsToCounterVec(httpRequestsTotal), handler, promOpts...)
handler = promhttp.InstrumentHandlerDuration(handlerConfig.applyOptionsToObserverVec(httpRequestDurationSeconds), handler, promOpts...)
handler = promhttp.InstrumentHandlerInFlight(httpInFlightRequests, handler)
handler = promhttp.InstrumentHandlerRequestSize(handlerConfig.applyOptionsToObserverVec(httpRequestSizeBytes), handler, promOpts...)
handler = promhttp.InstrumentHandlerResponseSize(handlerConfig.applyOptionsToObserverVec(httpResponseSizeBytes), handler, promOpts...)
handler = promhttp.InstrumentHandlerTimeToWriteHeader(handlerConfig.applyOptionsToObserverVec(httpTimeToWriteHeaderSeconds), handler, promOpts...)
return handler
}
}