pprof icon indicating copy to clipboard operation
pprof copied to clipboard

add AddCommand to driver

Open ianwoolf opened this issue 3 years ago • 6 comments

fix #637

ianwoolf avatar Jun 21 '21 03:06 ianwoolf

the dirver.UI is same as internal/plugin.UI, but internal/driver.PostProcessor require internal/plugin.UI. In my own go version, just set the type dirver.UI as internal/plugin.UI, and everything is ok.

But I don’t know if there is a better way, such as put the UI interface into a new package like Option.

ianwoolf avatar Jun 21 '21 03:06 ianwoolf

@aalexand thanks for your review. is this pr can be accepted?

ianwoolf avatar Jun 24 '21 03:06 ianwoolf

@aalexand thanks for your review. is this pr can be accepted?

I haven't looked at it yet. Overall, we do not support any public API in pprof beyond the profile package and the command-line interface, so I'm a bit hesitant to make this change.

Nevertheless, some requests for now (as I'll look more at this change):

  • There are typos in the PR title and description - could you please fix them?
  • Please add documentation to the added public method.
  • Do you have example code of how this new API is used?

aalexand avatar Jun 24 '21 07:06 aalexand

First of all, internal/driver.AddCommand does not seem to be called. And because it is under the package internal, it cannot be called outside the package.

For example, in this scenario, the profile data of the online service needs to be read and sent to other services, such as monitoring system or database like elasticsearch. But because the visualizer of command top is written as nil, I cannot get profile data such as cpu through Option.UI. So I may need to execute the following code.

// option.go
type output struct {
	// r *bufio.Reader
	msg *bytes.Buffer
}
func (ui *output) Print(args ...interface{}) {
	...
}
...
func (ui *output) SetAutoComplete(func(string) string) {
}

type fetcher struct {
	data []byte
}
func (f *fetcher) Fetch() {
	...
}

// main.go	
myfetch := fetcher{}

ui := output{
	msg: bytes.NewBufferString(""),
}

options := &driver.Options{
	UI:    &ui,
	Fetch: &myfetch,
}


f := func(input io.Reader, output io.Writer, ui driver.UI) error {
	msg, _ := ioutil.ReadAll(input)
	ui.Print(string(msg))
	return nil
}

driver.AddCommand("top", driver.Text, f, "Outputs top entries in text form", "top usage")

if err := driver.PProf(options); err != nil {
	fmt.Fprintf(os.Stderr, "%v\n", err)
	os.Exit(2)
}

ianwoolf avatar Jun 25 '21 03:06 ianwoolf

This seems convoluted. Can you instead run pprof command as a child process redirecting its output to a pipe that your program reads from?

aalexand avatar Jun 30 '21 08:06 aalexand

This seems convoluted. Can you instead run pprof command as a child process redirecting its output to a pipe that your program reads from?

it is executalbe. but it is too complex to me, and require pprof and run some command.

My services are running in pods. We have tens of thousands of pods, the cost of deploying pprof and the required environment of commands for each pod is a little high. the most easy way is put the profile into my service, and expose http and other methods to the standard monitoring such as prometheus.

ianwoolf avatar Jul 01 '21 02:07 ianwoolf

Closing as we do not plan to expand the pprof API surface.

aalexand avatar Dec 03 '23 20:12 aalexand