Skip to content

Commit

Permalink
feat: add /debug/pprof handlers (#1976)
Browse files Browse the repository at this point in the history
This adds debugging pprof HTTP handlers.

The controller serves this directly, while the runner forwards to the
user verb server's handlers, allowing verb servers to be debugged
directly.

Here's an example of CPU profiling the echo module:

```
🐚 ~/dev/ftl $ go tool pprof http://localhost:8894/debug/pprof/profile
Fetching profile over HTTP from http://localhost:8894/debug/pprof/profile
Saved profile in /Users/alec/pprof/pprof.main.samples.cpu.001.pb.gz
File: main
Type: cpu
Time: Jul 5, 2024 at 5:33am (AEST)
Duration: 30.18s, Total samples = 600ms ( 1.99%)
Entering interactive mode (type "help" for commands, "o" for options)
(pprof) top10
Showing nodes accounting for 600ms, 100% of 600ms total
Showing top 10 nodes out of 73
      flat  flat%   sum%        cum   cum%
     210ms 35.00% 35.00%      210ms 35.00%  runtime.pthread_cond_signal
     190ms 31.67% 66.67%      190ms 31.67%  runtime.kevent
     110ms 18.33% 85.00%      110ms 18.33%  runtime.pthread_cond_wait
      50ms  8.33% 93.33%       50ms  8.33%  syscall.syscall
      10ms  1.67% 95.00%       10ms  1.67%  connectrpc.com/connect.grpcErrorToTrailer
      10ms  1.67% 96.67%       10ms  1.67%  runtime.scanobject
      10ms  1.67% 98.33%       10ms  1.67%  runtime.usleep
      10ms  1.67%   100%       10ms  1.67%  runtime.write1
         0     0%   100%       30ms  5.00%  bufio.(*Writer).Flush
         0     0%   100%       10ms  1.67%  connectrpc.com/connect.(*Handler).ServeHTTP
```

pprof index looks like this:

<img width="967" alt="image"
src="https://github.com/TBD54566975/ftl/assets/41767/90675d6e-edd7-495e-8b6c-2ee1e299f743">
  • Loading branch information
alecthomas authored Jul 4, 2024
1 parent 27a844d commit 43a3b1e
Show file tree
Hide file tree
Showing 5 changed files with 50 additions and 0 deletions.
1 change: 1 addition & 0 deletions backend/controller/controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,7 @@ func Start(ctx context.Context, config Config, runnerScaling scaling.RunnerScali
rpc.GRPC(ftlv1connect.NewAdminServiceHandler, admin),
rpc.GRPC(pbconsoleconnect.NewConsoleServiceHandler, console),
rpc.HTTP("/", consoleHandler),
rpc.PProf(),
)
})

Expand Down
14 changes: 14 additions & 0 deletions backend/runner/runner.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ import (
"errors"
"fmt"
"math/rand"
"net/http"
"net/http/httputil"
"net/url"
"os"
"path/filepath"
Expand Down Expand Up @@ -108,6 +110,7 @@ func Start(ctx context.Context, config Config) error {
return rpc.Serve(ctx, config.Bind,
rpc.GRPC(ftlv1connect.NewVerbServiceHandler, svc),
rpc.GRPC(ftlv1connect.NewRunnerServiceHandler, svc),
rpc.HTTP("/", svc),
)
}

Expand Down Expand Up @@ -353,6 +356,17 @@ func (s *Service) Terminate(ctx context.Context, c *connect.Request[ftlv1.Termin
}), nil
}

func (s *Service) ServeHTTP(w http.ResponseWriter, r *http.Request) {
deployment, ok := s.deployment.Load().Get()
if !ok {
http.Error(w, "no deployment", http.StatusNotFound)
return
}
proxy := httputil.NewSingleHostReverseProxy(deployment.plugin.Endpoint)
proxy.ServeHTTP(w, r)

}

func (s *Service) makeDeployment(ctx context.Context, key model.DeploymentKey, plugin *plugin.Plugin[ftlv1connect.VerbServiceClient]) *deployment {
return &deployment{
ctx: ctx,
Expand Down
2 changes: 2 additions & 0 deletions common/plugin/serve.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import (
"golang.org/x/net/http2/h2c"

_ "github.com/TBD54566975/ftl/internal/automaxprocs" // Set GOMAXPROCS to match Linux container CPU quota.
ftlhttp "github.com/TBD54566975/ftl/internal/http"
"github.com/TBD54566975/ftl/internal/log"
"github.com/TBD54566975/ftl/internal/rpc"
)
Expand Down Expand Up @@ -154,6 +155,7 @@ func Start[Impl any, Iface any, Config any](
reflector := grpcreflect.NewStaticReflector(servicePaths...)
mux.Handle(grpcreflect.NewHandlerV1(reflector))
mux.Handle(grpcreflect.NewHandlerV1Alpha(reflector))
ftlhttp.RegisterPprof(mux)

// Start the server.
http1Server := &http.Server{
Expand Down
24 changes: 24 additions & 0 deletions internal/http/pprof.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package http

import (
"net/http"
"net/http/pprof"
)

// RegisterPprof registers all pprof handlers and the index on the provided ServeMux.
func RegisterPprof(mux *http.ServeMux) {
mux.HandleFunc("/debug/pprof", func(w http.ResponseWriter, r *http.Request) {
http.Redirect(w, r, "/debug/pprof/", http.StatusFound)
})
mux.HandleFunc("/debug/pprof/", 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("/debug/pprof/goroutine", pprof.Handler("goroutine"))
mux.Handle("/debug/pprof/heap", pprof.Handler("heap"))
mux.Handle("/debug/pprof/allocs", pprof.Handler("allocs"))
mux.Handle("/debug/pprof/threadcreate", pprof.Handler("threadcreate"))
mux.Handle("/debug/pprof/block", pprof.Handler("block"))
mux.Handle("/debug/pprof/mutex", pprof.Handler("mutex"))
}
9 changes: 9 additions & 0 deletions internal/rpc/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ import (
"strings"
"time"

gaphttp "github.com/TBD54566975/ftl/internal/http"

"connectrpc.com/connect"
"connectrpc.com/grpcreflect"
"github.com/alecthomas/concurrency"
Expand Down Expand Up @@ -40,6 +42,13 @@ func GRPC[Iface, Impl Pingable](constructor GRPCServerConstructor[Iface], impl I
}
}

// PProf adds /debug/pprof routes to the server.
func PProf() Option {
return func(so *serverOptions) {
gaphttp.RegisterPprof(so.mux)
}
}

// RawGRPC is a convenience function for registering a GRPC server with default options without Pingable.
func RawGRPC[Iface, Impl any](constructor RawGRPCServerConstructor[Iface], impl Impl, options ...connect.HandlerOption) Option {
return func(o *serverOptions) {
Expand Down

0 comments on commit 43a3b1e

Please sign in to comment.