mirror of
https://github.com/SagerNet/sing-box.git
synced 2024-11-24 17:41:29 +00:00
Add debug http server
This commit is contained in:
parent
98c2c439aa
commit
e056d4502b
|
@ -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)
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
}
|
|
|
@ -10,6 +10,7 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
func applyDebugOptions(options option.DebugOptions) {
|
func applyDebugOptions(options option.DebugOptions) {
|
||||||
|
applyDebugListenOption(options)
|
||||||
if options.GCPercent != nil {
|
if options.GCPercent != nil {
|
||||||
debug.SetGCPercent(*options.GCPercent)
|
debug.SetGCPercent(*options.GCPercent)
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,6 +10,7 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
func applyDebugOptions(options option.DebugOptions) {
|
func applyDebugOptions(options option.DebugOptions) {
|
||||||
|
applyDebugListenOption(options)
|
||||||
if options.GCPercent != nil {
|
if options.GCPercent != nil {
|
||||||
debug.SetGCPercent(*options.GCPercent)
|
debug.SetGCPercent(*options.GCPercent)
|
||||||
}
|
}
|
67
debug_http.go
Normal file
67
debug_http.go
Normal file
|
@ -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,6 +1,4 @@
|
||||||
//go:build debug
|
package box
|
||||||
|
|
||||||
package main
|
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"runtime"
|
"runtime"
|
|
@ -1,6 +1,6 @@
|
||||||
//go:build debug && !linux
|
//go:build !linux
|
||||||
|
|
||||||
package main
|
package box
|
||||||
|
|
||||||
func rusageMaxRSS() float64 {
|
func rusageMaxRSS() float64 {
|
||||||
return -1
|
return -1
|
|
@ -7,6 +7,7 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
type DebugOptions struct {
|
type DebugOptions struct {
|
||||||
|
Listen string `json:"listen,omitempty"`
|
||||||
GCPercent *int `json:"gc_percent,omitempty"`
|
GCPercent *int `json:"gc_percent,omitempty"`
|
||||||
MaxStack *int `json:"max_stack,omitempty"`
|
MaxStack *int `json:"max_stack,omitempty"`
|
||||||
MaxThreads *int `json:"max_threads,omitempty"`
|
MaxThreads *int `json:"max_threads,omitempty"`
|
||||||
|
|
Loading…
Reference in a new issue