93 lines
2.3 KiB
Go
93 lines
2.3 KiB
Go
package metrics
|
|
|
|
import (
|
|
"time"
|
|
|
|
"github.com/pkg/errors"
|
|
"github.com/prometheus/client_golang/prometheus"
|
|
|
|
"github.com/ThreeDotsLabs/watermill/message"
|
|
)
|
|
|
|
var (
|
|
handlerLabelKeys = []string{
|
|
labelKeyHandlerName,
|
|
labelSuccess,
|
|
}
|
|
|
|
// defaultHandlerExecutionTimeBuckets are one order of magnitude smaller than default buckets (5ms~10s),
|
|
// because the handler execution times are typically shorter (µs~ms range).
|
|
defaultHandlerExecutionTimeBuckets = []float64{
|
|
0.0005,
|
|
0.001,
|
|
0.0025,
|
|
0.005,
|
|
0.01,
|
|
0.025,
|
|
0.05,
|
|
0.1,
|
|
0.25,
|
|
0.5,
|
|
1,
|
|
}
|
|
)
|
|
|
|
// HandlerPrometheusMetricsMiddleware is a middleware that captures Prometheus metrics.
|
|
type HandlerPrometheusMetricsMiddleware struct {
|
|
handlerExecutionTimeSeconds *prometheus.HistogramVec
|
|
additionalLabels []MetricLabel
|
|
}
|
|
|
|
// Middleware returns the middleware ready to be used with watermill's Router.
|
|
func (m HandlerPrometheusMetricsMiddleware) Middleware(h message.HandlerFunc) message.HandlerFunc {
|
|
return func(msg *message.Message) (msgs []*message.Message, err error) {
|
|
now := time.Now()
|
|
ctx := msg.Context()
|
|
labels := prometheus.Labels{
|
|
labelKeyHandlerName: message.HandlerNameFromCtx(ctx),
|
|
}
|
|
for _, lb := range m.additionalLabels {
|
|
labels[lb.Label] = lb.ComputeValueFn(ctx)
|
|
}
|
|
|
|
defer func() {
|
|
if err != nil {
|
|
labels[labelSuccess] = "false"
|
|
} else {
|
|
labels[labelSuccess] = "true"
|
|
}
|
|
m.handlerExecutionTimeSeconds.With(labels).Observe(time.Since(now).Seconds())
|
|
}()
|
|
|
|
return h(msg)
|
|
}
|
|
}
|
|
|
|
// NewRouterMiddleware returns new middleware.
|
|
func (b PrometheusMetricsBuilder) NewRouterMiddleware() HandlerPrometheusMetricsMiddleware {
|
|
var err error
|
|
m := HandlerPrometheusMetricsMiddleware{
|
|
additionalLabels: b.additionalLabels,
|
|
}
|
|
|
|
if b.HandlerBuckets == nil {
|
|
b.HandlerBuckets = defaultHandlerExecutionTimeBuckets
|
|
}
|
|
|
|
m.handlerExecutionTimeSeconds, err = b.registerHistogramVec(prometheus.NewHistogramVec(
|
|
prometheus.HistogramOpts{
|
|
Namespace: b.Namespace,
|
|
Subsystem: b.Subsystem,
|
|
Name: "handler_execution_time_seconds",
|
|
Help: "The total time elapsed while executing the handler function in seconds",
|
|
Buckets: b.HandlerBuckets,
|
|
},
|
|
toLabelsSlice(handlerLabelKeys, b.additionalLabels),
|
|
))
|
|
if err != nil {
|
|
panic(errors.Wrap(err, "could not register handler execution time metric"))
|
|
}
|
|
|
|
return m
|
|
}
|