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 }