github.com/wangyougui/gf/v2@v2.6.5/net/ghttp/ghttp_server_pprof.go (about)

     1  // Copyright GoFrame Author(https://goframe.org). All Rights Reserved.
     2  //
     3  // This Source Code Form is subject to the terms of the MIT License.
     4  // If a copy of the MIT was not distributed with this file,
     5  // You can obtain one at https://github.com/wangyougui/gf.
     6  
     7  package ghttp
     8  
     9  import (
    10  	netpprof "net/http/pprof"
    11  	runpprof "runtime/pprof"
    12  	"strings"
    13  
    14  	"github.com/wangyougui/gf/v2/internal/intlog"
    15  	"github.com/wangyougui/gf/v2/os/gview"
    16  )
    17  
    18  // utilPProf is the PProf interface implementer.
    19  type utilPProf struct{}
    20  
    21  const (
    22  	defaultPProfServerName = "pprof-server"
    23  	defaultPProfPattern    = "/debug/pprof"
    24  )
    25  
    26  // StartPProfServer starts and runs a new server for pprof.
    27  func StartPProfServer(port int, pattern ...string) {
    28  	s := GetServer(defaultPProfServerName)
    29  	s.EnablePProf(pattern...)
    30  	s.SetPort(port)
    31  	s.Run()
    32  }
    33  
    34  // EnablePProf enables PProf feature for server.
    35  func (s *Server) EnablePProf(pattern ...string) {
    36  	s.Domain(DefaultDomainName).EnablePProf(pattern...)
    37  }
    38  
    39  // EnablePProf enables PProf feature for server of specified domain.
    40  func (d *Domain) EnablePProf(pattern ...string) {
    41  	p := defaultPProfPattern
    42  	if len(pattern) > 0 && pattern[0] != "" {
    43  		p = pattern[0]
    44  	}
    45  	up := &utilPProf{}
    46  	_, _, uri, _ := d.server.parsePattern(p)
    47  	uri = strings.TrimRight(uri, "/")
    48  	d.Group(uri, func(group *RouterGroup) {
    49  		group.ALL("/*action", up.Index)
    50  		group.ALL("/cmdline", up.Cmdline)
    51  		group.ALL("/profile", up.Profile)
    52  		group.ALL("/symbol", up.Symbol)
    53  		group.ALL("/trace", up.Trace)
    54  	})
    55  }
    56  
    57  // Index shows the PProf index page.
    58  func (p *utilPProf) Index(r *Request) {
    59  	var (
    60  		ctx      = r.Context()
    61  		profiles = runpprof.Profiles()
    62  		action   = r.Get("action").String()
    63  		data     = map[string]interface{}{
    64  			"uri":      strings.TrimRight(r.URL.Path, "/") + "/",
    65  			"profiles": profiles,
    66  		}
    67  	)
    68  	if len(action) == 0 {
    69  		buffer, _ := gview.ParseContent(r.Context(), `
    70              <html>
    71              <head>
    72                  <title>GoFrame PProf</title>
    73              </head>
    74              {{$uri := .uri}}
    75              <body>
    76                  profiles:<br>
    77                  <table>
    78                      {{range .profiles}}
    79  						<tr>
    80  							<td align=right>{{.Count}}</td>
    81  							<td><a href="{{$uri}}{{.Name}}?debug=1">{{.Name}}</a></td>
    82  						<tr>
    83  					{{end}}
    84                  </table>
    85                  <br><a href="{{$uri}}goroutine?debug=2">full goroutine stack dump</a><br>
    86              </body>
    87              </html>
    88              `, data)
    89  		r.Response.Write(buffer)
    90  		return
    91  	}
    92  	for _, p := range profiles {
    93  		if p.Name() == action {
    94  			if err := p.WriteTo(r.Response.Writer, r.GetRequest("debug").Int()); err != nil {
    95  				intlog.Errorf(ctx, `%+v`, err)
    96  			}
    97  			break
    98  		}
    99  	}
   100  }
   101  
   102  // Cmdline responds with the running program's
   103  // command line, with arguments separated by NUL bytes.
   104  // The package initialization registers it as /debug/pprof/cmdline.
   105  func (p *utilPProf) Cmdline(r *Request) {
   106  	netpprof.Cmdline(r.Response.Writer, r.Request)
   107  }
   108  
   109  // Profile responds with the pprof-formatted cpu profile.
   110  // Profiling lasts for duration specified in seconds GET parameter, or for 30 seconds if not specified.
   111  // The package initialization registers it as /debug/pprof/profile.
   112  func (p *utilPProf) Profile(r *Request) {
   113  	netpprof.Profile(r.Response.Writer, r.Request)
   114  }
   115  
   116  // Symbol looks up the program counters listed in the request,
   117  // responding with a table mapping program counters to function names.
   118  // The package initialization registers it as /debug/pprof/symbol.
   119  func (p *utilPProf) Symbol(r *Request) {
   120  	netpprof.Symbol(r.Response.Writer, r.Request)
   121  }
   122  
   123  // Trace responds with the execution trace in binary form.
   124  // Tracing lasts for duration specified in seconds GET parameter, or for 1 second if not specified.
   125  // The package initialization registers it as /debug/pprof/trace.
   126  func (p *utilPProf) Trace(r *Request) {
   127  	netpprof.Trace(r.Response.Writer, r.Request)
   128  }