github.com/wfusion/gofusion@v1.1.14/common/infra/watermill/components/metrics/handler.go (about)

     1  package metrics
     2  
     3  import (
     4  	"time"
     5  
     6  	"github.com/pkg/errors"
     7  	"github.com/prometheus/client_golang/prometheus"
     8  
     9  	"github.com/wfusion/gofusion/common/infra/watermill/message"
    10  )
    11  
    12  var (
    13  	handlerLabelKeys = []string{
    14  		labelKeyHandlerName,
    15  		labelSuccess,
    16  	}
    17  
    18  	// handlerExecutionTimeBuckets are one order of magnitude smaller than default buckets (5ms~10s),
    19  	// because the handler execution times are typically shorter (µs~ms range).
    20  	handlerExecutionTimeBuckets = []float64{
    21  		0.0005,
    22  		0.001,
    23  		0.0025,
    24  		0.005,
    25  		0.01,
    26  		0.025,
    27  		0.05,
    28  		0.1,
    29  		0.25,
    30  		0.5,
    31  		1,
    32  	}
    33  )
    34  
    35  // HandlerPrometheusMetricsMiddleware is a middleware that captures Prometheus metrics.
    36  type HandlerPrometheusMetricsMiddleware struct {
    37  	handlerExecutionTimeSeconds *prometheus.HistogramVec
    38  }
    39  
    40  // Middleware returns the middleware ready to be used with watermill's Router.
    41  func (m HandlerPrometheusMetricsMiddleware) Middleware(h message.HandlerFunc) message.HandlerFunc {
    42  	return func(msg *message.Message) (msgs []*message.Message, err error) {
    43  		now := time.Now()
    44  		ctx := msg.Context()
    45  		labels := prometheus.Labels{
    46  			labelKeyHandlerName: message.HandlerNameFromCtx(ctx),
    47  		}
    48  
    49  		defer func() {
    50  			if err != nil {
    51  				labels[labelSuccess] = "false"
    52  			} else {
    53  				labels[labelSuccess] = "true"
    54  			}
    55  			m.handlerExecutionTimeSeconds.With(labels).Observe(time.Since(now).Seconds())
    56  		}()
    57  
    58  		return h(msg)
    59  	}
    60  }
    61  
    62  // NewRouterMiddleware returns new middleware.
    63  func (b PrometheusMetricsBuilder) NewRouterMiddleware() HandlerPrometheusMetricsMiddleware {
    64  	var err error
    65  	m := HandlerPrometheusMetricsMiddleware{}
    66  
    67  	m.handlerExecutionTimeSeconds, err = b.registerHistogramVec(prometheus.NewHistogramVec(
    68  		prometheus.HistogramOpts{
    69  			Namespace: b.Namespace,
    70  			Subsystem: b.Subsystem,
    71  			Name:      "handler_execution_time_seconds",
    72  			Help:      "The total time elapsed while executing the handler function in seconds",
    73  			Buckets:   handlerExecutionTimeBuckets,
    74  		},
    75  		handlerLabelKeys,
    76  	))
    77  	if err != nil {
    78  		panic(errors.Wrap(err, "could not register handler execution time metric"))
    79  	}
    80  
    81  	return m
    82  }