stats is a net/http
handler in golang reporting various metrics about
your web application.
This middleware has been developed and required for the need of picfit, an image resizing server written in Go.
This handler supports the following frameworks at the moment:
We don't support your favorite Go framework? Send me a PR or create a new issue and I will implement it :)
- Make sure you have a Go language compiler >= 1.3 (required) and git installed.
- Make sure you have the following go system dependencies in your $PATH: bzr, svn, hg, git
- Ensure your GOPATH is properly set.
- Download it:
go get github.com/thoas/stats
To use this handler directly with net/http
, you need to call the
middleware with the handler itself:
package main
import (
"net/http"
"github.com/thoas/stats"
)
func main() {
h := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "application/json")
w.Write([]byte("{\"hello\": \"world\"}"))
})
handler := stats.New().Handler(h)
http.ListenAndServe(":8080", handler)
}
If you are using negroni you can implement the handler as
a simple middleware in server.go
:
package main
import (
"net/http"
"github.com/codegangsta/negroni"
"github.com/thoas/stats"
"encoding/json"
)
func main() {
middleware := stats.New()
mux := http.NewServeMux()
mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "application/json")
w.Write([]byte("{\"hello\": \"world\"}"))
})
mux.HandleFunc("/stats", func(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "application/json")
stats := middleware.Data()
b, _ := json.Marshal(stats)
w.Write(b)
})
n := negroni.Classic()
n.Use(middleware)
n.UseHandler(mux)
n.Run(":3000")
}
If you are using HTTPRouter you need to call the middleware with the handler itself:
package main
import (
"encoding/json"
"github.com/julienschmidt/httprouter"
"github.com/thoas/stats"
"net/http"
)
func main() {
router := httprouter.New()
s := stats.New()
router.GET("/stats", func(w http.ResponseWriter, _ *http.Request, _ httprouter.Params) {
w.Header().Set("Content-Type", "application/json; charset=utf-8")
s, err := json.Marshal(s.Data())
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
}
w.Write(s)
})
http.ListenAndServe(":8080", s.Handler(router))
}
If you are using martini, you can implement the handler as a wrapper of
a Martini.Context
in server.go
:
package main
import (
"encoding/json"
"github.com/go-martini/martini"
"github.com/thoas/stats"
"net/http"
)
func main() {
middleware := stats.New()
m := martini.Classic()
m.Get("/", func(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "application/json")
w.Write([]byte("{\"hello\": \"world\"}"))
})
m.Get("/stats", func(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "application/json")
stats := middleware.Data()
b, _ := json.Marshal(stats)
w.Write(b)
})
m.Use(func(c martini.Context, w http.ResponseWriter, r *http.Request) {
beginning, recorder := middleware.Begin(w)
c.Next()
middleware.End(beginning, stats.WithRecorder(recorder))
})
m.Run()
}
Run it in a shell:
$ go run server.go
Then in another shell run:
$ curl http://localhost:3000/stats | python -m "json.tool"
Expect the following result:
{
"total_response_time": "1.907382ms",
"average_response_time": "86.699\u00b5s",
"average_response_time_sec": 8.6699e-05,
"count": 1,
"pid": 99894,
"status_code_count": {
"200": 1
},
"time": "2015-03-06 17:23:27.000677896 +0100 CET",
"total_count": 22,
"total_response_time_sec": 0.0019073820000000002,
"total_status_code_count": {
"200": 22
},
"unixtime": 1425659007,
"uptime": "4m14.502271612s",
"uptime_sec": 254.502271612
}
See examples to test them.
Antoine Imbert is the original author of this middleware.
Originally developed for go-json-rest, it had been ported as a simple Golang handler by Florent Messa to be used in various frameworks.
This middleware implements a ticker which is launched every seconds to reset requests/sec and will implement new features in a near future :)