Browse Source

Add debug http server

世界 2 years ago
parent
commit
e056d4502b
7 changed files with 73 additions and 49 deletions
  1. 0 44
      cmd/sing-box/debug.go
  2. 1 0
      debug_go118.go
  3. 1 0
      debug_go119.go
  4. 67 0
      debug_http.go
  5. 1 3
      debug_linux.go
  6. 2 2
      debug_stub.go
  7. 1 0
      option/debug.go

+ 0 - 44
cmd/sing-box/debug.go

@@ -1,44 +0,0 @@
-//go:build debug
-
-package main
-
-import (
-	"encoding/json"
-	"net/http"
-	_ "net/http/pprof"
-	"runtime"
-	"runtime/debug"
-
-	"github.com/sagernet/sing-box/common/badjson"
-	"github.com/sagernet/sing-box/log"
-
-	"github.com/dustin/go-humanize"
-)
-
-func init() {
-	http.HandleFunc("/debug/gc", func(writer http.ResponseWriter, request *http.Request) {
-		writer.WriteHeader(http.StatusNoContent)
-		go debug.FreeOSMemory()
-	})
-	http.HandleFunc("/debug/memory", func(writer http.ResponseWriter, request *http.Request) {
-		var memStats runtime.MemStats
-		runtime.ReadMemStats(&memStats)
-
-		var memObject badjson.JSONObject
-		memObject.Put("heap", humanize.IBytes(memStats.HeapInuse))
-		memObject.Put("stack", humanize.IBytes(memStats.StackInuse))
-		memObject.Put("idle", humanize.IBytes(memStats.HeapIdle-memStats.HeapReleased))
-		memObject.Put("goroutines", runtime.NumGoroutine())
-		memObject.Put("rss", rusageMaxRSS())
-
-		encoder := json.NewEncoder(writer)
-		encoder.SetIndent("", "  ")
-		encoder.Encode(memObject)
-	})
-	go func() {
-		err := http.ListenAndServe("0.0.0.0:8964", nil)
-		if err != nil {
-			log.Debug(err)
-		}
-	}()
-}

+ 1 - 0
debug_go118.go

@@ -10,6 +10,7 @@ import (
 )
 
 func applyDebugOptions(options option.DebugOptions) {
+	applyDebugListenOption(options)
 	if options.GCPercent != nil {
 		debug.SetGCPercent(*options.GCPercent)
 	}

+ 1 - 0
debug.go → debug_go119.go

@@ -10,6 +10,7 @@ import (
 )
 
 func applyDebugOptions(options option.DebugOptions) {
+	applyDebugListenOption(options)
 	if options.GCPercent != nil {
 		debug.SetGCPercent(*options.GCPercent)
 	}

+ 67 - 0
debug_http.go

@@ -0,0 +1,67 @@
+package box
+
+import (
+	"net/http"
+	"net/http/pprof"
+	"runtime"
+	"runtime/debug"
+
+	"github.com/sagernet/sing-box/common/badjson"
+	"github.com/sagernet/sing-box/common/json"
+	"github.com/sagernet/sing-box/log"
+	"github.com/sagernet/sing-box/option"
+	E "github.com/sagernet/sing/common/exceptions"
+
+	"github.com/dustin/go-humanize"
+	"github.com/go-chi/chi/v5"
+)
+
+var debugHTTPServer *http.Server
+
+func applyDebugListenOption(options option.DebugOptions) {
+	if debugHTTPServer != nil {
+		debugHTTPServer.Close()
+		debugHTTPServer = nil
+	}
+	if options.Listen == "" {
+		return
+	}
+	r := chi.NewMux()
+	r.Route("/debug", func(r chi.Router) {
+		r.Get("/gc", func(writer http.ResponseWriter, request *http.Request) {
+			writer.WriteHeader(http.StatusNoContent)
+			go debug.FreeOSMemory()
+		})
+		r.Get("/memory", func(writer http.ResponseWriter, request *http.Request) {
+			var memStats runtime.MemStats
+			runtime.ReadMemStats(&memStats)
+
+			var memObject badjson.JSONObject
+			memObject.Put("heap", humanize.IBytes(memStats.HeapInuse))
+			memObject.Put("stack", humanize.IBytes(memStats.StackInuse))
+			memObject.Put("idle", humanize.IBytes(memStats.HeapIdle-memStats.HeapReleased))
+			memObject.Put("goroutines", runtime.NumGoroutine())
+			memObject.Put("rss", rusageMaxRSS())
+
+			encoder := json.NewEncoder(writer)
+			encoder.SetIndent("", "  ")
+			encoder.Encode(memObject)
+		})
+		r.HandleFunc("/pprof", pprof.Index)
+		r.HandleFunc("/pprof/*", pprof.Index)
+		r.HandleFunc("/pprof/cmdline", pprof.Cmdline)
+		r.HandleFunc("/pprof/profile", pprof.Profile)
+		r.HandleFunc("/pprof/symbol", pprof.Symbol)
+		r.HandleFunc("/pprof/trace", pprof.Trace)
+	})
+	debugHTTPServer = &http.Server{
+		Addr:    options.Listen,
+		Handler: r,
+	}
+	go func() {
+		err := debugHTTPServer.ListenAndServe()
+		if err != nil && !E.IsClosed(err) {
+			log.Error(E.Cause(err, "serve debug HTTP server"))
+		}
+	}()
+}

+ 1 - 3
cmd/sing-box/debug_linux.go → debug_linux.go

@@ -1,6 +1,4 @@
-//go:build debug
-
-package main
+package box
 
 import (
 	"runtime"

+ 2 - 2
cmd/sing-box/debug_stub.go → debug_stub.go

@@ -1,6 +1,6 @@
-//go:build debug && !linux
+//go:build !linux
 
-package main
+package box
 
 func rusageMaxRSS() float64 {
 	return -1

+ 1 - 0
option/debug.go

@@ -7,6 +7,7 @@ import (
 )
 
 type DebugOptions struct {
+	Listen       string      `json:"listen,omitempty"`
 	GCPercent    *int        `json:"gc_percent,omitempty"`
 	MaxStack     *int        `json:"max_stack,omitempty"`
 	MaxThreads   *int        `json:"max_threads,omitempty"`