package goroutineinstance import ( "encoding/json" "flag" "log" "net/http" "path" "sync" "github.com/DataDog/gostackparse" "github.com/go-chi/chi/v5" "github.com/go-chi/chi/v5/middleware" "github.com/rs/xid" ) type Instance struct { id xid.ID dat []*gostackparse.Goroutine mu sync.RWMutex once sync.Once handler http.Handler } func (i *Instance) Id() xid.ID { return i.id } func (i *Instance) ServeHTTP(tw http.ResponseWriter, tr *http.Request) { i.once.Do(func() { r := chi.NewRouter() r.Use(middleware.StripSlashes) r.Get("/", func(w http.ResponseWriter, r *http.Request) { http.Redirect(w, r, path.Join(r.URL.Path, "app"), http.StatusSeeOther) }) r.Get("/app", func(w http.ResponseWriter, r *http.Request) { w.Write(IndexHtmlEmbed) }) r.Get("/raw", func(w http.ResponseWriter, r *http.Request) { json.NewEncoder(w).Encode(i.dat) }) i.handler = r }) log.Printf("serve goroutine instance %s %s", i.id, tr.URL.String()) i.handler.ServeHTTP(tw, tr) } // Mostly copied from https://github.com/google/pprof/blob/master/internal/driver/flags.go type pprofFlags struct { args []string s flag.FlagSet usage []string }