Skip to content

Commit

Permalink
[supervisor] allow to enable pprof
Browse files Browse the repository at this point in the history
  • Loading branch information
akosyakov committed Mar 19, 2021
1 parent a081891 commit 33d4df7
Show file tree
Hide file tree
Showing 6 changed files with 27 additions and 7 deletions.
2 changes: 2 additions & 0 deletions .werft/values.dev.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,8 @@ components:
env:
- name: THEIA_RATELIMIT_LOG
value: "50"
- name: SUPERVISOR_DEBUG_ENABLE
value: "true"
prebuild:
spec:
containers:
Expand Down
23 changes: 16 additions & 7 deletions components/common-go/pprof/pprof.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,14 +15,12 @@ import (
"github.com/gitpod-io/gitpod/common-go/log"
)

const Path = "/debug/pprof/"

// Serve starts a new HTTP server serving pprof endpoints on the given addr
func Serve(addr string) {
mux := http.NewServeMux()
mux.HandleFunc("/debug/pprof/", index)
mux.HandleFunc("/debug/pprof/cmdline", pprof.Cmdline)
mux.HandleFunc("/debug/pprof/profile", pprof.Profile)
mux.HandleFunc("/debug/pprof/symbol", pprof.Symbol)
mux.HandleFunc("/debug/pprof/trace", pprof.Trace)
mux.Handle(Path, Handler())

log.WithField("addr", addr).Info("serving pprof service")
err := http.ListenAndServe(addr, mux)
Expand All @@ -31,8 +29,19 @@ func Serve(addr string) {
}
}

// Handler produces the pprof endpoint handler
func Handler() http.Handler {
mux := http.NewServeMux()
mux.HandleFunc("/", index)
mux.HandleFunc("/cmdline", pprof.Cmdline)
mux.HandleFunc("/profile", pprof.Profile)
mux.HandleFunc("/symbol", pprof.Symbol)
mux.HandleFunc("/trace", pprof.Trace)
return mux
}

func index(w http.ResponseWriter, r *http.Request) {
if strings.HasPrefix(r.URL.Path, "/debug/pprof/") {
if strings.HasPrefix(r.URL.Path, Path) {
// according to Ian Lance Taylor it's ok to turn on mutex and block profiling
// when asking for the actual profile [1]. This handler implements this idea, as
// discussed in [2]
Expand All @@ -41,7 +50,7 @@ func index(w http.ResponseWriter, r *http.Request) {
// [2] /~https://github.com/golang/go/issues/23401

var (
name = strings.TrimPrefix(r.URL.Path, "/debug/pprof/")
name = strings.TrimPrefix(r.URL.Path, Path)
seconds, serr = strconv.ParseInt(r.URL.Query().Get("seconds"), 10, 64)
)
if name == "mutex" {
Expand Down
1 change: 1 addition & 0 deletions components/supervisor/go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ require (
github.com/golang/protobuf v1.4.3
github.com/google/go-cmp v0.5.4
github.com/google/uuid v1.1.4
github.com/grpc-ecosystem/go-grpc-middleware v1.2.2
github.com/grpc-ecosystem/grpc-gateway/v2 v2.2.0
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e // indirect
github.com/prometheus/procfs v0.0.8 // indirect
Expand Down
1 change: 1 addition & 0 deletions components/supervisor/go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -193,6 +193,7 @@ github.com/gorilla/websocket v1.4.1/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/ad
github.com/gorilla/websocket v1.4.2 h1:+/TMaTYc4QFitKJxsQ7Yye35DkWvkdLcvGKqM+x0Ufc=
github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
github.com/grpc-ecosystem/go-grpc-middleware v1.0.0/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs=
github.com/grpc-ecosystem/go-grpc-middleware v1.2.2 h1:FlFbCRLd5Jr4iYXZufAvgWN6Ao0JrI5chLINnUXDDr0=
github.com/grpc-ecosystem/go-grpc-middleware v1.2.2/go.mod h1:EaizFBKfUKtMIF5iaDEhniwNedqGo9FuLFzppDr3uwI=
github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk=
github.com/grpc-ecosystem/grpc-gateway v1.9.0 h1:bM6ZAFZmc/wPFaRDi0d5L7hGEZEx/2u+Tmr2evNHDiI=
Expand Down
3 changes: 3 additions & 0 deletions components/supervisor/pkg/supervisor/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -192,6 +192,9 @@ type WorkspaceConfig struct {

// GitpodHeadless controls whether the workspace is running headless
GitpodHeadless string `env:"GITPOD_HEADLESS"`

// DebugEnabled controls whether the supervisor debugging facilities (pprof, grpc tracing) shoudl be enabled
DebugEnable bool `env:"SUPERVISOR_DEBUG_ENABLE"`
}

// WorkspaceGitpodToken is a list of tokens that should be added to supervisor's token service
Expand Down
4 changes: 4 additions & 0 deletions components/supervisor/pkg/supervisor/supervisor.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ import (
"google.golang.org/grpc"

"github.com/gitpod-io/gitpod/common-go/log"
"github.com/gitpod-io/gitpod/common-go/pprof"
csapi "github.com/gitpod-io/gitpod/content-service/api"
"github.com/gitpod-io/gitpod/content-service/pkg/executor"
"github.com/gitpod-io/gitpod/content-service/pkg/initializer"
Expand Down Expand Up @@ -596,6 +597,9 @@ func startAPIEndpoint(ctx context.Context, cfg *Config, wg *sync.WaitGroup, serv
routes := http.NewServeMux()
routes.Handle("/_supervisor/v1/", http.StripPrefix("/_supervisor", restMux))
routes.Handle("/_supervisor/frontend", http.FileServer(http.Dir(cfg.FrontendLocation)))
if cfg.DebugEnable {
routes.Handle("/_supervisor"+pprof.Path, http.StripPrefix("/_supervisor", pprof.Handler()))
}
go http.Serve(httpMux, routes)

go m.Serve()
Expand Down

0 comments on commit 33d4df7

Please sign in to comment.