Skip to content

Commit 3ba87e4

Browse files
committed
init
0 parents  commit 3ba87e4

File tree

4 files changed

+206
-0
lines changed

4 files changed

+206
-0
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
.idea/

example/example.go

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
package main
2+
3+
import (
4+
"github.com/labstack/echo"
5+
"github.com/sevenNt/echo-pprof"
6+
)
7+
8+
func main() {
9+
e := echo.New()
10+
11+
e.GET("/ping", func(c echo.Context) error {
12+
return c.String(200, "pong")
13+
})
14+
15+
// automatically add routers for net/http/pprof
16+
// e.g. /debug/pprof, /debug/pprof/heap, etc.
17+
echopprof.Wrap(e)
18+
19+
// echopprof also plays well with *gin.RouterGroup
20+
// group := e.Group("/debug/pprof")
21+
// echopprof.WrapGroup(group)
22+
23+
e.Start(":8080")
24+
}

pprof.go

Lines changed: 127 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,127 @@
1+
package echopprof
2+
3+
import (
4+
"net/http/pprof"
5+
"strings"
6+
7+
"github.com/labstack/echo"
8+
)
9+
10+
// Wrap adds several routes from package `net/http/pprof` to *gin.Engine object
11+
func Wrap(e *echo.Echo) {
12+
WrapGroup(e.Group(""))
13+
}
14+
15+
// Wrapper make sure we are backward compatible
16+
var Wrapper = Wrap
17+
18+
// WrapGroup adds several routes from package `net/http/pprof` to *gin.RouterGroup object
19+
func WrapGroup(g *echo.Group) {
20+
routers := []struct {
21+
Method string
22+
Path string
23+
Handler echo.HandlerFunc
24+
}{
25+
{"GET", "/debug/pprof/", IndexHandler()},
26+
{"GET", "/debug/pprof/heap", HeapHandler()},
27+
{"GET", "/debug/pprof/goroutine", GoroutineHandler()},
28+
{"GET", "/debug/pprof/block", BlockHandler()},
29+
{"GET", "/debug/pprof/threadcreate", ThreadCreateHandler()},
30+
{"GET", "/debug/pprof/cmdline", CmdlineHandler()},
31+
{"GET", "/debug/pprof/profile", ProfileHandler()},
32+
{"GET", "/debug/pprof/symbol", SymbolHandler()},
33+
{"POST", "/debug/pprof/symbol", SymbolHandler()},
34+
{"GET", "/debug/pprof/trace", TraceHandler()},
35+
{"GET", "/debug/pprof/mutex", MutexHandler()},
36+
}
37+
38+
prefix := ""
39+
for _, r := range routers {
40+
switch r.Method {
41+
case "GET":
42+
g.GET(strings.TrimPrefix(r.Path, prefix), r.Handler)
43+
case "POST":
44+
g.POST(strings.TrimPrefix(r.Path, prefix), r.Handler)
45+
}
46+
}
47+
}
48+
49+
// IndexHandler will pass the call from /debug/pprof to pprof
50+
func IndexHandler() echo.HandlerFunc {
51+
return func(ctx echo.Context) error {
52+
pprof.Index(ctx.Response().Writer, ctx.Request())
53+
return nil
54+
}
55+
}
56+
57+
// HeapHandler will pass the call from /debug/pprof/heap to pprof
58+
func HeapHandler() echo.HandlerFunc {
59+
return func(ctx echo.Context) error {
60+
pprof.Handler("heap").ServeHTTP(ctx.Response(), ctx.Request())
61+
return nil
62+
}
63+
}
64+
65+
// GoroutineHandler will pass the call from /debug/pprof/goroutine to pprof
66+
func GoroutineHandler() echo.HandlerFunc {
67+
return func(ctx echo.Context) error {
68+
pprof.Handler("goroutine").ServeHTTP(ctx.Response().Writer, ctx.Request())
69+
return nil
70+
}
71+
}
72+
73+
// BlockHandler will pass the call from /debug/pprof/block to pprof
74+
func BlockHandler() echo.HandlerFunc {
75+
return func(ctx echo.Context) error {
76+
pprof.Handler("block").ServeHTTP(ctx.Response().Writer, ctx.Request())
77+
return nil
78+
}
79+
}
80+
81+
// ThreadCreateHandler will pass the call from /debug/pprof/threadcreate to pprof
82+
func ThreadCreateHandler() echo.HandlerFunc {
83+
return func(ctx echo.Context) error {
84+
pprof.Handler("threadcreate").ServeHTTP(ctx.Response().Writer, ctx.Request())
85+
return nil
86+
}
87+
}
88+
89+
// CmdlineHandler will pass the call from /debug/pprof/cmdline to pprof
90+
func CmdlineHandler() echo.HandlerFunc {
91+
return func(ctx echo.Context) error {
92+
pprof.Cmdline(ctx.Response().Writer, ctx.Request())
93+
return nil
94+
}
95+
}
96+
97+
// ProfileHandler will pass the call from /debug/pprof/profile to pprof
98+
func ProfileHandler() echo.HandlerFunc {
99+
return func(ctx echo.Context) error {
100+
pprof.Profile(ctx.Response().Writer, ctx.Request())
101+
return nil
102+
}
103+
}
104+
105+
// SymbolHandler will pass the call from /debug/pprof/symbol to pprof
106+
func SymbolHandler() echo.HandlerFunc {
107+
return func(ctx echo.Context) error {
108+
pprof.Symbol(ctx.Response().Writer, ctx.Request())
109+
return nil
110+
}
111+
}
112+
113+
// TraceHandler will pass the call from /debug/pprof/trace to pprof
114+
func TraceHandler() echo.HandlerFunc {
115+
return func(ctx echo.Context) error {
116+
pprof.Trace(ctx.Response().Writer, ctx.Request())
117+
return nil
118+
}
119+
}
120+
121+
// MutexHandler will pass the call from /debug/pprof/mutex to pprof
122+
func MutexHandler() echo.HandlerFunc {
123+
return func(ctx echo.Context) error {
124+
pprof.Handler("mutex").ServeHTTP(ctx.Response().Writer, ctx.Request())
125+
return nil
126+
}
127+
}

pprof_test.go

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
package echopprof
2+
3+
import (
4+
"strings"
5+
"testing"
6+
7+
"github.com/labstack/echo"
8+
)
9+
10+
func newServer() *echo.Echo {
11+
e := echo.New()
12+
return e
13+
}
14+
15+
func checkRouters(routers []echo.Route, t *testing.T) {
16+
expectedRouters := map[string]string{
17+
"/debug/pprof/": "IndexHandler",
18+
"/debug/pprof/heap": "HeapHandler",
19+
"/debug/pprof/goroutine": "GoroutineHandler",
20+
"/debug/pprof/block": "BlockHandler",
21+
"/debug/pprof/threadcreate": "ThreadCreateHandler",
22+
"/debug/pprof/cmdline": "CmdlineHandler",
23+
"/debug/pprof/profile": "ProfileHandler",
24+
"/debug/pprof/symbol": "SymbolHandler",
25+
"/debug/pprof/trace": "TraceHandler",
26+
"/debug/pprof/mutex": "MutexHandler",
27+
}
28+
29+
for _, router := range routers {
30+
//fmt.Println(router.Path, router.Method, router.Handler)
31+
name, ok := expectedRouters[router.Path]
32+
if !ok {
33+
t.Errorf("missing router %s", router.Path)
34+
}
35+
if !strings.Contains(router.Handler, name) {
36+
t.Errorf("handler for %s should contain %s, got %s", router.Path, name, router.Handler)
37+
}
38+
}
39+
}
40+
41+
func TestWrap(t *testing.T) {
42+
e := newServer()
43+
Wrap(e)
44+
checkRouters(e.Routes(), t)
45+
}
46+
47+
func TestWrapGroup(t *testing.T) {
48+
for _, prefix := range []string{"/debug", "/debug/", "/debug/pprof", "/debug/pprof/"} {
49+
e := newServer()
50+
g := e.Group(prefix)
51+
WrapGroup(g)
52+
checkRouters(e.Routes(), t)
53+
}
54+
}

0 commit comments

Comments
 (0)