Skip to content

Commit

Permalink
chore: add prometheus metrics
Browse files Browse the repository at this point in the history
  • Loading branch information
martinsaporiti committed Apr 5, 2024
1 parent 9a3ec0e commit bde3d57
Show file tree
Hide file tree
Showing 3 changed files with 99 additions and 1 deletion.
13 changes: 12 additions & 1 deletion cmd/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,14 +11,18 @@ import (
chiMiddleware "github.com/go-chi/chi/v5/middleware"
"github.com/go-chi/cors"
"github.com/iden3/go-iden3-auth/v2/loaders"
"github.com/prometheus/client_golang/prometheus"
log "github.com/sirupsen/logrus"

"github.com/0xPolygonID/verifier-backend/internal/api"
"github.com/0xPolygonID/verifier-backend/internal/config"
"github.com/0xPolygonID/verifier-backend/internal/errors"
"github.com/0xPolygonID/verifier-backend/internal/metrics"
)

func main() {
registerMetrics()

cfg, err := config.Load()
if err != nil {
log.WithField("error", err).Error("cannot load config")
Expand All @@ -28,8 +32,8 @@ func main() {
keysLoader := &loaders.FSKeyLoader{Dir: cfg.KeyDIR}

mux := chi.NewRouter()

mux.Use(
metrics.PrometheusTotalRequestsMiddleware,
chiMiddleware.RequestID,
chiMiddleware.Recoverer,
cors.Handler(cors.Options{AllowedOrigins: []string{"*"}}),
Expand All @@ -40,6 +44,7 @@ func main() {
api.HandlerFromMux(api.NewStrictHandlerWithOptions(apiServer, nil,
api.StrictHTTPServerOptions{RequestErrorHandlerFunc: errors.RequestErrorHandlerFunc}), mux)
api.RegisterStatic(mux)
api.RegisterMetrics(mux)

server := &http.Server{
Addr: fmt.Sprintf(":%s", cfg.ApiPort),
Expand All @@ -58,3 +63,9 @@ func main() {
<-quit
log.Info("Shutting down")
}

func registerMetrics() {
prometheus.MustRegister(metrics.TotalRequests)
prometheus.MustRegister(metrics.HttpDuration)
prometheus.MustRegister(metrics.ResponseStatus)
}
11 changes: 11 additions & 0 deletions internal/api/metrics.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package api

import (
"github.com/go-chi/chi/v5"
"github.com/prometheus/client_golang/prometheus/promhttp"
)

// RegisterMetrics - registers the static routes for the API.
func RegisterMetrics(mux *chi.Mux) {
mux.Handle("/metrics", promhttp.Handler())
}
76 changes: 76 additions & 0 deletions internal/metrics/metrics.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
package metrics

import (
"net/http"
"strconv"

"github.com/prometheus/client_golang/prometheus"
)

// TotalRequests - CounterVec to store the total number of requests per path
var TotalRequests = prometheus.NewCounterVec(
prometheus.CounterOpts{
Name: "http_requests_total_per_path",
Help: "Number of get requests per path",
},
[]string{"path"},
)

// ResponseStatus - CounterVec to store the status of the response
var ResponseStatus = prometheus.NewCounterVec(
prometheus.CounterOpts{
Name: "http_response_status",
Help: "Status of HTTP response",
},
[]string{"status"},
)

// HttpDuration - HistogramVec to store the duration of the HTTP requests per path
var HttpDuration = prometheus.NewHistogramVec(prometheus.HistogramOpts{
Name: "http_response_time_seconds_per_path",
Help: "Duration of HTTP requests per path",
}, []string{"path"})

type responseWriter struct {
http.ResponseWriter
statusCode int
}

func newResponseWriter(w http.ResponseWriter) *responseWriter {
return &responseWriter{w, http.StatusOK}
}

func (rw *responseWriter) WriteHeader(code int) {
rw.statusCode = code
rw.ResponseWriter.WriteHeader(code)
}

// PrometheusTotalRequestsMiddleware - Middleware to record metrics for the API
func PrometheusTotalRequestsMiddleware(next http.Handler) http.Handler {
fn := func(w http.ResponseWriter, r *http.Request) {
ctx := r.Context()
path := r.URL.Path
if mustBeExcluded(path) {
next.ServeHTTP(w, r.WithContext(ctx))
return
}
timer := prometheus.NewTimer(HttpDuration.WithLabelValues(path))
rw := newResponseWriter(w)
next.ServeHTTP(rw, r)

statusCode := rw.statusCode
ResponseStatus.WithLabelValues(strconv.Itoa(statusCode)).Inc()
TotalRequests.WithLabelValues(path).Inc()

timer.ObserveDuration()
}
return http.HandlerFunc(fn)
}

func mustBeExcluded(path string) bool {
mustBe := false
if path == "" || path == "/static/docs/api/api.yaml" || path == "/metrics" {
mustBe = true
}
return mustBe
}

0 comments on commit bde3d57

Please sign in to comment.