From ed1da076654cdec96ec1f43afcfcead4c5b97ade Mon Sep 17 00:00:00 2001 From: Chris Lu Date: Thu, 18 Dec 2025 17:44:36 -0800 Subject: [PATCH] Add consistent -debug and -debug.port flags to commands (#7816) * Add consistent -debug and -debug.port flags to commands Add -debug and -debug.port flags to weed master, weed volume, weed s3, weed mq.broker, and weed filer.sync commands for consistency with weed filer. When -debug is enabled, an HTTP server starts on the specified port (default 6060) serving runtime profiling data at /debug/pprof/. For mq.broker, replaced the older -port.pprof flag with the new -debug and -debug.port pattern for consistency. * Update weed/util/grace/pprof.go Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com> --------- Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com> --- test/kafka/docker-compose.yml | 3 +- .../kafka-client-loadtest/docker-compose.yml | 3 +- weed/command/filer_sync.go | 7 +++++ weed/command/master.go | 7 +++++ weed/command/mq_broker.go | 28 ++++++------------- weed/command/s3.go | 8 ++++++ weed/command/volume.go | 7 +++++ weed/util/grace/pprof.go | 15 ++++++++++ 8 files changed, 56 insertions(+), 22 deletions(-) diff --git a/test/kafka/docker-compose.yml b/test/kafka/docker-compose.yml index e19a39a5a..24532c164 100644 --- a/test/kafka/docker-compose.yml +++ b/test/kafka/docker-compose.yml @@ -172,7 +172,8 @@ services: - -master=seaweedfs-master:9333 - -ip=seaweedfs-mq-broker - -port=17777 - - -port.pprof=18777 + - -debug + - -debug.port=18777 depends_on: seaweedfs-filer: condition: service_healthy diff --git a/test/kafka/kafka-client-loadtest/docker-compose.yml b/test/kafka/kafka-client-loadtest/docker-compose.yml index c5a20d155..b6f1a9fb1 100644 --- a/test/kafka/kafka-client-loadtest/docker-compose.yml +++ b/test/kafka/kafka-client-loadtest/docker-compose.yml @@ -181,7 +181,8 @@ services: - -ip=seaweedfs-mq-broker - -port=17777 - -logFlushInterval=0 - - -port.pprof=18777 + - -debug + - -debug.port=18777 depends_on: seaweedfs-filer: condition: service_healthy diff --git a/weed/command/filer_sync.go b/weed/command/filer_sync.go index 94c9bc1be..8f752b6d7 100644 --- a/weed/command/filer_sync.go +++ b/weed/command/filer_sync.go @@ -53,6 +53,8 @@ type SyncOptions struct { bDoDeleteFiles *bool clientId int32 clientEpoch atomic.Int32 + debug *bool + debugPort *int } const ( @@ -108,6 +110,8 @@ func init() { syncOptions.metricsHttpPort = cmdFilerSynchronize.Flag.Int("metricsPort", 0, "metrics listen port") syncOptions.aDoDeleteFiles = cmdFilerSynchronize.Flag.Bool("a.doDeleteFiles", true, "delete and update files when synchronizing on filer A") syncOptions.bDoDeleteFiles = cmdFilerSynchronize.Flag.Bool("b.doDeleteFiles", true, "delete and update files when synchronizing on filer B") + syncOptions.debug = cmdFilerSynchronize.Flag.Bool("debug", false, "serves runtime profiling data via pprof on the port specified by -debug.port") + syncOptions.debugPort = cmdFilerSynchronize.Flag.Int("debug.port", 6060, "http port for debugging") syncOptions.clientId = util.RandomInt32() } @@ -130,6 +134,9 @@ var cmdFilerSynchronize = &Command{ } func runFilerSynchronize(cmd *Command, args []string) bool { + if *syncOptions.debug { + grace.StartDebugServer(*syncOptions.debugPort) + } util.LoadSecurityConfiguration() grpcDialOption := security.LoadClientTLS(util.GetViper(), "grpc.client") diff --git a/weed/command/master.go b/weed/command/master.go index 11c57701b..543e5f199 100644 --- a/weed/command/master.go +++ b/weed/command/master.go @@ -69,6 +69,8 @@ type MasterOptions struct { raftBootstrap *bool telemetryUrl *string telemetryEnabled *bool + debug *bool + debugPort *int } func init() { @@ -98,6 +100,8 @@ func init() { m.raftBootstrap = cmdMaster.Flag.Bool("raftBootstrap", false, "Whether to bootstrap the Raft cluster") m.telemetryUrl = cmdMaster.Flag.String("telemetry.url", "https://telemetry.seaweedfs.com/api/collect", "telemetry server URL to send usage statistics") m.telemetryEnabled = cmdMaster.Flag.Bool("telemetry", false, "enable telemetry reporting") + m.debug = cmdMaster.Flag.Bool("debug", false, "serves runtime profiling data via pprof on the port specified by -debug.port") + m.debugPort = cmdMaster.Flag.Int("debug.port", 6060, "http port for debugging") } var cmdMaster = &Command{ @@ -121,6 +125,9 @@ var ( ) func runMaster(cmd *Command, args []string) bool { + if *m.debug { + grace.StartDebugServer(*m.debugPort) + } util.LoadSecurityConfiguration() util.LoadConfiguration("master", false) diff --git a/weed/command/mq_broker.go b/weed/command/mq_broker.go index 8ea7f96a4..3b6057548 100644 --- a/weed/command/mq_broker.go +++ b/weed/command/mq_broker.go @@ -1,20 +1,15 @@ package command import ( - "fmt" - "net/http" - _ "net/http/pprof" - "google.golang.org/grpc/reflection" - "github.com/seaweedfs/seaweedfs/weed/util/grace" - "github.com/seaweedfs/seaweedfs/weed/glog" "github.com/seaweedfs/seaweedfs/weed/mq/broker" "github.com/seaweedfs/seaweedfs/weed/pb" "github.com/seaweedfs/seaweedfs/weed/pb/mq_pb" "github.com/seaweedfs/seaweedfs/weed/security" "github.com/seaweedfs/seaweedfs/weed/util" + "github.com/seaweedfs/seaweedfs/weed/util/grace" ) var ( @@ -27,12 +22,13 @@ type MessageQueueBrokerOptions struct { filerGroup *string ip *string port *int - pprofPort *int dataCenter *string rack *string cpuprofile *string memprofile *string logFlushInterval *int + debug *bool + debugPort *int } func init() { @@ -41,12 +37,13 @@ func init() { mqBrokerStandaloneOptions.filerGroup = cmdMqBroker.Flag.String("filerGroup", "", "share metadata with other filers in the same filerGroup") mqBrokerStandaloneOptions.ip = cmdMqBroker.Flag.String("ip", util.DetectedHostAddress(), "broker host address") mqBrokerStandaloneOptions.port = cmdMqBroker.Flag.Int("port", 17777, "broker gRPC listen port") - mqBrokerStandaloneOptions.pprofPort = cmdMqBroker.Flag.Int("port.pprof", 0, "HTTP profiling port (0 to disable)") mqBrokerStandaloneOptions.dataCenter = cmdMqBroker.Flag.String("dataCenter", "", "prefer to read and write to volumes in this data center") mqBrokerStandaloneOptions.rack = cmdMqBroker.Flag.String("rack", "", "prefer to write to volumes in this rack") mqBrokerStandaloneOptions.cpuprofile = cmdMqBroker.Flag.String("cpuprofile", "", "cpu profile output file") mqBrokerStandaloneOptions.memprofile = cmdMqBroker.Flag.String("memprofile", "", "memory profile output file") mqBrokerStandaloneOptions.logFlushInterval = cmdMqBroker.Flag.Int("logFlushInterval", 5, "log buffer flush interval in seconds") + mqBrokerStandaloneOptions.debug = cmdMqBroker.Flag.Bool("debug", false, "serves runtime profiling data via pprof on the port specified by -debug.port") + mqBrokerStandaloneOptions.debugPort = cmdMqBroker.Flag.Int("debug.port", 6060, "http port for debugging") } var cmdMqBroker = &Command{ @@ -61,6 +58,9 @@ var cmdMqBroker = &Command{ } func runMqBroker(cmd *Command, args []string) bool { + if *mqBrokerStandaloneOptions.debug { + grace.StartDebugServer(*mqBrokerStandaloneOptions.debugPort) + } util.LoadSecurityConfiguration() @@ -115,18 +115,6 @@ func (mqBrokerOpt *MessageQueueBrokerOptions) startQueueServer() bool { }() } - // Start HTTP profiling server if enabled - if mqBrokerOpt.pprofPort != nil && *mqBrokerOpt.pprofPort > 0 { - go func() { - pprofAddr := fmt.Sprintf(":%d", *mqBrokerOpt.pprofPort) - glog.V(0).Infof("MQ Broker pprof server listening on %s", pprofAddr) - glog.V(0).Infof("Access profiling at: http://localhost:%d/debug/pprof/", *mqBrokerOpt.pprofPort) - if err := http.ListenAndServe(pprofAddr, nil); err != nil { - glog.Errorf("pprof server error: %v", err) - } - }() - } - glog.V(0).Infof("MQ Broker listening on %s:%d", *mqBrokerOpt.ip, *mqBrokerOpt.port) grpcS.Serve(grpcL) diff --git a/weed/command/s3.go b/weed/command/s3.go index 0a1296097..940536176 100644 --- a/weed/command/s3.go +++ b/weed/command/s3.go @@ -26,6 +26,7 @@ import ( "github.com/seaweedfs/seaweedfs/weed/security" stats_collect "github.com/seaweedfs/seaweedfs/weed/stats" "github.com/seaweedfs/seaweedfs/weed/util" + "github.com/seaweedfs/seaweedfs/weed/util/grace" "github.com/seaweedfs/seaweedfs/weed/util/version" ) @@ -59,6 +60,8 @@ type S3Options struct { concurrentUploadLimitMB *int concurrentFileUploadLimit *int enableIam *bool + debug *bool + debugPort *int } func init() { @@ -88,6 +91,8 @@ func init() { s3StandaloneOptions.concurrentUploadLimitMB = cmdS3.Flag.Int("concurrentUploadLimitMB", 0, "limit total concurrent upload size, 0 means unlimited") s3StandaloneOptions.concurrentFileUploadLimit = cmdS3.Flag.Int("concurrentFileUploadLimit", 0, "limit number of concurrent file uploads, 0 means unlimited") s3StandaloneOptions.enableIam = cmdS3.Flag.Bool("iam", true, "enable embedded IAM API on the same port") + s3StandaloneOptions.debug = cmdS3.Flag.Bool("debug", false, "serves runtime profiling data via pprof on the port specified by -debug.port") + s3StandaloneOptions.debugPort = cmdS3.Flag.Int("debug.port", 6060, "http port for debugging") } var cmdS3 = &Command{ @@ -182,6 +187,9 @@ var cmdS3 = &Command{ } func runS3(cmd *Command, args []string) bool { + if *s3StandaloneOptions.debug { + grace.StartDebugServer(*s3StandaloneOptions.debugPort) + } util.LoadSecurityConfiguration() diff --git a/weed/command/volume.go b/weed/command/volume.go index 28a34679a..86bea0ee6 100644 --- a/weed/command/volume.go +++ b/weed/command/volume.go @@ -72,6 +72,8 @@ type VolumeServerOptions struct { hasSlowRead *bool readBufferSizeMB *int ldbTimeout *int64 + debug *bool + debugPort *int } func init() { @@ -110,6 +112,8 @@ func init() { v.inflightDownloadDataTimeout = cmdVolume.Flag.Duration("inflightDownloadDataTimeout", 60*time.Second, "inflight download data wait timeout of volume servers") v.hasSlowRead = cmdVolume.Flag.Bool("hasSlowRead", true, " if true, this prevents slow reads from blocking other requests, but large file read P99 latency will increase.") v.readBufferSizeMB = cmdVolume.Flag.Int("readBufferSizeMB", 4, " larger values can optimize query performance but will increase some memory usage,Use with hasSlowRead normally.") + v.debug = cmdVolume.Flag.Bool("debug", false, "serves runtime profiling data via pprof on the port specified by -debug.port") + v.debugPort = cmdVolume.Flag.Int("debug.port", 6060, "http port for debugging") } var cmdVolume = &Command{ @@ -129,6 +133,9 @@ var ( ) func runVolume(cmd *Command, args []string) bool { + if *v.debug { + grace.StartDebugServer(*v.debugPort) + } util.LoadSecurityConfiguration() diff --git a/weed/util/grace/pprof.go b/weed/util/grace/pprof.go index 620184c9b..5f5617c16 100644 --- a/weed/util/grace/pprof.go +++ b/weed/util/grace/pprof.go @@ -1,6 +1,9 @@ package grace import ( + "fmt" + "net/http" + _ "net/http/pprof" "os" "runtime" "runtime/pprof" @@ -8,6 +11,18 @@ import ( "github.com/seaweedfs/seaweedfs/weed/glog" ) +// StartDebugServer starts an HTTP server for pprof debugging on the specified port. +// The server runs in a goroutine and serves pprof endpoints at /debug/pprof/*. +func StartDebugServer(debugPort int) { + go func() { + addr := fmt.Sprintf(":%d", debugPort) + glog.V(0).Infof("Starting debug server for pprof at http://localhost%s/debug/pprof/", addr) + if err := http.ListenAndServe(addr, nil); err != nil && err != http.ErrServerClosed { + glog.Errorf("Failed to start debug server on %s: %v", addr, err) + } + }() +} + func SetupProfiling(cpuProfile, memProfile string) { if cpuProfile != "" { f, err := os.Create(cpuProfile)