Skip to content
Snippets Groups Projects
metric.go 3.09 KiB
Newer Older
Diez37's avatar
Diez37 committed
package middleware

import (
Diez37's avatar
Diez37 committed
	"git.diez37.ru/diez37/go-library/app"
	"git.diez37.ru/diez37/go-library/http/client"
	metricHTTP "git.diez37.ru/diez37/go-library/http/metric"
	"git.diez37.ru/diez37/go-library/logger"
	"git.diez37.ru/diez37/go-library/metric"
Diez37's avatar
Diez37 committed
	"github.com/prometheus/client_golang/prometheus"
	"github.com/prometheus/client_golang/prometheus/promauto"
	"net/http"
	"strconv"
)

type requestDurationMetric struct {
	originalTransport http.RoundTripper
	metric            *prometheus.HistogramVec
}

func NewRequestDurationMetric(originalTransport http.RoundTripper, metric *prometheus.HistogramVec) http.RoundTripper {
	return &requestDurationMetric{originalTransport: originalTransport, metric: metric}
}

func (transport *requestDurationMetric) RoundTrip(request *http.Request) (*http.Response, error) {
	timer := prometheus.NewTimer(transport.metric.With(prometheus.Labels{
		metricHTTP.HostFieldName:     request.URL.Host,
		metricHTTP.EndpointFieldName: request.URL.Path,
	}))
	defer timer.ObserveDuration()

	return transport.originalTransport.RoundTrip(request)
}

Diez37's avatar
Diez37 committed
func RequestDuration(appConfig *app.Config, informer logger.Informer) client.MiddlewareFunc {
Diez37's avatar
Diez37 committed
	informer.Info("http.client.middleware: added metric of query execution time counter")

	httpClientDuration := promauto.NewHistogramVec(prometheus.HistogramOpts{
Diez37's avatar
Diez37 committed
		Name: "go_http_client_duration_seconds",
Diez37's avatar
Diez37 committed
		Help: "Duration of HTTP client requests",
		ConstLabels: map[string]string{
			metric.AppNameFieldName: appConfig.Name,
		},
	}, []string{metricHTTP.HostFieldName, metricHTTP.EndpointFieldName})

	return func(next http.RoundTripper) http.RoundTripper {
		return NewRequestDurationMetric(next, httpClientDuration)
	}
}

type totalRequestCountMetric struct {
	originalTransport http.RoundTripper
	metric            *prometheus.CounterVec
}

func NewTotalRequestCountMetric(originalTransport http.RoundTripper, metric *prometheus.CounterVec) http.RoundTripper {
	return &totalRequestCountMetric{originalTransport: originalTransport, metric: metric}
}

func (transport *totalRequestCountMetric) RoundTrip(request *http.Request) (*http.Response, error) {
	response, err := transport.originalTransport.RoundTrip(request)

	statusCode := 0
	if response != nil {
		statusCode = response.StatusCode
	}

	transport.metric.With(prometheus.Labels{
		metricHTTP.CodeFieldName:     strconv.Itoa(statusCode),
		metricHTTP.HostFieldName:     request.URL.Host,
		metricHTTP.EndpointFieldName: request.URL.Path,
	}).Inc()

	return response, err
}

Diez37's avatar
Diez37 committed
func TotalRequestCount(appConfig *app.Config, informer logger.Informer) client.MiddlewareFunc {
Diez37's avatar
Diez37 committed
	informer.Info("http.client.middleware: added a metric for the total number of requests")

	httpClientRequestTotal := promauto.NewCounterVec(prometheus.CounterOpts{
Diez37's avatar
Diez37 committed
		Name: "go_http_client_requests_total",
Diez37's avatar
Diez37 committed
		Help: "Number of HTTP client requests",
		ConstLabels: map[string]string{
			metric.AppNameFieldName: appConfig.Name,
		},
	}, []string{metricHTTP.CodeFieldName, metricHTTP.EndpointFieldName, metricHTTP.HostFieldName})

	return func(next http.RoundTripper) http.RoundTripper {
		return NewTotalRequestCountMetric(next, httpClientRequestTotal)
	}
}