Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2016 The LUCI Authors. All rights reserved. | 1 // Copyright 2016 The LUCI Authors. All rights reserved. |
| 2 // Use of this source code is governed under the Apache License, Version 2.0 | 2 // Use of this source code is governed under the Apache License, Version 2.0 |
| 3 // that can be found in the LICENSE file. | 3 // that can be found in the LICENSE file. |
| 4 | 4 |
| 5 package profiling | 5 package profiling |
| 6 | 6 |
| 7 import ( | 7 import ( |
| 8 "flag" | 8 "flag" |
| 9 "fmt" | 9 "fmt" |
| 10 "net" | 10 "net" |
| 11 "net/http" | 11 "net/http" |
| 12 httpProf "net/http/pprof" | 12 httpProf "net/http/pprof" |
|
Vadim Sh.
2016/12/18 22:44:37
This import registers routes in default net/http r
| |
| 13 "os" | 13 "os" |
| 14 "path/filepath" | 14 "path/filepath" |
| 15 "runtime" | 15 "runtime" |
| 16 "runtime/pprof" | 16 "runtime/pprof" |
| 17 "sync/atomic" | 17 "sync/atomic" |
| 18 | 18 |
| 19 » "github.com/julienschmidt/httprouter" | 19 » "github.com/luci/luci-go/server/router" |
| 20 | |
| 20 "github.com/luci/luci-go/common/clock" | 21 "github.com/luci/luci-go/common/clock" |
| 21 "github.com/luci/luci-go/common/errors" | 22 "github.com/luci/luci-go/common/errors" |
| 22 "github.com/luci/luci-go/common/logging" | 23 "github.com/luci/luci-go/common/logging" |
| 23 ) | 24 ) |
| 24 | 25 |
| 25 // Profiler helps setup and manage profiling | 26 // Profiler helps setup and manage profiling |
| 26 type Profiler struct { | 27 type Profiler struct { |
| 27 // BindHTTP, if not empty, is the HTTP address to bind to. | 28 // BindHTTP, if not empty, is the HTTP address to bind to. |
| 28 // | 29 // |
| 29 // Can also be configured with "-profile-bind-http" flag. | 30 // Can also be configured with "-profile-bind-http" flag. |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 64 // If we have an output directory, start our CPU profiling. | 65 // If we have an output directory, start our CPU profiling. |
| 65 if p.BindHTTP != "" { | 66 if p.BindHTTP != "" { |
| 66 if err := p.startHTTP(); err != nil { | 67 if err := p.startHTTP(); err != nil { |
| 67 return errors.Annotate(err).Reason("failed to start HTTP server").Err() | 68 return errors.Annotate(err).Reason("failed to start HTTP server").Err() |
| 68 } | 69 } |
| 69 } | 70 } |
| 70 return nil | 71 return nil |
| 71 } | 72 } |
| 72 | 73 |
| 73 func (p *Profiler) startHTTP() error { | 74 func (p *Profiler) startHTTP() error { |
| 74 » // Register paths: https://golang.org/src/net/http/pprof/pprof.go | 75 » r := router.New() |
| 75 » router := httprouter.New() | 76 » InstallHandlers(r, router.MiddlewareChain{}) |
| 76 » router.HandlerFunc("GET", "/debug/pprof/", httpProf.Index) | |
| 77 » router.HandlerFunc("GET", "/debug/pprof/cmdline", httpProf.Cmdline) | |
| 78 » router.HandlerFunc("GET", "/debug/pprof/profile", httpProf.Profile) | |
| 79 » router.HandlerFunc("GET", "/debug/pprof/symbol", httpProf.Symbol) | |
| 80 » router.HandlerFunc("GET", "/debug/pprof/trace", httpProf.Trace) | |
| 81 » for _, p := range pprof.Profiles() { | |
| 82 » » name := p.Name() | |
| 83 » » router.Handler("GET", fmt.Sprintf("/debug/pprof/%s", name), http Prof.Handler(name)) | |
| 84 » } | |
| 85 | 77 |
| 86 // Bind to our profiling port. | 78 // Bind to our profiling port. |
| 87 l, err := net.Listen("tcp4", p.BindHTTP) | 79 l, err := net.Listen("tcp4", p.BindHTTP) |
| 88 if err != nil { | 80 if err != nil { |
| 89 return errors.Annotate(err).Reason("failed to bind to TCP4 addre ss: %(addr)q"). | 81 return errors.Annotate(err).Reason("failed to bind to TCP4 addre ss: %(addr)q"). |
| 90 D("addr", p.BindHTTP).Err() | 82 D("addr", p.BindHTTP).Err() |
| 91 } | 83 } |
| 92 | 84 |
| 93 server := http.Server{ | 85 server := http.Server{ |
| 94 » » Handler: http.HandlerFunc(router.ServeHTTP), | 86 » » Handler: http.HandlerFunc(r.ServeHTTP), |
| 95 } | 87 } |
| 96 go func() { | 88 go func() { |
| 97 if err := server.Serve(l); err != nil { | 89 if err := server.Serve(l); err != nil { |
| 98 p.getLogger().Errorf("Error serving profile HTTP: %s", e rr) | 90 p.getLogger().Errorf("Error serving profile HTTP: %s", e rr) |
| 99 } | 91 } |
| 100 }() | 92 }() |
| 101 return nil | 93 return nil |
| 102 } | 94 } |
| 103 | 95 |
| 104 // Stop stops the Profiler's operations. | 96 // Stop stops the Profiler's operations. |
| (...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 151 counter := atomic.AddUint32(&p.pathCounter, 1) - 1 | 143 counter := atomic.AddUint32(&p.pathCounter, 1) - 1 |
| 152 return filepath.Join(p.Dir, fmt.Sprintf("%s_%d_%d.prof", base, now.Unix( ), counter)) | 144 return filepath.Join(p.Dir, fmt.Sprintf("%s_%d_%d.prof", base, now.Unix( ), counter)) |
| 153 } | 145 } |
| 154 | 146 |
| 155 func (p *Profiler) getLogger() logging.Logger { | 147 func (p *Profiler) getLogger() logging.Logger { |
| 156 if p.Logger != nil { | 148 if p.Logger != nil { |
| 157 return p.Logger | 149 return p.Logger |
| 158 } | 150 } |
| 159 return logging.Null | 151 return logging.Null |
| 160 } | 152 } |
| 153 | |
| 154 // InstallHandlers installs standard profiler paths into the supplied Router. | |
| 155 // | |
| 156 // See https://golang.org/src/net/http/pprof/pprof.go | |
| 157 func InstallHandlers(r *router.Router, base router.MiddlewareChain) { | |
| 158 r.GET("/debug/pprof/", base, wrapHandlerFunc(httpProf.Index)) | |
| 159 r.GET("/debug/pprof/cmdline", base, wrapHandlerFunc(httpProf.Cmdline)) | |
| 160 r.GET("/debug/pprof/profile", base, wrapHandlerFunc(httpProf.Profile)) | |
| 161 r.GET("/debug/pprof/symbol", base, wrapHandlerFunc(httpProf.Symbol)) | |
| 162 r.GET("/debug/pprof/trace", base, wrapHandlerFunc(httpProf.Trace)) | |
| 163 for _, p := range pprof.Profiles() { | |
| 164 name := p.Name() | |
| 165 r.GET(fmt.Sprintf("/debug/pprof/%s", name), base, wrapHandler(ht tpProf.Handler(name))) | |
| 166 } | |
| 167 } | |
| 168 | |
| 169 func wrapHandlerFunc(h http.HandlerFunc) router.Handler { | |
| 170 return func(c *router.Context) { | |
| 171 h(c.Writer, c.Request) | |
| 172 } | |
| 173 } | |
| 174 | |
| 175 func wrapHandler(h http.Handler) router.Handler { | |
| 176 return func(c *router.Context) { | |
| 177 h.ServeHTTP(c.Writer, c.Request) | |
| 178 } | |
| 179 } | |
| OLD | NEW |