diff options
Diffstat (limited to 'libgo/go/net/http/pprof/pprof.go')
-rw-r--r-- | libgo/go/net/http/pprof/pprof.go | 51 |
1 files changed, 39 insertions, 12 deletions
diff --git a/libgo/go/net/http/pprof/pprof.go b/libgo/go/net/http/pprof/pprof.go index 05d0890fdf3..12c7599ab0f 100644 --- a/libgo/go/net/http/pprof/pprof.go +++ b/libgo/go/net/http/pprof/pprof.go @@ -37,6 +37,11 @@ // // wget http://localhost:6060/debug/pprof/trace?seconds=5 // +// Or to look at the holders of contended mutexes, after calling +// runtime.SetMutexProfileFraction in your program: +// +// go tool pprof http://localhost:6060/debug/pprof/mutex +// // To view all available profiles, open http://localhost:6060/debug/pprof/ // in your browser. // @@ -57,6 +62,7 @@ import ( "os" "runtime" "runtime/pprof" + "runtime/trace" "strconv" "strings" "time" @@ -89,6 +95,11 @@ func sleep(w http.ResponseWriter, d time.Duration) { } } +func durationExceedsWriteTimeout(r *http.Request, seconds float64) bool { + srv, ok := r.Context().Value(http.ServerContextKey).(*http.Server) + return ok && srv.WriteTimeout != 0 && seconds >= srv.WriteTimeout.Seconds() +} + // Profile responds with the pprof-formatted cpu profile. // The package initialization registers it as /debug/pprof/profile. func Profile(w http.ResponseWriter, r *http.Request) { @@ -97,6 +108,14 @@ func Profile(w http.ResponseWriter, r *http.Request) { sec = 30 } + if durationExceedsWriteTimeout(r, float64(sec)) { + w.Header().Set("Content-Type", "text/plain; charset=utf-8") + w.Header().Set("X-Go-Pprof", "1") + w.WriteHeader(http.StatusBadRequest) + fmt.Fprintln(w, "profile duration exceeds server's WriteTimeout") + return + } + // Set Content Type assuming StartCPUProfile will work, // because if it does it starts writing. w.Header().Set("Content-Type", "application/octet-stream") @@ -105,6 +124,7 @@ func Profile(w http.ResponseWriter, r *http.Request) { // Can change header back to text content // and send error code. w.Header().Set("Content-Type", "text/plain; charset=utf-8") + w.Header().Set("X-Go-Pprof", "1") w.WriteHeader(http.StatusInternalServerError) fmt.Fprintf(w, "Could not enable CPU profiling: %s\n", err) return @@ -122,20 +142,28 @@ func Trace(w http.ResponseWriter, r *http.Request) { sec = 1 } + if durationExceedsWriteTimeout(r, sec) { + w.Header().Set("Content-Type", "text/plain; charset=utf-8") + w.Header().Set("X-Go-Pprof", "1") + w.WriteHeader(http.StatusBadRequest) + fmt.Fprintln(w, "profile duration exceeds server's WriteTimeout") + return + } + // Set Content Type assuming trace.Start will work, // because if it does it starts writing. w.Header().Set("Content-Type", "application/octet-stream") - w.Write([]byte("tracing not yet supported with gccgo")) - // if err := trace.Start(w); err != nil { - // // trace.Start failed, so no writes yet. - // // Can change header back to text content and send error code. - // w.Header().Set("Content-Type", "text/plain; charset=utf-8") - // w.WriteHeader(http.StatusInternalServerError) - // fmt.Fprintf(w, "Could not enable tracing: %s\n", err) - // return - // } - // sleep(w, time.Duration(sec*float64(time.Second))) - // trace.Stop() + if err := trace.Start(w); err != nil { + // trace.Start failed, so no writes yet. + // Can change header back to text content and send error code. + w.Header().Set("Content-Type", "text/plain; charset=utf-8") + w.Header().Set("X-Go-Pprof", "1") + w.WriteHeader(http.StatusInternalServerError) + fmt.Fprintf(w, "Could not enable tracing: %s\n", err) + return + } + sleep(w, time.Duration(sec*float64(time.Second))) + trace.Stop() } // Symbol looks up the program counters listed in the request, @@ -207,7 +235,6 @@ func (name handler) ServeHTTP(w http.ResponseWriter, r *http.Request) { runtime.GC() } p.WriteTo(w, debug) - return } // Index responds with the pprof-formatted profile named by the request. |