aboutsummaryrefslogtreecommitdiff
path: root/web/server.go
diff options
context:
space:
mode:
Diffstat (limited to 'web/server.go')
-rw-r--r--web/server.go51
1 files changed, 43 insertions, 8 deletions
diff --git a/web/server.go b/web/server.go
index 198cb44..26dbb06 100644
--- a/web/server.go
+++ b/web/server.go
@@ -1,8 +1,11 @@
package web
import (
+ "context"
"database/sql"
"net/http"
+ http_pprof "net/http/pprof"
+ runtime_pprof "runtime/pprof"
"sync"
"time"
@@ -21,6 +24,7 @@ type Server struct {
returnToURL string
syncMu sync.Mutex
syncActive bool
+ enablePprof bool
}
type syncClient interface {
@@ -32,20 +36,51 @@ func NewServer(db *sql.DB, configPath string) *Server {
return &Server{db: db, configPath: configPath}
}
+func (s *Server) WithPprof(enabled bool) *Server {
+ s.enablePprof = enabled
+ return s
+}
+
func (s *Server) Handler() http.Handler {
mux := http.NewServeMux()
mux.Handle("GET /static/", http.FileServer(http.FS(staticFiles)))
- mux.HandleFunc("GET /", s.handleRides)
- mux.HandleFunc("GET /rides/{id}", s.handleRide)
- mux.HandleFunc("GET /analytics", s.handleAnalytics)
- mux.HandleFunc("POST /rides/{id}/official-climbs", s.handleCreateOfficialClimb)
- mux.HandleFunc("GET /sync", s.handleSyncForm)
- mux.HandleFunc("POST /sync", s.handleSync)
- mux.HandleFunc("GET /strava/login", s.handleStravaLogin)
- mux.HandleFunc("GET /strava/callback", s.handleStravaCallback)
+ handleRoute(mux, "GET /", s.handleRides)
+ handleRoute(mux, "GET /rides/{id}", s.handleRide)
+ handleRoute(mux, "GET /analytics", s.handleAnalytics)
+ handleRoute(mux, "POST /rides/{id}/official-climbs", s.handleCreateOfficialClimb)
+ handleRoute(mux, "GET /sync", s.handleSyncForm)
+ handleRoute(mux, "POST /sync", s.handleSync)
+ handleRoute(mux, "GET /strava/login", s.handleStravaLogin)
+ handleRoute(mux, "GET /strava/callback", s.handleStravaCallback)
+ if s.enablePprof {
+ registerPprof(mux)
+ }
return kcore.RecoverMiddleware(mux)
}
+func handleRoute(mux *http.ServeMux, pattern string, handler http.HandlerFunc) {
+ mux.HandleFunc(pattern, withPprofLabel(pattern, handler))
+}
+
+func withPprofLabel(route string, next http.HandlerFunc) http.HandlerFunc {
+ return func(w http.ResponseWriter, r *http.Request) {
+ runtime_pprof.Do(r.Context(), runtime_pprof.Labels("route", route), func(ctx context.Context) {
+ next(w, r.WithContext(ctx))
+ })
+ }
+}
+
+func registerPprof(mux *http.ServeMux) {
+ mux.HandleFunc("GET /debug/pprof/", http_pprof.Index)
+ mux.HandleFunc("GET /debug/pprof/cmdline", http_pprof.Cmdline)
+ mux.HandleFunc("GET /debug/pprof/profile", http_pprof.Profile)
+ mux.HandleFunc("GET /debug/pprof/symbol", http_pprof.Symbol)
+ mux.HandleFunc("GET /debug/pprof/trace", http_pprof.Trace)
+ for _, name := range []string{"allocs", "block", "goroutine", "heap", "mutex", "threadcreate"} {
+ mux.Handle("GET /debug/pprof/"+name, http_pprof.Handler(name))
+ }
+}
+
func (s *Server) ListenAndServe(addr string) error {
return http.ListenAndServe(addr, s.Handler())
}