Commit 63e4352d authored by Matt Holt's avatar Matt Holt

Merge pull request #612 from captncraig/pprof

pprof: Adding pprof middleware for profiling caddy.
parents 591b2090 640a0ef9
...@@ -61,6 +61,7 @@ var directiveOrder = []directive{ ...@@ -61,6 +61,7 @@ var directiveOrder = []directive{
{"mime", setup.Mime}, {"mime", setup.Mime},
{"basicauth", setup.BasicAuth}, {"basicauth", setup.BasicAuth},
{"internal", setup.Internal}, {"internal", setup.Internal},
{"pprof", setup.PProf},
{"proxy", setup.Proxy}, {"proxy", setup.Proxy},
{"fastcgi", setup.FastCGI}, {"fastcgi", setup.FastCGI},
{"websocket", setup.WebSocket}, {"websocket", setup.WebSocket},
......
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
}
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)
}
}
}
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
}
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment