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  }