Repository: hyperledger/firefly
Pull request #1088 (2022-10-11 12:31:37)

Allow listening for go debug on all interfaces, not just localhost
It's difficult using the go pprof debug utility when running in a container since the network interface it binds to defaults to localhost. This PR makes 2 changes:

1. Make the interface address configurable
2. Change the default interface to "*"

It still requires changes to the docker run command or docker compose overrides file to get a route through to the debug listener, but doesn't require you to rebuild firefly. 


Patch:
diff --git a/cmd/firefly.go b/cmd/firefly.go
index 3a889ebb1..ffe03f74d 100644
--- a/cmd/firefly.go
+++ b/cmd/firefly.go
@@ -164,6 +164,7 @@ func startFirefly(ctx context.Context, cancelCtx context.CancelFunc, mgr namespa
 	// Start debug listener
 	var debugServer *http.Server
 	debugPort := config.GetInt(coreconfig.DebugPort)
+	debugAddress := config.GetString(coreconfig.DebugAddress)
 	if debugPort >= 0 {
 		r := mux.NewRouter()
 		r.PathPrefix("/debug/pprof/cmdline").HandlerFunc(pprof.Cmdline)
@@ -171,11 +172,11 @@ func startFirefly(ctx context.Context, cancelCtx context.CancelFunc, mgr namespa
 		r.PathPrefix("/debug/pprof/symbol").HandlerFunc(pprof.Symbol)
 		r.PathPrefix("/debug/pprof/trace").HandlerFunc(pprof.Trace)
 		r.PathPrefix("/debug/pprof/").HandlerFunc(pprof.Index)
-		debugServer = &http.Server{Addr: fmt.Sprintf("localhost:%d", debugPort), Handler: r, ReadHeaderTimeout: 30 * time.Second}
+		debugServer = &http.Server{Addr: fmt.Sprintf("%s:%d", debugAddress, debugPort), Handler: r, ReadHeaderTimeout: 30 * time.Second}
 		go func() {
 			_ = debugServer.ListenAndServe()
 		}()
-		log.L(ctx).Debugf("Debug HTTP endpoint listening on localhost:%d", debugPort)
+		log.L(ctx).Debugf("Debug HTTP endpoint listening on %s:%d", debugAddress, debugPort)
 	}
 
 	defer func() {
diff --git a/docs/reference/config.md b/docs/reference/config.md
index 4425795a1..2efe8ef08 100644
--- a/docs/reference/config.md
+++ b/docs/reference/config.md
@@ -464,6 +464,7 @@ nav_order: 2
 
 |Key|Description|Type|Default Value|
 |---|-----------|----|-------------|
+|address|The HTTP interface the go debugger binds to|`string`|`<nil>`
 |port|An HTTP port on which to enable the go debugger|`int`|`<nil>`
 
 ## download.retry
diff --git a/internal/coreconfig/coreconfig.go b/internal/coreconfig/coreconfig.go
index 56a0e0ae2..ba828acdd 100644
--- a/internal/coreconfig/coreconfig.go
+++ b/internal/coreconfig/coreconfig.go
@@ -209,6 +209,8 @@ var (
 	PluginsIdentityList = ffc("plugins.identity")
 	// DebugPort a HTTP port on which to enable the go debugger
 	DebugPort = ffc("debug.port")
+	// DebugAddress the HTTP interface for the debugger to listen on
+	DebugAddress = ffc("debug.address")
 	// EventTransportsDefault the default event transport for new subscriptions
 	EventTransportsDefault = ffc("event.transports.default")
 	// EventTransportsEnabled which event interface plugins are enabled
@@ -359,6 +361,7 @@ func setDefaults() {
 	viper.SetDefault(string(CacheOperationsTTL), "5m")
 	viper.SetDefault(string(HistogramsMaxChartRows), 100)
 	viper.SetDefault(string(DebugPort), -1)
+	viper.SetDefault(string(DebugAddress), "localhost")
 	viper.SetDefault(string(DownloadWorkerCount), 10)
 	viper.SetDefault(string(DownloadRetryMaxAttempts), 100)
 	viper.SetDefault(string(DownloadRetryInitDelay), "100ms")
diff --git a/internal/coremsgs/en_config_descriptions.go b/internal/coremsgs/en_config_descriptions.go
index de083d383..8f0927b64 100644
--- a/internal/coremsgs/en_config_descriptions.go
+++ b/internal/coremsgs/en_config_descriptions.go
@@ -216,7 +216,8 @@ var (
 
 	ConfigPluginDataexchangeFfdxProxyURL = ffc("config.plugins.dataexchange[].ffdx.proxy.url", "Optional HTTP proxy server to use when connecting to the Data Exchange", "URL "+i18n.StringType)
 
-	ConfigDebugPort = ffc("config.debug.port", "An HTTP port on which to enable the go debugger", i18n.IntType)
+	ConfigDebugPort    = ffc("config.debug.port", "An HTTP port on which to enable the go debugger", i18n.IntType)
+	ConfigDebugAddress = ffc("config.debug.address", "The HTTP interface the go debugger binds to", i18n.StringType)
 
 	ConfigDownloadWorkerCount       = ffc("config.download.worker.count", "The number of download workers", i18n.IntType)
 	ConfigDownloadWorkerQueueLength = ffc("config.download.worker.queueLength", "The length of the work queue in the channel to the workers - defaults to 2x the worker count", i18n.IntType)


Test patch:
diff --git a/internal/coreconfig/coreconfig_test.go b/internal/coreconfig/coreconfig_test.go
index f390c4f3f..3344cc0dd 100644
--- a/internal/coreconfig/coreconfig_test.go
+++ b/internal/coreconfig/coreconfig_test.go
@@ -29,4 +29,6 @@ func TestInitConfigOK(t *testing.T) {
 	Reset()
 
 	assert.Equal(t, 25, config.GetInt(APIDefaultFilterLimit))
+	assert.Equal(t, "localhost", config.GetString(DebugAddress))
+	assert.Equal(t, -1, config.GetInt(DebugPort))
 }