Profiling Go web application built with Gorilla's mux with net/http/pprof

user983716 - Thanks for your question and solution!

I was not able to use the links from the web index (http://[my-server]/debug/pprof), until I added a few lines to your solution, like so:

...

func AttachProfiler(router *mux.Router) {
    router.HandleFunc("/debug/pprof/", pprof.Index)
    router.HandleFunc("/debug/pprof/cmdline", pprof.Cmdline)
    router.HandleFunc("/debug/pprof/profile", pprof.Profile)
    router.HandleFunc("/debug/pprof/symbol", pprof.Symbol)

    // Manually add support for paths linked to by index page at /debug/pprof/
    router.Handle("/debug/pprof/goroutine", pprof.Handler("goroutine"))
    router.Handle("/debug/pprof/heap", pprof.Handler("heap"))
    router.Handle("/debug/pprof/threadcreate", pprof.Handler("threadcreate"))
    router.Handle("/debug/pprof/block", pprof.Handler("block"))
}

...

If anyone has the same problem, I hope this helps!


My preferred method for this is to just let net/http/pprof register itself to http.DefaultServeMux, and then pass all requests starting with /debug/pprof/ along:

package main

import (
    "net/http"
    _ "net/http/pprof"

    "github.com/gorilla/mux"
)

func main() {
    router := mux.NewRouter()
    router.PathPrefix("/debug/pprof/").Handler(http.DefaultServeMux)
    if err := http.ListenAndServe(":6060", router); err != nil {
        panic(err)
    }
}

I find that this approach is a lot more stable than one that depends on the implementation of a hidden initialization method, and also guarantees that you didn't miss anything.


Sorry for that question. The answer is in the init() function of pprof. One just need to add 4 functions from pprof to the mux router. Here is the fixed code from above.

package main

import (
    "fmt"
    "github.com/gorilla/mux"
    "math"

    "net/http"
)
import "net/http/pprof"

func AttachProfiler(router *mux.Router) {
    router.HandleFunc("/debug/pprof/", pprof.Index)
    router.HandleFunc("/debug/pprof/cmdline", pprof.Cmdline)
    router.HandleFunc("/debug/pprof/profile", pprof.Profile)
    router.HandleFunc("/debug/pprof/symbol", pprof.Symbol)
}

func SayHello(w http.ResponseWriter, r *http.Request) {
    for i := 0; i < 1000000; i++ {
        math.Pow(36, 89)
    }
    fmt.Fprint(w, "Hello!")
}

func main() {
    r := mux.NewRouter()
    AttachProfiler(r)
    r.HandleFunc("/hello", SayHello)
    http.ListenAndServe(":6060", r)
}

Tags:

Go