Commit c9d0c812 authored by Shenghou Ma's avatar Shenghou Ma Committed by Russ Cox

cmd/pprof/internal/commands: add command to open browser on windows

While we're at there, also add a message to prompt the user to install
Graphviz if "dot" command is not found.

Fixes #9178.

LGTM=adg, alex.brainman, cookieo9, rsc
R=rsc, adg, bradfitz, alex.brainman, cookieo9, smyrman
CC=golang-codereviews
https://golang.org/cl/180380043
parent b2950a29
...@@ -11,6 +11,7 @@ import ( ...@@ -11,6 +11,7 @@ import (
"io" "io"
"os" "os"
"os/exec" "os/exec"
"runtime"
"strings" "strings"
"cmd/pprof/internal/plugin" "cmd/pprof/internal/plugin"
...@@ -71,15 +72,27 @@ func PProf(c Completer, interactive **bool, svgpan **string) Commands { ...@@ -71,15 +72,27 @@ func PProf(c Completer, interactive **bool, svgpan **string) Commands {
"eog": {c, report.Dot, invokeVisualizer(interactive, invokeDot("svg"), "svg", []string{"eog"}), false, "Visualize graph through eog"}, "eog": {c, report.Dot, invokeVisualizer(interactive, invokeDot("svg"), "svg", []string{"eog"}), false, "Visualize graph through eog"},
"evince": {c, report.Dot, invokeVisualizer(interactive, invokeDot("pdf"), "pdf", []string{"evince"}), false, "Visualize graph through evince"}, "evince": {c, report.Dot, invokeVisualizer(interactive, invokeDot("pdf"), "pdf", []string{"evince"}), false, "Visualize graph through evince"},
"gv": {c, report.Dot, invokeVisualizer(interactive, invokeDot("ps"), "ps", []string{"gv --noantialias"}), false, "Visualize graph through gv"}, "gv": {c, report.Dot, invokeVisualizer(interactive, invokeDot("ps"), "ps", []string{"gv --noantialias"}), false, "Visualize graph through gv"},
"web": {c, report.Dot, invokeVisualizer(interactive, saveSVGToFile(svgpan), "svg", browsers), false, "Visualize graph through web browser"}, "web": {c, report.Dot, invokeVisualizer(interactive, saveSVGToFile(svgpan), "svg", browsers()), false, "Visualize graph through web browser"},
// Visualize HTML directly generated by report. // Visualize HTML directly generated by report.
"weblist": {c, report.WebList, invokeVisualizer(interactive, awayFromTTY("html"), "html", browsers), true, "Output annotated source in HTML for functions matching regexp or address"}, "weblist": {c, report.WebList, invokeVisualizer(interactive, awayFromTTY("html"), "html", browsers()), true, "Output annotated source in HTML for functions matching regexp or address"},
} }
} }
// List of web browsers to attempt for web visualization // browsers returns a list of commands to attempt for web visualization
var browsers = []string{"chrome", "google-chrome", "firefox", "/usr/bin/open"} // on the current platform
func browsers() []string {
cmds := []string{"chrome", "google-chrome", "firefox"}
switch runtime.GOOS {
case "darwin":
cmds = append(cmds, "/usr/bin/open")
case "windows":
cmds = append(cmds, "cmd /c start")
default:
cmds = append(cmds, "xdg-open")
}
return cmds
}
// NewCompleter creates an autocompletion function for a set of commands. // NewCompleter creates an autocompletion function for a set of commands.
func NewCompleter(cs Commands) Completer { func NewCompleter(cs Commands) Completer {
...@@ -142,6 +155,10 @@ func awayFromTTY(format string) PostProcessor { ...@@ -142,6 +155,10 @@ func awayFromTTY(format string) PostProcessor {
func invokeDot(format string) PostProcessor { func invokeDot(format string) PostProcessor {
divert := awayFromTTY(format) divert := awayFromTTY(format)
return func(input *bytes.Buffer, output io.Writer, ui plugin.UI) error { return func(input *bytes.Buffer, output io.Writer, ui plugin.UI) error {
if _, err := exec.LookPath("dot"); err != nil {
ui.PrintErr("Cannot find dot, have you installed Graphviz?")
return err
}
cmd := exec.Command("dot", "-T"+format) cmd := exec.Command("dot", "-T"+format)
var buf bytes.Buffer var buf bytes.Buffer
cmd.Stdin, cmd.Stdout, cmd.Stderr = input, &buf, os.Stderr cmd.Stdin, cmd.Stdout, cmd.Stderr = input, &buf, os.Stderr
...@@ -174,6 +191,7 @@ func invokeVisualizer(interactive **bool, format PostProcessor, suffix string, v ...@@ -174,6 +191,7 @@ func invokeVisualizer(interactive **bool, format PostProcessor, suffix string, v
if err = format(input, tempFile, ui); err != nil { if err = format(input, tempFile, ui); err != nil {
return err return err
} }
tempFile.Close() // on windows, if the file is Open, start cannot access it.
// Try visualizers until one is successful // Try visualizers until one is successful
for _, v := range visualizers { for _, v := range visualizers {
// Separate command and arguments for exec.Command. // Separate command and arguments for exec.Command.
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment