Adding pprof middleware for debugging purposes

This commit is contained in:
Craig Peterson 2016-03-18 10:39:29 -06:00
parent 591b209024
commit 640a0ef956
4 changed files with 89 additions and 0 deletions

View File

@ -61,6 +61,7 @@ var directiveOrder = []directive{
{"mime", setup.Mime},
{"basicauth", setup.BasicAuth},
{"internal", setup.Internal},
{"pprof", setup.PProf},
{"proxy", setup.Proxy},
{"fastcgi", setup.FastCGI},
{"websocket", setup.WebSocket},

26
caddy/setup/pprof.go Normal file
View File

@ -0,0 +1,26 @@
package setup
import (
"github.com/mholt/caddy/middleware"
"github.com/mholt/caddy/middleware/pprof"
)
//PProf returns a new instance of a pprof handler. It accepts no arguments or options.
func PProf(c *Controller) (middleware.Middleware, error) {
found := false
for c.Next() {
if found {
return nil, c.Err("pprof can only be specified once")
}
if len(c.RemainingArgs()) != 0 {
return nil, c.ArgErr()
}
if c.NextBlock() {
return nil, c.ArgErr()
}
found = true
}
return func(next middleware.Handler) middleware.Handler {
return pprof.New(next)
}, nil
}

28
caddy/setup/pprof_test.go Normal file
View File

@ -0,0 +1,28 @@
package setup
import "testing"
func TestPProf(t *testing.T) {
tests := []struct {
input string
shouldErr bool
}{
{`pprof`, false},
{`pprof {}`, true},
{`pprof /foo`, true},
{`pprof {
a b
}`, true},
{`pprof
pprof`, true},
}
for i, test := range tests {
c := NewTestController(test.input)
_, err := PProf(c)
if test.shouldErr && err == nil {
t.Errorf("Test %v: Expected error but found nil", i)
} else if !test.shouldErr && err != nil {
t.Errorf("Test %v: Expected no error but found error: %v", i, err)
}
}
}

34
middleware/pprof/pprof.go Normal file
View File

@ -0,0 +1,34 @@
package pprof
import (
"net/http"
pp "net/http/pprof"
"github.com/mholt/caddy/middleware"
)
//Handler is a simple struct whose ServeHTTP will delegate relevant pprof endpoints to net/http/pprof
type handler struct {
mux *http.ServeMux
}
//New creates a new pprof middleware
func New(next middleware.Handler) middleware.Handler {
//pretty much copying what pprof does on init: https://golang.org/src/net/http/pprof/pprof.go#L67
mux := http.NewServeMux()
mux.HandleFunc("/debug/pprof/", pp.Index)
mux.HandleFunc("/debug/pprof/cmdline", pp.Cmdline)
mux.HandleFunc("/debug/pprof/profile", pp.Profile)
mux.HandleFunc("/debug/pprof/symbol", pp.Symbol)
mux.HandleFunc("/debug/pprof/trace", pp.Trace)
mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
next.ServeHTTP(w, r)
})
return &handler{mux}
}
func (h *handler) ServeHTTP(w http.ResponseWriter, r *http.Request) (int, error) {
rec := middleware.NewResponseRecorder(w)
h.mux.ServeHTTP(rec, r)
return rec.Status(), nil
}