| // Copyright 2014 Google Inc. All Rights Reserved. |
| // |
| // Licensed under the Apache License, Version 2.0 (the "License"); |
| // you may not use this file except in compliance with the License. |
| // You may obtain a copy of the License at |
| // |
| // http://www.apache.org/licenses/LICENSE-2.0 |
| // |
| // Unless required by applicable law or agreed to in writing, software |
| // distributed under the License is distributed on an "AS IS" BASIS, |
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| // See the License for the specific language governing permissions and |
| // limitations under the License. |
| |
| // pprof is a tool for collection, manipulation and visualization |
| // of performance profiles. |
| package main |
| |
| import ( |
| "fmt" |
| "os" |
| "strings" |
| "syscall" |
| |
| "github.com/chzyer/readline" |
| "github.com/google/pprof/driver" |
| ) |
| |
| func main() { |
| if err := driver.PProf(&driver.Options{UI: newUI()}); err != nil { |
| fmt.Fprintf(os.Stderr, "pprof: %v\n", err) |
| os.Exit(2) |
| } |
| } |
| |
| // readlineUI implements the driver.UI interface using the |
| // github.com/chzyer/readline library. |
| // This is contained in pprof.go to avoid adding the readline |
| // dependency in the vendored copy of pprof in the Go distribution, |
| // which does not use this file. |
| type readlineUI struct { |
| rl *readline.Instance |
| } |
| |
| func newUI() driver.UI { |
| rl, err := readline.New("") |
| if err != nil { |
| fmt.Fprintf(os.Stderr, "readline: %v", err) |
| return nil |
| } |
| return &readlineUI{ |
| rl: rl, |
| } |
| } |
| |
| // ReadLine returns a line of text (a command) read from the user. |
| // prompt is printed before reading the command. |
| func (r *readlineUI) ReadLine(prompt string) (string, error) { |
| r.rl.SetPrompt(prompt) |
| return r.rl.Readline() |
| } |
| |
| // Print shows a message to the user. |
| // It is printed over stderr as stdout is reserved for regular output. |
| func (r *readlineUI) Print(args ...interface{}) { |
| text := fmt.Sprint(args...) |
| if !strings.HasSuffix(text, "\n") { |
| text += "\n" |
| } |
| fmt.Fprint(r.rl.Stderr(), text) |
| } |
| |
| // PrintErr shows a message to the user, colored in red for emphasis. |
| // It is printed over stderr as stdout is reserved for regular output. |
| func (r *readlineUI) PrintErr(args ...interface{}) { |
| text := fmt.Sprint(args...) |
| if !strings.HasSuffix(text, "\n") { |
| text += "\n" |
| } |
| if readline.IsTerminal(int(syscall.Stderr)) { |
| text = colorize(text) |
| } |
| fmt.Fprint(r.rl.Stderr(), text) |
| } |
| |
| // colorize the msg using ANSI color escapes. |
| func colorize(msg string) string { |
| var red = 31 |
| var colorEscape = fmt.Sprintf("\033[0;%dm", red) |
| var colorResetEscape = "\033[0m" |
| return colorEscape + msg + colorResetEscape |
| } |
| |
| // IsTerminal returns whether the UI is known to be tied to an |
| // interactive terminal (as opposed to being redirected to a file). |
| func (r *readlineUI) IsTerminal() bool { |
| return readline.IsTerminal(int(syscall.Stdout)) |
| } |
| |
| // WantBrowser starts a browser on interactive mode. |
| func (r *readlineUI) WantBrowser() bool { |
| return r.IsTerminal() |
| } |
| |
| // SetAutoComplete instructs the UI to call complete(cmd) to obtain |
| // the auto-completion of cmd, if the UI supports auto-completion at all. |
| func (r *readlineUI) SetAutoComplete(complete func(string) string) { |
| // TODO: Implement auto-completion support. |
| } |