github.com/sagernet/sing-box@v1.9.0-rc.20/debug_http.go (about) 1 package box 2 3 import ( 4 "net/http" 5 "net/http/pprof" 6 "runtime" 7 "runtime/debug" 8 "strings" 9 10 "github.com/sagernet/sing-box/common/humanize" 11 "github.com/sagernet/sing-box/log" 12 "github.com/sagernet/sing-box/option" 13 E "github.com/sagernet/sing/common/exceptions" 14 "github.com/sagernet/sing/common/json" 15 "github.com/sagernet/sing/common/json/badjson" 16 17 "github.com/go-chi/chi/v5" 18 ) 19 20 var debugHTTPServer *http.Server 21 22 func applyDebugListenOption(options option.DebugOptions) { 23 if debugHTTPServer != nil { 24 debugHTTPServer.Close() 25 debugHTTPServer = nil 26 } 27 if options.Listen == "" { 28 return 29 } 30 r := chi.NewMux() 31 r.Route("/debug", func(r chi.Router) { 32 r.Get("/gc", func(writer http.ResponseWriter, request *http.Request) { 33 writer.WriteHeader(http.StatusNoContent) 34 go debug.FreeOSMemory() 35 }) 36 r.Get("/memory", func(writer http.ResponseWriter, request *http.Request) { 37 var memStats runtime.MemStats 38 runtime.ReadMemStats(&memStats) 39 40 var memObject badjson.JSONObject 41 memObject.Put("heap", humanize.MemoryBytes(memStats.HeapInuse)) 42 memObject.Put("stack", humanize.MemoryBytes(memStats.StackInuse)) 43 memObject.Put("idle", humanize.MemoryBytes(memStats.HeapIdle-memStats.HeapReleased)) 44 memObject.Put("goroutines", runtime.NumGoroutine()) 45 memObject.Put("rss", rusageMaxRSS()) 46 47 encoder := json.NewEncoder(writer) 48 encoder.SetIndent("", " ") 49 encoder.Encode(memObject) 50 }) 51 r.Route("/pprof", func(r chi.Router) { 52 r.HandleFunc("/", func(writer http.ResponseWriter, request *http.Request) { 53 if !strings.HasSuffix(request.URL.Path, "/") { 54 http.Redirect(writer, request, request.URL.Path+"/", http.StatusMovedPermanently) 55 } else { 56 pprof.Index(writer, request) 57 } 58 }) 59 r.HandleFunc("/*", pprof.Index) 60 r.HandleFunc("/cmdline", pprof.Cmdline) 61 r.HandleFunc("/profile", pprof.Profile) 62 r.HandleFunc("/symbol", pprof.Symbol) 63 r.HandleFunc("/trace", pprof.Trace) 64 }) 65 }) 66 debugHTTPServer = &http.Server{ 67 Addr: options.Listen, 68 Handler: r, 69 } 70 go func() { 71 err := debugHTTPServer.ListenAndServe() 72 if err != nil && !E.IsClosed(err) { 73 log.Error(E.Cause(err, "serve debug HTTP server")) 74 } 75 }() 76 }