Added metrics, stats and logging
This commit is contained in:
parent
84159c33bf
commit
89269b7aad
90
server.go
90
server.go
@ -1,12 +1,21 @@
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"log"
|
"log"
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/url"
|
"net/url"
|
||||||
|
|
||||||
|
// Logging
|
||||||
|
"github.com/unrolled/logger"
|
||||||
|
|
||||||
|
// Stats/Metrics
|
||||||
|
"github.com/rcrowley/go-metrics"
|
||||||
|
"github.com/rcrowley/go-metrics/exp"
|
||||||
|
"github.com/thoas/stats"
|
||||||
|
|
||||||
"github.com/GeertJohan/go.rice"
|
"github.com/GeertJohan/go.rice"
|
||||||
"github.com/julienschmidt/httprouter"
|
"github.com/julienschmidt/httprouter"
|
||||||
"github.com/patrickmn/go-cache"
|
"github.com/patrickmn/go-cache"
|
||||||
@ -15,11 +24,40 @@ import (
|
|||||||
"go.iondynamics.net/templice"
|
"go.iondynamics.net/templice"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// AcceptedTypes ...
|
||||||
var AcceptedTypes = []string{
|
var AcceptedTypes = []string{
|
||||||
"text/html",
|
"text/html",
|
||||||
"text/plain",
|
"text/plain",
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Counters ...
|
||||||
|
type Counters struct {
|
||||||
|
r metrics.Registry
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewCounters() *Counters {
|
||||||
|
counters := &Counters{
|
||||||
|
r: metrics.NewRegistry(),
|
||||||
|
}
|
||||||
|
return counters
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Counters) Inc(name string) {
|
||||||
|
metrics.GetOrRegisterCounter(name, c.r).Inc(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Counters) Dec(name string) {
|
||||||
|
metrics.GetOrRegisterCounter(name, c.r).Dec(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Counters) IncBy(name string, n int64) {
|
||||||
|
metrics.GetOrRegisterCounter(name, c.r).Inc(n)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Counters) DecBy(name string, n int64) {
|
||||||
|
metrics.GetOrRegisterCounter(name, c.r).Dec(n)
|
||||||
|
}
|
||||||
|
|
||||||
// Server ...
|
// Server ...
|
||||||
type Server struct {
|
type Server struct {
|
||||||
bind string
|
bind string
|
||||||
@ -27,6 +65,13 @@ type Server struct {
|
|||||||
store *cache.Cache
|
store *cache.Cache
|
||||||
templates *templice.Template
|
templates *templice.Template
|
||||||
router *httprouter.Router
|
router *httprouter.Router
|
||||||
|
|
||||||
|
// Logger
|
||||||
|
logger *logger.Logger
|
||||||
|
|
||||||
|
// Stats/Metrics
|
||||||
|
counters *Counters
|
||||||
|
stats *stats.Stats
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Server) render(w http.ResponseWriter, tmpl string, data interface{}) {
|
func (s *Server) render(w http.ResponseWriter, tmpl string, data interface{}) {
|
||||||
@ -39,6 +84,8 @@ func (s *Server) render(w http.ResponseWriter, tmpl string, data interface{}) {
|
|||||||
// IndexHandler ...
|
// IndexHandler ...
|
||||||
func (s *Server) IndexHandler() httprouter.Handle {
|
func (s *Server) IndexHandler() httprouter.Handle {
|
||||||
return func(w http.ResponseWriter, r *http.Request, _ httprouter.Params) {
|
return func(w http.ResponseWriter, r *http.Request, _ httprouter.Params) {
|
||||||
|
s.counters.Inc("n_index")
|
||||||
|
|
||||||
accepts, err := accept.Negotiate(
|
accepts, err := accept.Negotiate(
|
||||||
r.Header.Get("Accept"), AcceptedTypes...,
|
r.Header.Get("Accept"), AcceptedTypes...,
|
||||||
)
|
)
|
||||||
@ -60,6 +107,8 @@ func (s *Server) IndexHandler() httprouter.Handle {
|
|||||||
// PasteHandler ...
|
// PasteHandler ...
|
||||||
func (s *Server) PasteHandler() httprouter.Handle {
|
func (s *Server) PasteHandler() httprouter.Handle {
|
||||||
return func(w http.ResponseWriter, r *http.Request, p httprouter.Params) {
|
return func(w http.ResponseWriter, r *http.Request, p httprouter.Params) {
|
||||||
|
s.counters.Inc("n_paste")
|
||||||
|
|
||||||
var blob string
|
var blob string
|
||||||
|
|
||||||
body, err := ioutil.ReadAll(r.Body)
|
body, err := ioutil.ReadAll(r.Body)
|
||||||
@ -91,7 +140,7 @@ func (s *Server) PasteHandler() httprouter.Handle {
|
|||||||
uuid := shortuuid.NewWithNamespace(s.config.fqdn)
|
uuid := shortuuid.NewWithNamespace(s.config.fqdn)
|
||||||
s.store.Set(uuid, blob, cache.DefaultExpiration)
|
s.store.Set(uuid, blob, cache.DefaultExpiration)
|
||||||
|
|
||||||
u, err := url.Parse(fmt.Sprintf("./%s", uuid))
|
u, err := url.Parse(fmt.Sprintf("./view/%s", uuid))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
http.Error(w, "Internal Error", http.StatusInternalServerError)
|
http.Error(w, "Internal Error", http.StatusInternalServerError)
|
||||||
}
|
}
|
||||||
@ -102,6 +151,8 @@ func (s *Server) PasteHandler() httprouter.Handle {
|
|||||||
// ViewHandler ...
|
// ViewHandler ...
|
||||||
func (s *Server) ViewHandler() httprouter.Handle {
|
func (s *Server) ViewHandler() httprouter.Handle {
|
||||||
return func(w http.ResponseWriter, r *http.Request, p httprouter.Params) {
|
return func(w http.ResponseWriter, r *http.Request, p httprouter.Params) {
|
||||||
|
s.counters.Inc("n_view")
|
||||||
|
|
||||||
accepts, err := accept.Negotiate(
|
accepts, err := accept.Negotiate(
|
||||||
r.Header.Get("Accept"), AcceptedTypes...,
|
r.Header.Get("Accept"), AcceptedTypes...,
|
||||||
)
|
)
|
||||||
@ -134,15 +185,37 @@ func (s *Server) ViewHandler() httprouter.Handle {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// StatsHandler ...
|
||||||
|
func (s *Server) StatsHandler() httprouter.Handle {
|
||||||
|
return func(w http.ResponseWriter, r *http.Request, p httprouter.Params) {
|
||||||
|
w.Header().Set("Content-Type", "application/json; charset=utf-8")
|
||||||
|
bs, err := json.Marshal(s.stats.Data())
|
||||||
|
if err != nil {
|
||||||
|
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||||
|
}
|
||||||
|
w.Write(bs)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// ListenAndServe ...
|
// ListenAndServe ...
|
||||||
func (s *Server) ListenAndServe() {
|
func (s *Server) ListenAndServe() {
|
||||||
log.Fatal(http.ListenAndServe(s.bind, s.router))
|
log.Fatal(
|
||||||
|
http.ListenAndServe(
|
||||||
|
s.bind,
|
||||||
|
s.logger.Handler(
|
||||||
|
s.stats.Handler(s.router),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Server) initRoutes() {
|
func (s *Server) initRoutes() {
|
||||||
|
s.router.Handler("GET", "/debug/metrics", exp.ExpHandler(s.counters.r))
|
||||||
|
s.router.GET("/debug/stats", s.StatsHandler())
|
||||||
|
|
||||||
s.router.GET("/", s.IndexHandler())
|
s.router.GET("/", s.IndexHandler())
|
||||||
s.router.POST("/", s.PasteHandler())
|
s.router.POST("/", s.PasteHandler())
|
||||||
s.router.GET("/:uuid", s.ViewHandler())
|
s.router.GET("/view/:uuid", s.ViewHandler())
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewServer ...
|
// NewServer ...
|
||||||
@ -153,6 +226,17 @@ func NewServer(bind string, config Config) *Server {
|
|||||||
router: httprouter.New(),
|
router: httprouter.New(),
|
||||||
store: cache.New(cfg.expiry, cfg.expiry*2),
|
store: cache.New(cfg.expiry, cfg.expiry*2),
|
||||||
templates: templice.New(rice.MustFindBox("templates")),
|
templates: templice.New(rice.MustFindBox("templates")),
|
||||||
|
|
||||||
|
// Logger
|
||||||
|
logger: logger.New(logger.Options{
|
||||||
|
Prefix: "pastebin",
|
||||||
|
RemoteAddressHeaders: []string{"X-Forwarded-For"},
|
||||||
|
OutputFlags: log.LstdFlags,
|
||||||
|
}),
|
||||||
|
|
||||||
|
// Stats/Metrics
|
||||||
|
counters: NewCounters(),
|
||||||
|
stats: stats.New(),
|
||||||
}
|
}
|
||||||
|
|
||||||
err := server.templates.Load()
|
err := server.templates.Load()
|
||||||
|
Loading…
Reference in New Issue
Block a user