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
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"net/http"
|
||||
"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/julienschmidt/httprouter"
|
||||
"github.com/patrickmn/go-cache"
|
||||
@ -15,11 +24,40 @@ import (
|
||||
"go.iondynamics.net/templice"
|
||||
)
|
||||
|
||||
// AcceptedTypes ...
|
||||
var AcceptedTypes = []string{
|
||||
"text/html",
|
||||
"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 ...
|
||||
type Server struct {
|
||||
bind string
|
||||
@ -27,6 +65,13 @@ type Server struct {
|
||||
store *cache.Cache
|
||||
templates *templice.Template
|
||||
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{}) {
|
||||
@ -39,6 +84,8 @@ func (s *Server) render(w http.ResponseWriter, tmpl string, data interface{}) {
|
||||
// IndexHandler ...
|
||||
func (s *Server) IndexHandler() httprouter.Handle {
|
||||
return func(w http.ResponseWriter, r *http.Request, _ httprouter.Params) {
|
||||
s.counters.Inc("n_index")
|
||||
|
||||
accepts, err := accept.Negotiate(
|
||||
r.Header.Get("Accept"), AcceptedTypes...,
|
||||
)
|
||||
@ -60,6 +107,8 @@ func (s *Server) IndexHandler() httprouter.Handle {
|
||||
// PasteHandler ...
|
||||
func (s *Server) PasteHandler() httprouter.Handle {
|
||||
return func(w http.ResponseWriter, r *http.Request, p httprouter.Params) {
|
||||
s.counters.Inc("n_paste")
|
||||
|
||||
var blob string
|
||||
|
||||
body, err := ioutil.ReadAll(r.Body)
|
||||
@ -91,7 +140,7 @@ func (s *Server) PasteHandler() httprouter.Handle {
|
||||
uuid := shortuuid.NewWithNamespace(s.config.fqdn)
|
||||
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 {
|
||||
http.Error(w, "Internal Error", http.StatusInternalServerError)
|
||||
}
|
||||
@ -102,6 +151,8 @@ func (s *Server) PasteHandler() httprouter.Handle {
|
||||
// ViewHandler ...
|
||||
func (s *Server) ViewHandler() httprouter.Handle {
|
||||
return func(w http.ResponseWriter, r *http.Request, p httprouter.Params) {
|
||||
s.counters.Inc("n_view")
|
||||
|
||||
accepts, err := accept.Negotiate(
|
||||
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 ...
|
||||
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() {
|
||||
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.POST("/", s.PasteHandler())
|
||||
s.router.GET("/:uuid", s.ViewHandler())
|
||||
s.router.GET("/view/:uuid", s.ViewHandler())
|
||||
}
|
||||
|
||||
// NewServer ...
|
||||
@ -153,6 +226,17 @@ func NewServer(bind string, config Config) *Server {
|
||||
router: httprouter.New(),
|
||||
store: cache.New(cfg.expiry, cfg.expiry*2),
|
||||
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()
|
||||
|
Loading…
Reference in New Issue
Block a user