Files
logiflow/internal/handler/metrics.go

67 lines
1.5 KiB
Go

package handler
import (
"bufio"
"fmt"
"net"
"net/http"
"strconv"
"time"
"github.com/prometheus/client_golang/prometheus"
"github.com/prometheus/client_golang/prometheus/promauto"
)
var (
httpRequests = promauto.NewCounterVec(prometheus.CounterOpts{
Name: "logiflow_http_requests_total",
Help: "Количество HTTP запросов",
}, []string{"method", "path", "status"})
httpDuration = promauto.NewHistogramVec(prometheus.HistogramOpts{
Name: "logiflow_http_duration_seconds",
Help: "Время обработки HTTP запросов",
Buckets: prometheus.DefBuckets,
}, []string{"method", "path"})
)
func (s *Server) MiddlewareMetrics(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
start := time.Now()
wrapped := &statusRecorder{ResponseWriter: w, status: http.StatusOK}
next.ServeHTTP(wrapped, r)
httpRequests.WithLabelValues(
r.Method,
r.URL.Path,
strconv.Itoa(wrapped.status),
).Inc()
httpDuration.WithLabelValues(r.Method, r.URL.Path).
Observe(time.Since(start).Seconds())
})
}
type statusRecorder struct {
http.ResponseWriter
status int
}
func (r *statusRecorder) Hijack() (net.Conn, *bufio.ReadWriter, error) {
h, ok := r.ResponseWriter.(http.Hijacker)
if !ok {
return nil, nil, fmt.Errorf("hijack not supportd")
}
return h.Hijack()
}
func (r *statusRecorder) Unwrap() http.ResponseWriter {
return r.ResponseWriter
}
func (r *statusRecorder) WriteHeader(status int) {
r.status = status
r.ResponseWriter.WriteHeader(status)
}