File: handler.go

package info (click to toggle)
golang-gitlab-gitlab-org-labkit 1.17.0-4
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 1,092 kB
  • sloc: sh: 210; javascript: 49; makefile: 4
file content (115 lines) | stat: -rw-r--r-- 4,531 bytes parent folder | download | duplicates (4)
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
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 := applyHandlerOptions(handlerOpts)

		handler := next

		handler = promhttp.InstrumentHandlerCounter(httpRequestsTotal.MustCurryWith(handlerConfig.labelValues), handler)
		handler = promhttp.InstrumentHandlerDuration(httpRequestDurationSeconds.MustCurryWith(handlerConfig.labelValues), handler)
		handler = promhttp.InstrumentHandlerInFlight(httpInFlightRequests, handler)
		handler = promhttp.InstrumentHandlerRequestSize(httpRequestSizeBytes.MustCurryWith(handlerConfig.labelValues), handler)
		handler = promhttp.InstrumentHandlerResponseSize(httpResponseSizeBytes.MustCurryWith(handlerConfig.labelValues), handler)
		handler = promhttp.InstrumentHandlerTimeToWriteHeader(httpTimeToWriteHeaderSeconds.MustCurryWith(handlerConfig.labelValues), handler)

		return handler
	}
}