diff --git a/.golangci.yml b/.golangci.yml index b92e4ac5..1e2584a8 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -57,6 +57,10 @@ linters-settings: simple: true range-loops: true for-loops: false + gosec: + excludes: + - G108 + - G114 gocritic: enabled-checks: - appendAssign diff --git a/README.md b/README.md index edecd8e6..be783468 100644 --- a/README.md +++ b/README.md @@ -46,6 +46,8 @@ docker build . * `NSM_CGROUP_PATH` - path to the host cgroup directory * `NSM_VFIO_PATH` - path to the host VFIO directory * `NSM_MECHANISM_PRIORITY` - sets priorities for mechanisms +* `NSM_ENABLE_PROFILER` - Enable pprof package HTTP server for profiling runtime data. +* `NSM_PROFILER_HTTP_PORT` - Profiling server HTTP port providing data in the format expected by the pprof visualization tool. # Testing diff --git a/internal/config/config.go b/internal/config/config.go index 9e9c5498..3fb09a4a 100644 --- a/internal/config/config.go +++ b/internal/config/config.go @@ -64,6 +64,8 @@ type Config struct { CgroupPath string `default:"/host/sys/fs/cgroup/devices" desc:"path to the host cgroup directory" split_words:"true"` VFIOPath string `default:"/host/dev/vfio" desc:"path to the host VFIO directory" split_words:"true"` MechanismPriority []string `default:"" desc:"sets priorities for mechanisms" split_words:"true"` + EnableProfiler bool `default:"false" desc:"Enable pprof package HTTP server for profiling runtime data. The handled paths all begin with /debug/pprof/." split_words:"true"` + ProfilerHTTPPort uint16 `default:"6060" desc:"Profiling server HTTP port providing data in the format expected by the pprof visualization tool." split_words:"true"` } // Process reads config from env diff --git a/internal/imports/imports_linux.go b/internal/imports/imports_linux.go index 6c94703b..b20a371e 100644 --- a/internal/imports/imports_linux.go +++ b/internal/imports/imports_linux.go @@ -116,6 +116,8 @@ import ( _ "google.golang.org/grpc/health/grpc_health_v1" _ "gopkg.in/yaml.v3" _ "net" + _ "net/http" + _ "net/http/pprof" _ "net/url" _ "os" _ "os/signal" diff --git a/main.go b/main.go index dcea1705..b7905052 100644 --- a/main.go +++ b/main.go @@ -22,6 +22,7 @@ package main import ( "context" "crypto/tls" + "fmt" "os" "os/signal" "path" @@ -70,6 +71,9 @@ import ( "github.com/networkservicemesh/cmd-forwarder-vpp/internal/devicecfg" "github.com/networkservicemesh/cmd-forwarder-vpp/internal/vppinit" "github.com/networkservicemesh/cmd-forwarder-vpp/internal/xconnectns" + + "net/http" + _ "net/http/pprof" ) func main() { @@ -134,6 +138,18 @@ func main() { log.EnableTracing(true) log.FromContext(ctx).WithField("duration", time.Since(now)).Infof("completed phase 1: get config from environment") + // Enable profiling server + if cfg.EnableProfiler { + go func() { + log.FromContext(ctx).Infof("Profiler is enabled. Starting HTTP server on %d", cfg.ProfilerHTTPPort) + + address := fmt.Sprintf("localhost:%d", cfg.ProfilerHTTPPort) + if err = http.ListenAndServe(address, nil); err != nil { + log.FromContext(ctx).Errorf("Failed to start profiler: %s", err.Error()) + } + }() + } + // ******************************************************************************** // Configure Open Telemetry // ********************************************************************************