Repository: fatedier/frp (language: go)

Issue:
support go pprof in HTTP server



Discussion / hints:

Fix patch:
diff --git a/client/admin.go b/client/admin.go
index fff169f82b6..6a6ceecb7c4 100644
--- a/client/admin.go
+++ b/client/admin.go
@@ -17,6 +17,7 @@ package client
 import (
 	"net"
 	"net/http"
+	"net/http/pprof"
 	"time"
 
 	"github.com/fatedier/frp/assets"
@@ -26,8 +27,8 @@ import (
 )
 
 var (
-	httpServerReadTimeout  = 10 * time.Second
-	httpServerWriteTimeout = 10 * time.Second
+	httpServerReadTimeout  = 60 * time.Second
+	httpServerWriteTimeout = 60 * time.Second
 )
 
 func (svr *Service) RunAdminServer(address string) (err error) {
@@ -36,6 +37,15 @@ func (svr *Service) RunAdminServer(address string) (err error) {
 
 	router.HandleFunc("/healthz", svr.healthz)
 
+	// debug
+	if svr.cfg.PprofEnable {
+		router.HandleFunc("/debug/pprof/cmdline", pprof.Cmdline)
+		router.HandleFunc("/debug/pprof/profile", pprof.Profile)
+		router.HandleFunc("/debug/pprof/symbol", pprof.Symbol)
+		router.HandleFunc("/debug/pprof/trace", pprof.Trace)
+		router.PathPrefix("/debug/pprof/").HandlerFunc(pprof.Index)
+	}
+
 	subRouter := router.NewRoute().Subrouter()
 	user, passwd := svr.cfg.AdminUser, svr.cfg.AdminPwd
 	subRouter.Use(frpNet.NewHTTPAuthMiddleware(user, passwd).Middleware)
diff --git a/conf/frpc_full.ini b/conf/frpc_full.ini
index 58aefde8144..04ede862969 100644
--- a/conf/frpc_full.ini
+++ b/conf/frpc_full.ini
@@ -126,6 +126,10 @@ udp_packet_size = 1500
 # If DisableCustomTLSFirstByte is true, frpc will not send that custom byte.
 disable_custom_tls_first_byte = false
 
+# Enable golang pprof handlers in admin listener.
+# Admin port must be set first.
+pprof_enable = false
+
 # 'ssh' is the unique proxy name
 # if user in [common] section is not empty, it will be changed to {user}.{proxy} such as 'your_name.ssh'
 [ssh]
diff --git a/conf/frps_full.ini b/conf/frps_full.ini
index 4aef9774d55..e32d37ec4b0 100644
--- a/conf/frps_full.ini
+++ b/conf/frps_full.ini
@@ -133,6 +133,10 @@ tcp_mux = true
 # It affects the udp and sudp proxy.
 udp_packet_size = 1500
 
+# Enable golang pprof handlers in dashboard listener.
+# Dashboard port must be set first
+pprof_enable = false
+
 [plugin.user-manager]
 addr = 127.0.0.1:9000
 path = /handler
diff --git a/pkg/config/client.go b/pkg/config/client.go
index e65e1064a06..ce96255ba43 100644
--- a/pkg/config/client.go
+++ b/pkg/config/client.go
@@ -151,6 +151,9 @@ type ClientCommonConf struct {
 	UDPPacketSize int64 `ini:"udp_packet_size" json:"udp_packet_size"`
 	// Include other config files for proxies.
 	IncludeConfigFiles []string `ini:"includes" json:"includes"`
+	// Enable golang pprof handlers in admin listener.
+	// Admin port must be set first.
+	PprofEnable bool `ini:"pprof_enable" json:"pprof_enable"`
 }
 
 // GetDefaultClientConf returns a client configuration with default values.
@@ -188,6 +191,7 @@ func GetDefaultClientConf() ClientCommonConf {
 		Metas:                   make(map[string]string),
 		UDPPacketSize:           1500,
 		IncludeConfigFiles:      make([]string, 0),
+		PprofEnable:             false,
 	}
 }
 
diff --git a/pkg/config/server.go b/pkg/config/server.go
index d002f9ff26e..e4f5a498633 100644
--- a/pkg/config/server.go
+++ b/pkg/config/server.go
@@ -167,6 +167,9 @@ type ServerCommonConf struct {
 	// UDPPacketSize specifies the UDP packet size
 	// By default, this value is 1500
 	UDPPacketSize int64 `ini:"udp_packet_size" json:"udp_packet_size"`
+	// Enable golang pprof handlers in dashboard listener.
+	// Dashboard port must be set first.
+	PprofEnable bool `ini:"pprof_enable" json:"pprof_enable"`
 }
 
 // GetDefaultServerConf returns a server configuration with reasonable
@@ -210,6 +213,7 @@ func GetDefaultServerConf() ServerCommonConf {
 		Custom404Page:           "",
 		HTTPPlugins:             make(map[string]plugin.HTTPPluginOptions),
 		UDPPacketSize:           1500,
+		PprofEnable:             false,
 	}
 }
 
diff --git a/server/dashboard.go b/server/dashboard.go
index 0e06ed8255e..8ae1ea8696b 100644
--- a/server/dashboard.go
+++ b/server/dashboard.go
@@ -17,6 +17,7 @@ package server
 import (
 	"net"
 	"net/http"
+	"net/http/pprof"
 	"time"
 
 	"github.com/fatedier/frp/assets"
@@ -27,8 +28,8 @@ import (
 )
 
 var (
-	httpServerReadTimeout  = 10 * time.Second
-	httpServerWriteTimeout = 10 * time.Second
+	httpServerReadTimeout  = 60 * time.Second
+	httpServerWriteTimeout = 60 * time.Second
 )
 
 func (svr *Service) RunDashboardServer(address string) (err error) {
@@ -36,6 +37,15 @@ func (svr *Service) RunDashboardServer(address string) (err error) {
 	router := mux.NewRouter()
 	router.HandleFunc("/healthz", svr.Healthz)
 
+	// debug
+	if svr.cfg.PprofEnable {
+		router.HandleFunc("/debug/pprof/cmdline", pprof.Cmdline)
+		router.HandleFunc("/debug/pprof/profile", pprof.Profile)
+		router.HandleFunc("/debug/pprof/symbol", pprof.Symbol)
+		router.HandleFunc("/debug/pprof/trace", pprof.Trace)
+		router.PathPrefix("/debug/pprof/").HandlerFunc(pprof.Index)
+	}
+
 	subRouter := router.NewRoute().Subrouter()
 
 	user, passwd := svr.cfg.DashboardUser, svr.cfg.DashboardPwd


Test patch: