| // Copyright 2019 The Go Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style |
| // license that can be found in the LICENSE file. |
| |
| package debug |
| |
| import ( |
| "bytes" |
| "context" |
| "html/template" |
| "log" |
| "net" |
| "net/http" |
| _ "net/http/pprof" // pull in the standard pprof handlers |
| ) |
| |
| func init() { |
| http.HandleFunc("/", Render(mainTmpl, nil)) |
| http.HandleFunc("/debug/", Render(debugTmpl, nil)) |
| http.HandleFunc("/info", Render(infoTmpl, getInfo)) |
| } |
| |
| func getInfo(r *http.Request) interface{} { |
| buf := &bytes.Buffer{} |
| PrintVersionInfo(buf, true, HTML) |
| return template.HTML(buf.String()) |
| } |
| |
| // Serve starts and runs a debug server in the background. |
| // It also logs the port the server starts on, to allow for :0 auto assigned |
| // ports. |
| func Serve(ctx context.Context, addr string) error { |
| if addr == "" { |
| return nil |
| } |
| listener, err := net.Listen("tcp", addr) |
| if err != nil { |
| return err |
| } |
| log.Printf("Debug serving on port: %d", listener.Addr().(*net.TCPAddr).Port) |
| go func() { |
| if err := http.Serve(listener, nil); err != nil { |
| log.Printf("Debug server failed with %v", err) |
| return |
| } |
| log.Printf("Debug server finished") |
| }() |
| return nil |
| } |
| |
| func Render(tmpl *template.Template, fun func(*http.Request) interface{}) func(http.ResponseWriter, *http.Request) { |
| return func(w http.ResponseWriter, r *http.Request) { |
| var data interface{} |
| if fun != nil { |
| data = fun(r) |
| } |
| if err := tmpl.Execute(w, data); err != nil { |
| log.Print(err) |
| } |
| } |
| } |
| |
| var BaseTemplate = template.Must(template.New("").Parse(` |
| <html> |
| <head> |
| <title>{{template "title"}}</title> |
| <style> |
| .profile-name{ |
| display:inline-block; |
| width:6rem; |
| } |
| </style> |
| </head> |
| <body> |
| <a href="/">Main</a> |
| <a href="/info">Info</a> |
| <a href="/debug/">Debug</a> |
| <hr> |
| <h1>{{template "title" .}}</h1> |
| {{block "body" .}} |
| Unknown page |
| {{end}} |
| </body> |
| </html> |
| `)) |
| |
| var mainTmpl = template.Must(template.Must(BaseTemplate.Clone()).Parse(` |
| {{define "title"}}GoPls server information{{end}} |
| {{define "body"}} |
| {{end}} |
| `)) |
| |
| var infoTmpl = template.Must(template.Must(BaseTemplate.Clone()).Parse(` |
| {{define "title"}}GoPls version information{{end}} |
| {{define "body"}} |
| {{.}} |
| {{end}} |
| `)) |
| |
| var debugTmpl = template.Must(template.Must(BaseTemplate.Clone()).Parse(` |
| {{define "title"}}GoPls Debug pages{{end}} |
| {{define "body"}} |
| <A href="/debug/pprof">Profiling</A> |
| {{end}} |
| `)) |