/
pprof.go
149 lines (135 loc) · 3.75 KB
/
pprof.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
package core
import (
"context"
"fmt"
"net/http"
"os"
"strconv"
"net/http/pprof"
"github.com/fluffy-bunny/grpcdotnetgo/pkg/utils"
"github.com/labstack/echo/v4"
"github.com/labstack/gommon/log"
zlog "github.com/rs/zerolog/log"
"github.com/reugn/async"
)
// PProfServer is the PProfServer object that manages an echo web server
type PProfServer struct {
waitChannel chan os.Signal
future async.Future[string]
e *echo.Echo
}
// NewPProfServer creates a new PProf object
func NewPProfServer() *PProfServer {
return &PProfServer{
waitChannel: make(chan os.Signal),
}
}
// Stop ...
func (s *PProfServer) Stop() {
if s.future == nil {
return
}
zlog.Info().Msg("Stopping PProf Web Server")
if err := s.e.Shutdown(context.Background()); err != nil {
s.e.Logger.Error(err)
}
s.future.Join()
zlog.Info().Msg("PProf Web Server stopped")
}
// Start starts the echo web server using async and futures
func (s *PProfServer) Start() {
pprofPort := os.Getenv("PPROF_PORT")
if len(pprofPort) != 0 {
// convert to int
port, err := strconv.Atoi(pprofPort)
if err != nil {
zlog.Fatal().Err(err).Msg("Failed to convert pprof port to int")
}
s.e = echo.New()
e := s.e
e.Logger.SetLevel(log.DEBUG)
e.GET("/", func(c echo.Context) error {
return c.String(http.StatusOK, "Hello from PProf")
})
e.Any("/debug/pprof/", func(c echo.Context) error {
// call pprof index
pprof.Index(c.Response().Writer, c.Request())
return nil
})
// call pprof heap
e.Any("/debug/pprof/heap", func(c echo.Context) error {
// call pprof index specifying the gc
pprof.Handler("heap").ServeHTTP(c.Response().Writer, c.Request())
return nil
})
// call pprof cmdline
e.Any("/debug/pprof/cmdline", func(c echo.Context) error {
// call pprof index
pprof.Cmdline(c.Response().Writer, c.Request())
return nil
})
// call pprof profile
e.Any("/debug/pprof/profile", func(c echo.Context) error {
// call pprof index
pprof.Profile(c.Response().Writer, c.Request())
return nil
})
// call pprof symbol
e.Any("/debug/pprof/symbol", func(c echo.Context) error {
// call pprof index
pprof.Symbol(c.Response().Writer, c.Request())
return nil
})
// call pprof trace
e.Any("/debug/pprof/trace", func(c echo.Context) error {
// call pprof index
pprof.Trace(c.Response().Writer, c.Request())
return nil
})
// call pprof goroutine
e.Any("/debug/pprof/goroutine", func(c echo.Context) error {
// call pprof index
pprof.Handler("goroutine").ServeHTTP(c.Response().Writer, c.Request())
return nil
})
// call pprof threadcreate
e.Any("/debug/pprof/threadcreate", func(c echo.Context) error {
// call pprof index
pprof.Handler("threadcreate").ServeHTTP(c.Response().Writer, c.Request())
return nil
})
// call pprof block
e.Any("/debug/pprof/block", func(c echo.Context) error {
// call pprof index
pprof.Handler("block").ServeHTTP(c.Response().Writer, c.Request())
return nil
})
// call pprof mutex
e.Any("/debug/pprof/mutex", func(c echo.Context) error {
// call pprof index
pprof.Handler("mutex").ServeHTTP(c.Response().Writer, c.Request())
return nil
})
// call pprof allocs
e.Any("/debug/pprof/allocs", func(c echo.Context) error {
// call pprof index
pprof.Handler("allocs").ServeHTTP(c.Response().Writer, c.Request())
return nil
})
asyncAction := func() async.Future[string] {
promise := async.NewPromise[string]()
go func() {
port := fmt.Sprintf(":%d", port)
if err := e.Start(port); err != nil {
e.Logger.Info("shutting down the server")
promise.Success(utils.Ptr("OK"))
} else {
promise.Failure(err)
}
}()
return promise.Future()
}
s.future = asyncAction()
zlog.Info().Msg("Starting PProf Web Server")
}
}