Skip to content

Commit 9d369f3

Browse files
committed
kubectl: Refactor profiling helpers
1 parent 34f2a0f commit 9d369f3

File tree

2 files changed

+29
-14
lines changed

2 files changed

+29
-14
lines changed

staging/src/k8s.io/kubectl/pkg/cmd/cmd.go

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -306,6 +306,7 @@ func HandlePluginCommand(pluginHandler PluginHandler, cmdArgs []string, minArgs
306306
func NewKubectlCommand(o KubectlOptions) *cobra.Command {
307307
warningHandler := rest.NewWarningWriter(o.IOStreams.ErrOut, rest.WarningWriterOptions{Deduplicate: true, Color: term.AllowsColorOutput(o.IOStreams.ErrOut)})
308308
warningsAsErrors := false
309+
var finishProfiling func() error
309310
// Parent command to which all subcommands are added.
310311
cmds := &cobra.Command{
311312
Use: "kubectl",
@@ -327,11 +328,15 @@ func NewKubectlCommand(o KubectlOptions) *cobra.Command {
327328
plugin.SetupPluginCompletion(cmd, args)
328329
}
329330

330-
return initProfiling()
331+
var err error
332+
finishProfiling, err = initProfiling()
333+
return err
331334
},
332335
PersistentPostRunE: func(*cobra.Command, []string) error {
333-
if err := flushProfiling(); err != nil {
334-
return err
336+
if finishProfiling != nil {
337+
if err := finishProfiling(); err != nil {
338+
return err
339+
}
335340
}
336341
if warningsAsErrors {
337342
count := warningHandler.WarningCount()

staging/src/k8s.io/kubectl/pkg/cmd/profiling.go

Lines changed: 21 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ package cmd
1818

1919
import (
2020
"fmt"
21+
"io"
2122
"os"
2223
"os/signal"
2324
"runtime"
@@ -36,22 +37,25 @@ func addProfilingFlags(flags *pflag.FlagSet) {
3637
flags.StringVar(&profileOutput, "profile-output", "profile.pprof", "Name of the file to write the profile to")
3738
}
3839

39-
func initProfiling() error {
40+
// initProfiling inits profiling and returns a function to be called on exit to flush and close.
41+
func initProfiling() (func() error, error) {
4042
var (
4143
f *os.File
4244
err error
4345
)
4446
switch profileName {
4547
case "none":
46-
return nil
48+
return nil, nil
4749
case "cpu":
4850
f, err = os.Create(profileOutput)
4951
if err != nil {
50-
return err
52+
return nil, err
5153
}
54+
5255
err = pprof.StartCPUProfile(f)
5356
if err != nil {
54-
return err
57+
f.Close() //nolint:errcheck
58+
return nil, err
5559
}
5660
// Block and mutex profiles need a call to Set{Block,Mutex}ProfileRate to
5761
// output anything. We choose to sample all events.
@@ -62,25 +66,29 @@ func initProfiling() error {
6266
default:
6367
// Check the profile name is valid.
6468
if profile := pprof.Lookup(profileName); profile == nil {
65-
return fmt.Errorf("unknown profile '%s'", profileName)
69+
return nil, fmt.Errorf("unknown profile '%s'", profileName)
6670
}
6771
}
6872

69-
// If the command is interrupted before the end (ctrl-c), flush the
70-
// profiling files
73+
// If the command is interrupted before the end (ctrl-c), flush the profiling files
7174
c := make(chan os.Signal, 1)
7275
signal.Notify(c, os.Interrupt)
7376
go func() {
7477
<-c
75-
f.Close()
76-
flushProfiling()
78+
flushProfiling(f) //nolint:errcheck
7779
os.Exit(0)
7880
}()
7981

80-
return nil
82+
return func() error {
83+
return flushProfiling(f)
84+
}, nil
8185
}
8286

83-
func flushProfiling() error {
87+
func flushProfiling(output io.Closer) error {
88+
if output != nil {
89+
defer output.Close() //nolint:errcheck
90+
}
91+
8492
switch profileName {
8593
case "none":
8694
return nil
@@ -94,10 +102,12 @@ func flushProfiling() error {
94102
if profile == nil {
95103
return nil
96104
}
105+
97106
f, err := os.Create(profileOutput)
98107
if err != nil {
99108
return err
100109
}
110+
101111
defer f.Close()
102112
profile.WriteTo(f, 0)
103113
}

0 commit comments

Comments
 (0)