package app import ( "fmt" "net/http" "time" "github.com/prometheus/client_golang/prometheus" "github.com/rs/cors" ) var ( namespace = "collage" counter = prometheus.NewCounterVec(prometheus.CounterOpts{ Namespace: namespace, Name: "endpoint_request_count", Help: "collage request count.", }, []string{"app", "name", "method", "state"}) histogram = prometheus.NewHistogramVec(prometheus.HistogramOpts{ Namespace: namespace, Name: "endpoint_duration_seconds", Help: "Time taken to execute endpoint.", }, []string{"app", "name", "method", "status"}) ) type metricResponseWriter struct { http.ResponseWriter statusCode int } func newMetricResponseWriter(w http.ResponseWriter) *metricResponseWriter { return &metricResponseWriter{w, http.StatusOK} } func (lrw *metricResponseWriter) WriteHeader(code int) { lrw.statusCode = code lrw.ResponseWriter.WriteHeader(code) } // SetupPrometheusHandler enable CORS, handler metrics func SetupPrometheusHandler(handler http.Handler, app string) http.Handler { sugar.Debug("app.SetupPrometheusHandler: 📥") handleCORS := cors.AllowAll().Handler h := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { start := time.Now() lrw := newMetricResponseWriter(w) handler.ServeHTTP(lrw, r) statusCode := lrw.statusCode duration := time.Since(start) histogram.WithLabelValues(app, r.URL.String(), r.Method, fmt.Sprintf("%d", statusCode)).Observe(duration.Seconds()) counter.WithLabelValues(app, r.URL.String(), r.Method, fmt.Sprintf("%d", statusCode)).Inc() }) err := prometheus.Register(histogram) if err != nil { sugar.Errorf("app.SetupPrometheusHandler: 💣 ⛔ %w", err) return nil } err = prometheus.Register(counter) if err != nil { sugar.Errorf("app.SetupPrometheusHandler: 💣 ⛔ %w", err) return nil } sugar.Info("app.SetupPrometheusHandler: 👍 📤") return handleCORS(h) }