debug_http.go 1.9 KB

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