Skip to content

Instantly share code, notes, and snippets.

@alexrios
Created July 28, 2022 20:35
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save alexrios/ea9366b5537b076387d141a993731830 to your computer and use it in GitHub Desktop.
Save alexrios/ea9366b5537b076387d141a993731830 to your computer and use it in GitHub Desktop.
Tally based RED metrics middleware
package middleware
import (
"net/http"
"github.com/uber-go/tally/v4"
)
type statusCodeAwareWriter struct {
http.ResponseWriter
statusCode int
}
func (w *statusCodeAwareWriter) WriteHeader(status int) {
w.statusCode = status
w.ResponseWriter.WriteHeader(status)
}
func (w *statusCodeAwareWriter) Write(b []byte) (int, error) {
return w.ResponseWriter.Write(b)
}
func (w *statusCodeAwareWriter) HasAnError() bool {
return w.statusCode >= http.StatusInternalServerError
}
type RedMetricsMiddleware struct {
TotalRequests tally.Counter
RequestsDuration tally.Histogram
RequestFailures tally.Counter
}
func NewRedMetricsMiddleware(c tally.Counter, d tally.Histogram, f tally.Counter) *RedMetricsMiddleware {
return &RedMetricsMiddleware{
TotalRequests: c,
RequestsDuration: d,
RequestFailures: f,
}
}
func (m *RedMetricsMiddleware) Handle() func(next http.Handler) http.Handler {
return func(next http.Handler) http.Handler {
fn := func(w http.ResponseWriter, r *http.Request) {
dw := &statusCodeAwareWriter{ResponseWriter: w}
stopwatch := m.RequestsDuration.Start()
m.TotalRequests.Inc(1)
next.ServeHTTP(dw, r)
stopwatch.Stop()
if dw.HasAnError() {
m.RequestFailures.Inc(1)
}
}
return http.HandlerFunc(fn)
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment