To instrument an HTTP handler with Prometheus in Go, create and register a Counter for request totals and a Histogram for request durations (or a Summary). Use labels (e.g., method, path, status) carefully to avoid high cardinality. Wrap handlers in middleware that starts a timer, calls the handler, records status and duration, and increments the counter.go
package main
import (
"net/http"
"time"
"github.com/prometheus/client_golang/prometheus"
"github.com/prometheus/client_golang/prometheus/promhttp"
)
var (
reqCount = prometheus.NewCounterVec(
prometheus.CounterOpts{
Name: "myapp_http_requests_total",
Help: "Total HTTP requests",
},
[]string{"method", "path", "status"},
)
reqDuration = prometheus.NewHistogramVec(
prometheus.HistogramOpts{
Name: "myapp_http_request_duration_seconds",
Help: "HTTP request durations in seconds",
Buckets: prometheus.DefBuckets, // tune buckets for your latencies
},
[]string{"method", "path"},
)
)
func init() {
prometheus.MustRegister(reqCount, reqDuration)
}
func instrumented(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
start := time.Now()
// capture status using a wrapper
rw := &statusResponseWriter{ResponseWriter: w, status: http.StatusOK}
next.ServeHTTP(rw, r)
dur := time.Since(start).Seconds()
path := r.URL.Path // consider route templating to reduce cardinality
reqDuration.WithLabelValues(r.Method, path).Observe(dur)
reqCount.WithLabelValues(r.Method, path, http.StatusText(rw.status)).Inc()
})
}
type statusResponseWriter struct {
http.ResponseWriter
status int
}
func (s *statusResponseWriter) WriteHeader(code int) {
s.status = code
s.ResponseWriter.WriteHeader(code)
}
func main() {
mux := http.NewServeMux()
mux.Handle("/metrics", promhttp.Handler())
mux.Handle("/home", instrumented(http.HandlerFunc(homeHandler)))
http.ListenAndServe(":8080", mux)
}
func homeHandler(w http.ResponseWriter, r *http.Request) {
w.Write([]byte("ok"))
}
Key points:- Register metrics once (global/init).- Use Histogram buckets appropriate to your latency distribution.- Reduce label cardinality (use route names, not raw paths).- Expose /metrics via promhttp.Handler().