prometheus
prometheus
metrics
Basic prometheus example with HTTP Basic authentication for the /metrics
endpoint:
Notice the use of .Name("endpoint")
and GetRouteName
:
endpoint := violetear.GetRouteName(r)
c.WithLabelValues(endpoint).Observe(time.Since(start).Seconds())
This helps to create the labels using the defined names when creating the route.
package main
import (
"crypto/subtle"
"fmt"
"log"
"net/http"
"time"
"github.com/nbari/violetear"
"github.com/nbari/violetear/middleware"
"github.com/prometheus/client_golang/prometheus"
)
func index(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, "index %s!", r.URL.Path)
}
func foo(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, "foo %s!", r.URL.Path)
}
func bar(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, "bar %s!", r.URL.Path)
}
// BasicAuth secure /metrics endpoint by using the defined username and password
func BasicAuth(next http.Handler, username, password, realm string) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
user, pass, ok := r.BasicAuth()
if !ok || subtle.ConstantTimeCompare([]byte(user), []byte(username)) != 1 || subtle.ConstantTimeCompare([]byte(pass), []byte(password)) != 1 {
w.Header().Set("WWW-Authenticate", `Basic realm="`+realm+`"`)
http.Error(w, "Unauthorized.", http.StatusUnauthorized)
return
}
next.ServeHTTP(w, r)
})
}
func secondMW(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
log.Println("Second middleware")
// do something here
next.ServeHTTP(w, r)
})
}
func counterMW(c *prometheus.HistogramVec) middleware.Constructor {
return func(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
start := time.Now()
log.Println("Executing counter middleware")
// do something here
next.ServeHTTP(w, r)
log.Println("updating prometheus counters")
endpoint := violetear.GetRouteName(r)
c.WithLabelValues(endpoint).Observe(time.Since(start).Seconds())
})
}
}
func main() {
counter := prometheus.NewHistogramVec(
prometheus.HistogramOpts{
Namespace: "myAPI",
Name: "requests_total",
Help: "Total number of requests.",
}, []string{"endpoint"})
prometheus.MustRegister(counter)
// midleware
stdChain := middleware.New(counterMW(counter), secondMW)
router := violetear.New()
router.Handle("/", stdChain.ThenFunc(index)).Name("root")
router.Handle("/foo", stdChain.ThenFunc(foo), "GET").Name("foo")
router.Handle("/bar", stdChain.ThenFunc(bar), "POST").Name("bar")
router.Handle("/metrics", BasicAuth(prometheus.Handler(),
"user",
"password",
"Please enter username and password"),
)
// configure server
srv := &http.Server{
Addr: ":8080",
Handler: router,
ReadTimeout: 5 * time.Second,
WriteTimeout: 7 * time.Second,
MaxHeaderBytes: 1 << 20,
}
log.Fatal(srv.ListenAndServe())
}
gist: https://gist.github.com/nbari/04ce9bf4080e52951aedd1fced0a16bd