Skip to content

Commit

Permalink
Added CPU Profiling Support via pprof
Browse files Browse the repository at this point in the history
This adds an option to enable cpu profiling using pprof at startup. The
profiling data is dumped to a file when the daemon is stopped.

Signed-off-by: Blake Devcich <[email protected]>
  • Loading branch information
bdevcich committed Dec 13, 2023
1 parent 9c7d43c commit ff6a3ac
Show file tree
Hide file tree
Showing 2 changed files with 39 additions and 12 deletions.
25 changes: 24 additions & 1 deletion daemons/compute/server/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,9 @@ import (
"os"
"os/signal"
"runtime"
"runtime/pprof"
"syscall"
"time"

"github.com/takama/daemon"
"google.golang.org/grpc"
Expand All @@ -49,7 +51,7 @@ type Service struct {
daemon.Daemon
}

func (service *Service) Manage() (string, error) {
func (service *Service) Manage() (msg string, err error) {

if len(os.Args) > 1 {
command := os.Args[1]
Expand Down Expand Up @@ -99,6 +101,27 @@ func (service *Service) Manage() (string, error) {
return fmt.Sprintf("Failed to set permissions on socket %s", *socketAddr), err
}

// Enable CPU profiling with pprof
if len(options.CpuProfile) > 0 {
filename := options.CpuProfile + "-" + time.Now().UTC().Format(time.RFC3339)
f, err := os.Create(filename)
if err != nil {
return fmt.Sprintf("could not create CPU profile"), err
}
defer func() {
if cerr := f.Close(); cerr != nil {
err = cerr
msg = "could not close CPU profile"
}
}()

if err := pprof.StartCPUProfile(f); err != nil {
return fmt.Sprintf("could not start CPU profile"), err
}
errlog.Printf("CPU profiling enabled (%s)\n", filename)
defer pprof.StopCPUProfile()
}

go service.Run(server, listener)

for {
Expand Down
26 changes: 15 additions & 11 deletions daemons/compute/server/servers/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,24 +32,26 @@ type ServerOptions struct {
tokenFile string
certFile string

name string
nodeName string
sysConfig string
simulated bool
name string
nodeName string
sysConfig string
CpuProfile string
simulated bool

k8sQPS int
k8sBurst int
}

func GetOptions() (*ServerOptions, error) {
opts := ServerOptions{
host: os.Getenv("KUBERNETES_SERVICE_HOST"),
port: os.Getenv("KUBERNETES_SERVICE_PORT"),
name: os.Getenv("NODE_NAME"),
nodeName: os.Getenv("NNF_NODE_NAME"),
tokenFile: os.Getenv("NNF_DATA_MOVEMENT_SERVICE_TOKEN_FILE"),
certFile: os.Getenv("NNF_DATA_MOVEMENT_SERVICE_CERT_FILE"),
simulated: false,
host: os.Getenv("KUBERNETES_SERVICE_HOST"),
port: os.Getenv("KUBERNETES_SERVICE_PORT"),
name: os.Getenv("NODE_NAME"),
nodeName: os.Getenv("NNF_NODE_NAME"),
tokenFile: os.Getenv("NNF_DATA_MOVEMENT_SERVICE_TOKEN_FILE"),
certFile: os.Getenv("NNF_DATA_MOVEMENT_SERVICE_CERT_FILE"),
CpuProfile: os.Getenv("NNF_DATA_MOVEMENT_SERVICE_CPU_PROFILE"),
simulated: false,

// These options adjust the client-side rate-limiting for k8s. The new defaults are 50 and
// 100 (rather than 5, 10). See more info https://github.com/kubernetes/kubernetes/pull/116121
Expand All @@ -68,6 +70,8 @@ func GetOptions() (*ServerOptions, error) {
flag.BoolVar(&opts.simulated, "simulated", opts.simulated, "Run in simulation mode where no requests are sent to the server")
flag.IntVar(&opts.k8sQPS, "kubernetes-qps", opts.k8sQPS, "Kubernetes client queries per second (QPS)")
flag.IntVar(&opts.k8sBurst, "kubernetes-burst", opts.k8sBurst, "Kubernetes client additional concurrent calls above QPS")
flag.StringVar(&opts.CpuProfile, "cpu-profile", opts.CpuProfile,
"Enable and dump CPU profiling data to this file after daemon is stopped. Timestamp is added to end of filename.")
flag.Parse()
return &opts, nil
}
Expand Down

0 comments on commit ff6a3ac

Please sign in to comment.