Skip to content

Commit

Permalink
init
Browse files Browse the repository at this point in the history
  • Loading branch information
sevennt committed Apr 26, 2017
0 parents commit 3ba87e4
Show file tree
Hide file tree
Showing 4 changed files with 206 additions and 0 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
.idea/
24 changes: 24 additions & 0 deletions example/example.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package main

import (
"github.com/labstack/echo"
"github.com/sevenNt/echo-pprof"
)

func main() {
e := echo.New()

e.GET("/ping", func(c echo.Context) error {
return c.String(200, "pong")
})

// automatically add routers for net/http/pprof
// e.g. /debug/pprof, /debug/pprof/heap, etc.
echopprof.Wrap(e)

// echopprof also plays well with *gin.RouterGroup
// group := e.Group("/debug/pprof")
// echopprof.WrapGroup(group)

e.Start(":8080")
}
127 changes: 127 additions & 0 deletions pprof.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
package echopprof

import (
"net/http/pprof"
"strings"

"github.com/labstack/echo"
)

// Wrap adds several routes from package `net/http/pprof` to *gin.Engine object
func Wrap(e *echo.Echo) {
WrapGroup(e.Group(""))
}

// Wrapper make sure we are backward compatible
var Wrapper = Wrap

// WrapGroup adds several routes from package `net/http/pprof` to *gin.RouterGroup object
func WrapGroup(g *echo.Group) {
routers := []struct {
Method string
Path string
Handler echo.HandlerFunc
}{
{"GET", "/debug/pprof/", IndexHandler()},
{"GET", "/debug/pprof/heap", HeapHandler()},
{"GET", "/debug/pprof/goroutine", GoroutineHandler()},
{"GET", "/debug/pprof/block", BlockHandler()},
{"GET", "/debug/pprof/threadcreate", ThreadCreateHandler()},
{"GET", "/debug/pprof/cmdline", CmdlineHandler()},
{"GET", "/debug/pprof/profile", ProfileHandler()},
{"GET", "/debug/pprof/symbol", SymbolHandler()},
{"POST", "/debug/pprof/symbol", SymbolHandler()},
{"GET", "/debug/pprof/trace", TraceHandler()},
{"GET", "/debug/pprof/mutex", MutexHandler()},
}

prefix := ""
for _, r := range routers {
switch r.Method {
case "GET":
g.GET(strings.TrimPrefix(r.Path, prefix), r.Handler)
case "POST":
g.POST(strings.TrimPrefix(r.Path, prefix), r.Handler)
}
}
}

// IndexHandler will pass the call from /debug/pprof to pprof
func IndexHandler() echo.HandlerFunc {
return func(ctx echo.Context) error {
pprof.Index(ctx.Response().Writer, ctx.Request())
return nil
}
}

// HeapHandler will pass the call from /debug/pprof/heap to pprof
func HeapHandler() echo.HandlerFunc {
return func(ctx echo.Context) error {
pprof.Handler("heap").ServeHTTP(ctx.Response(), ctx.Request())
return nil
}
}

// GoroutineHandler will pass the call from /debug/pprof/goroutine to pprof
func GoroutineHandler() echo.HandlerFunc {
return func(ctx echo.Context) error {
pprof.Handler("goroutine").ServeHTTP(ctx.Response().Writer, ctx.Request())
return nil
}
}

// BlockHandler will pass the call from /debug/pprof/block to pprof
func BlockHandler() echo.HandlerFunc {
return func(ctx echo.Context) error {
pprof.Handler("block").ServeHTTP(ctx.Response().Writer, ctx.Request())
return nil
}
}

// ThreadCreateHandler will pass the call from /debug/pprof/threadcreate to pprof
func ThreadCreateHandler() echo.HandlerFunc {
return func(ctx echo.Context) error {
pprof.Handler("threadcreate").ServeHTTP(ctx.Response().Writer, ctx.Request())
return nil
}
}

// CmdlineHandler will pass the call from /debug/pprof/cmdline to pprof
func CmdlineHandler() echo.HandlerFunc {
return func(ctx echo.Context) error {
pprof.Cmdline(ctx.Response().Writer, ctx.Request())
return nil
}
}

// ProfileHandler will pass the call from /debug/pprof/profile to pprof
func ProfileHandler() echo.HandlerFunc {
return func(ctx echo.Context) error {
pprof.Profile(ctx.Response().Writer, ctx.Request())
return nil
}
}

// SymbolHandler will pass the call from /debug/pprof/symbol to pprof
func SymbolHandler() echo.HandlerFunc {
return func(ctx echo.Context) error {
pprof.Symbol(ctx.Response().Writer, ctx.Request())
return nil
}
}

// TraceHandler will pass the call from /debug/pprof/trace to pprof
func TraceHandler() echo.HandlerFunc {
return func(ctx echo.Context) error {
pprof.Trace(ctx.Response().Writer, ctx.Request())
return nil
}
}

// MutexHandler will pass the call from /debug/pprof/mutex to pprof
func MutexHandler() echo.HandlerFunc {
return func(ctx echo.Context) error {
pprof.Handler("mutex").ServeHTTP(ctx.Response().Writer, ctx.Request())
return nil
}
}
54 changes: 54 additions & 0 deletions pprof_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
package echopprof

import (
"strings"
"testing"

"github.com/labstack/echo"
)

func newServer() *echo.Echo {
e := echo.New()
return e
}

func checkRouters(routers []echo.Route, t *testing.T) {
expectedRouters := map[string]string{
"/debug/pprof/": "IndexHandler",
"/debug/pprof/heap": "HeapHandler",
"/debug/pprof/goroutine": "GoroutineHandler",
"/debug/pprof/block": "BlockHandler",
"/debug/pprof/threadcreate": "ThreadCreateHandler",
"/debug/pprof/cmdline": "CmdlineHandler",
"/debug/pprof/profile": "ProfileHandler",
"/debug/pprof/symbol": "SymbolHandler",
"/debug/pprof/trace": "TraceHandler",
"/debug/pprof/mutex": "MutexHandler",
}

for _, router := range routers {
//fmt.Println(router.Path, router.Method, router.Handler)
name, ok := expectedRouters[router.Path]
if !ok {
t.Errorf("missing router %s", router.Path)
}
if !strings.Contains(router.Handler, name) {
t.Errorf("handler for %s should contain %s, got %s", router.Path, name, router.Handler)
}
}
}

func TestWrap(t *testing.T) {
e := newServer()
Wrap(e)
checkRouters(e.Routes(), t)
}

func TestWrapGroup(t *testing.T) {
for _, prefix := range []string{"/debug", "/debug/", "/debug/pprof", "/debug/pprof/"} {
e := newServer()
g := e.Group(prefix)
WrapGroup(g)
checkRouters(e.Routes(), t)
}
}

0 comments on commit 3ba87e4

Please sign in to comment.