Add optional pprof endpoint support to multus-daemon

Add pprof profiling endpoints to the metrics server, gated behind
a new EnablePprof config field. When enabled, standard Go pprof
handlers are registered on the metrics port under /debug/pprof/.

This also improves the metrics server setup:
- Use dedicated http.ServeMux instead of DefaultServeMux
- Move mux/handler setup outside the retry loop
- Use http.Server with ReadHeaderTimeout for resource safety
- Add graceful shutdown on context cancellation

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Signed-off-by: Benjamin Pickard <bpickard@redhat.com>
This commit is contained in:
Benjamin Pickard
2026-05-18 16:05:31 -04:00
parent bd3f2a56c8
commit 9063a32fe1
2 changed files with 27 additions and 4 deletions

View File

@@ -22,12 +22,14 @@ import (
"fmt"
"io"
"net/http"
"net/http/pprof"
"os"
"os/signal"
"os/user"
"path/filepath"
"sync"
"syscall"
"time"
utilwait "k8s.io/apimachinery/pkg/util/wait"
@@ -155,11 +157,31 @@ func startMultusDaemon(ctx context.Context, daemonConfig *srv.ControllerNetConf,
}
if daemonConfig.MetricsPort != nil {
mux := http.NewServeMux()
mux.Handle("/metrics", promhttp.Handler())
if daemonConfig.EnablePprof != nil && *daemonConfig.EnablePprof {
mux.HandleFunc("/debug/pprof/", pprof.Index)
mux.HandleFunc("/debug/pprof/cmdline", pprof.Cmdline)
mux.HandleFunc("/debug/pprof/profile", pprof.Profile)
mux.HandleFunc("/debug/pprof/symbol", pprof.Symbol)
mux.HandleFunc("/debug/pprof/trace", pprof.Trace)
logging.Verbosef("pprof endpoints enabled on metrics port %d", *daemonConfig.MetricsPort)
}
metricsSrv := &http.Server{
Addr: fmt.Sprintf(":%d", *daemonConfig.MetricsPort),
Handler: mux,
ReadHeaderTimeout: 10 * time.Second,
}
logging.Debugf("metrics port: %d", *daemonConfig.MetricsPort)
go utilwait.UntilWithContext(ctx, func(_ context.Context) {
http.Handle("/metrics", promhttp.Handler())
logging.Debugf("metrics port: %d", *daemonConfig.MetricsPort)
logging.Debugf("metrics: %s", http.ListenAndServe(fmt.Sprintf(":%d", *daemonConfig.MetricsPort), nil))
if err := metricsSrv.ListenAndServe(); err != nil && err != http.ErrServerClosed {
logging.Debugf("metrics server error: %v", err)
}
}, 0)
go func() {
<-ctx.Done()
metricsSrv.Shutdown(context.Background())
}()
}
l, err := srv.GetListener(api.SocketPath(daemonConfig.SocketDir))

View File

@@ -78,7 +78,8 @@ type ControllerNetConf struct {
LogToStderr bool `json:"logToStderr,omitempty"`
PerNodeCertificate *PerNodeCertificate `json:"perNodeCertificate,omitempty"`
MetricsPort *int `json:"metricsPort,omitempty"`
MetricsPort *int `json:"metricsPort,omitempty"`
EnablePprof *bool `json:"enablePprof,omitempty"`
// Option to point to the path of the unix domain socket through which the
// multus client / server communicate.