github.com/FenixAra/go@v0.0.0-20170127160404-96ea0918e670/src/cmd/trace/main.go (about) 1 // Copyright 2014 The Go Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 /* 6 Trace is a tool for viewing trace files. 7 8 Trace files can be generated with: 9 - runtime/trace.Start 10 - net/http/pprof package 11 - go test -trace 12 13 Example usage: 14 Generate a trace file with 'go test': 15 go test -trace trace.out pkg 16 View the trace in a web browser: 17 go tool trace trace.out 18 Generate a pprof-like profile from the trace: 19 go tool trace -pprof=TYPE trace.out > TYPE.pprof 20 21 Supported profile types are: 22 - net: network blocking profile 23 - sync: synchronization blocking profile 24 - syscall: syscall blocking profile 25 - sched: scheduler latency profile 26 */ 27 package main 28 29 import ( 30 "bufio" 31 "cmd/internal/browser" 32 "flag" 33 "fmt" 34 "html/template" 35 "internal/trace" 36 "io" 37 "log" 38 "net" 39 "net/http" 40 "os" 41 "sync" 42 ) 43 44 const usageMessage = "" + 45 `Usage of 'go tool trace': 46 Given a trace file produced by 'go test': 47 go test -trace=trace.out pkg 48 49 Open a web browser displaying trace: 50 go tool trace [flags] [pkg.test] trace.out 51 52 Generate a pprof-like profile from the trace: 53 go tool trace -pprof=TYPE [pkg.test] trace.out 54 55 [pkg.test] argument is required for traces produced by Go 1.6 and below. 56 Go 1.7 does not require the binary argument. 57 58 Supported profile types are: 59 - net: network blocking profile 60 - sync: synchronization blocking profile 61 - syscall: syscall blocking profile 62 - sched: scheduler latency profile 63 64 Flags: 65 -http=addr: HTTP service address (e.g., ':6060') 66 -pprof=type: print a pprof-like profile instead 67 ` 68 69 var ( 70 httpFlag = flag.String("http", "localhost:0", "HTTP service address (e.g., ':6060')") 71 pprofFlag = flag.String("pprof", "", "print a pprof-like profile instead") 72 73 // The binary file name, left here for serveSVGProfile. 74 programBinary string 75 traceFile string 76 ) 77 78 func main() { 79 flag.Usage = func() { 80 fmt.Fprintln(os.Stderr, usageMessage) 81 os.Exit(2) 82 } 83 flag.Parse() 84 85 // Go 1.7 traces embed symbol info and does not require the binary. 86 // But we optionally accept binary as first arg for Go 1.5 traces. 87 switch flag.NArg() { 88 case 1: 89 traceFile = flag.Arg(0) 90 case 2: 91 programBinary = flag.Arg(0) 92 traceFile = flag.Arg(1) 93 default: 94 flag.Usage() 95 } 96 97 var pprofFunc func(io.Writer) error 98 switch *pprofFlag { 99 case "net": 100 pprofFunc = pprofIO 101 case "sync": 102 pprofFunc = pprofBlock 103 case "syscall": 104 pprofFunc = pprofSyscall 105 case "sched": 106 pprofFunc = pprofSched 107 } 108 if pprofFunc != nil { 109 if err := pprofFunc(os.Stdout); err != nil { 110 dief("failed to generate pprof: %v\n", err) 111 } 112 os.Exit(0) 113 } 114 if *pprofFlag != "" { 115 dief("unknown pprof type %s\n", *pprofFlag) 116 } 117 118 ln, err := net.Listen("tcp", *httpFlag) 119 if err != nil { 120 dief("failed to create server socket: %v\n", err) 121 } 122 123 log.Printf("Parsing trace...") 124 events, err := parseEvents() 125 if err != nil { 126 dief("%v\n", err) 127 } 128 129 log.Printf("Serializing trace...") 130 params := &traceParams{ 131 events: events, 132 endTime: int64(1<<63 - 1), 133 } 134 data, err := generateTrace(params) 135 if err != nil { 136 dief("%v\n", err) 137 } 138 139 log.Printf("Splitting trace...") 140 ranges = splitTrace(data) 141 142 log.Printf("Opening browser") 143 if !browser.Open("http://" + ln.Addr().String()) { 144 fmt.Fprintf(os.Stderr, "Trace viewer is listening on http://%s\n", ln.Addr().String()) 145 } 146 147 // Start http server. 148 http.HandleFunc("/", httpMain) 149 err = http.Serve(ln, nil) 150 dief("failed to start http server: %v\n", err) 151 } 152 153 var ranges []Range 154 155 var loader struct { 156 once sync.Once 157 events []*trace.Event 158 err error 159 } 160 161 func parseEvents() ([]*trace.Event, error) { 162 loader.once.Do(func() { 163 tracef, err := os.Open(traceFile) 164 if err != nil { 165 loader.err = fmt.Errorf("failed to open trace file: %v", err) 166 return 167 } 168 defer tracef.Close() 169 170 // Parse and symbolize. 171 events, err := trace.Parse(bufio.NewReader(tracef), programBinary) 172 if err != nil { 173 loader.err = fmt.Errorf("failed to parse trace: %v", err) 174 return 175 } 176 loader.events = events 177 }) 178 return loader.events, loader.err 179 } 180 181 // httpMain serves the starting page. 182 func httpMain(w http.ResponseWriter, r *http.Request) { 183 if err := templMain.Execute(w, ranges); err != nil { 184 http.Error(w, err.Error(), http.StatusInternalServerError) 185 return 186 } 187 } 188 189 var templMain = template.Must(template.New("").Parse(` 190 <html> 191 <body> 192 {{if $}} 193 {{range $e := $}} 194 <a href="/trace?start={{$e.Start}}&end={{$e.End}}">View trace ({{$e.Name}})</a><br> 195 {{end}} 196 <br> 197 {{else}} 198 <a href="/trace">View trace</a><br> 199 {{end}} 200 <a href="/goroutines">Goroutine analysis</a><br> 201 <a href="/io">Network blocking profile</a><br> 202 <a href="/block">Synchronization blocking profile</a><br> 203 <a href="/syscall">Syscall blocking profile</a><br> 204 <a href="/sched">Scheduler latency profile</a><br> 205 </body> 206 </html> 207 `)) 208 209 func dief(msg string, args ...interface{}) { 210 fmt.Fprintf(os.Stderr, msg, args...) 211 os.Exit(1) 212 }