diff --git a/box.go b/box.go index 434f0655..2488e7db 100644 --- a/box.go +++ b/box.go @@ -48,7 +48,7 @@ func New(options Options) (*Box, error) { } createdAt := time.Now() experimentalOptions := common.PtrValueOrDefault(options.Experimental) - applyDebugOptions(common.PtrValueOrDefault(experimentalOptions.Debug)) + applyDebugOptions(ctx, common.PtrValueOrDefault(experimentalOptions.Debug)) var needClashAPI bool var needV2RayAPI bool if experimentalOptions.ClashAPI != nil && experimentalOptions.ClashAPI.ExternalController != "" { diff --git a/debug.go b/debug.go index b6197420..b3ec84be 100644 --- a/debug.go +++ b/debug.go @@ -3,13 +3,15 @@ package box import ( + "context" + "github.com/sagernet/sing-box/experimental/pprof" "runtime/debug" "github.com/sagernet/sing-box/common/dialer/conntrack" "github.com/sagernet/sing-box/option" ) -func applyDebugOptions(options option.DebugOptions) { +func applyDebugOptions(ctx context.Context, options option.DebugOptions) { if options.GCPercent != nil { debug.SetGCPercent(*options.GCPercent) } @@ -32,4 +34,7 @@ func applyDebugOptions(options option.DebugOptions) { if options.OOMKiller != nil { conntrack.KillerEnabled = *options.OOMKiller } + if options.Pprof != "" { + pprof.NewPprof(ctx, options.Pprof) + } } diff --git a/debug_go118.go b/debug_go118.go index 88fdc05e..e97b10bf 100644 --- a/debug_go118.go +++ b/debug_go118.go @@ -3,13 +3,15 @@ package box import ( + "context" + "github.com/sagernet/sing-box/experimental/pprof" "runtime/debug" "github.com/sagernet/sing-box/common/dialer/conntrack" "github.com/sagernet/sing-box/option" ) -func applyDebugOptions(options option.DebugOptions) { +func applyDebugOptions(ctx context.Context, options option.DebugOptions) { if options.GCPercent != nil { debug.SetGCPercent(*options.GCPercent) } @@ -32,4 +34,7 @@ func applyDebugOptions(options option.DebugOptions) { if options.OOMKiller != nil { conntrack.KillerEnabled = *options.OOMKiller } + if options.Pprof != "" { + pprof.NewPprof(ctx, options.Pprof) + } } diff --git a/experimental/pprof/pprof.go b/experimental/pprof/pprof.go new file mode 100644 index 00000000..3beb77ef --- /dev/null +++ b/experimental/pprof/pprof.go @@ -0,0 +1,34 @@ +package pprof + +import ( + "context" + "github.com/sagernet/sing-box/log" + "net/http" + "net/http/pprof" +) + +func NewPprof(ctx context.Context, listen string) { + server := &http.Server{} + serverMux := http.NewServeMux() + + serverMux.HandleFunc("/debug/pprof/", pprof.Index) + serverMux.HandleFunc("/debug/pprof/cmdline", pprof.Cmdline) + serverMux.HandleFunc("/debug/pprof/profile", pprof.Profile) + serverMux.HandleFunc("/debug/pprof/symbol", pprof.Symbol) + serverMux.HandleFunc("/debug/pprof/trace", pprof.Trace) + + server.Handler = serverMux + server.Addr = listen + + go func() { + <-ctx.Done() + server.Shutdown(context.Background()) + }() + + go func() { + err := server.ListenAndServe() + if err != nil && err != http.ErrServerClosed { + log.Fatal("pprof server fail: ", err) + } + }() +} diff --git a/option/debug.go b/option/debug.go index 78318c23..aac41ff3 100644 --- a/option/debug.go +++ b/option/debug.go @@ -14,6 +14,7 @@ type DebugOptions struct { TraceBack string `json:"trace_back,omitempty"` MemoryLimit BytesLength `json:"memory_limit,omitempty"` OOMKiller *bool `json:"oom_killer,omitempty"` + Pprof string `json:"pprof,omitempty"` } type BytesLength int64