How to do profiling on a live production (Heroku)

I am using _“net/http/pprof” for profiling.
I am able to do profiling on localhost. at port :6060 but not on production.
I am using Heroku. If my link is abc.herokuapp.com Then what to change for the following lines.

go func() {
log.Println(http.ListenAndServe(“localhost:6060”, nil))
}()

If i use the same line on production. on runnning the command 'go tool pprof http://localhost:6060/debug/pprof/profile
I got this error-
Get http://localhost:6060/debug/pprof/profile: dial tcp [::1]:6060: getsockopt: connection refused

Thanks in advance.

If you want to profile a program running on another machine, replace the word localhost with the DNS name or IP address of the machine that the program is running on.

Depending on where that machine is, you may have to adjust firewall rules to permit traffic to port 6060.

Thanks for the response. Now I am facing problem with Heroku. How to open a different port for my app. Is there any setting or code?

This question can be interpreted in two ways.

  1. how to change the port your Go application is listening on
  2. or, how to open an additional port for your Go application to listen on.

Which do you want to do?

It might be easier if you can post a small sample program which runs in your heroku account, we can guide you on how to modify it to allow remote profiling. Then you can apply that knowledge to your real program.

2 Likes

Thanks @dfc
I want the answer of the second question.
2) how to open an additional port for your Go application (On Heroku) to listen on.

Right now my app is running on the default port. I have not specified any port, But for profiling, I have to specify any port.

import (
             _"net/http/pprof"
    	"runtime/pprof"
    	"flag"
    	"net/http"
    )
    var cpuprofile = flag.String("cpuprofile", "", "write cpu profile `file`")
    var memprofile = flag.String("memprofile", "", "write memory profile to `file`")
    func main() {
    	if *cpuprofile != "" {
    		f, err := os.Create(*cpuprofile)
    		if err != nil {
    			log.Fatal("could not create CPU profile: ", err)
    		}
    		if err := pprof.StartCPUProfile(f); err != nil {
    			log.Fatal("could not start CPU profile: ", err)
    		}
    		defer pprof.StopCPUProfile()
    	}

    	if *memprofile != "" {
    		f, err := os.Create(*memprofile)
    		if err != nil {
    			log.Fatal("could not create memory profile: ", err)
    		}
    		runtime.GC() // get up-to-date statistics
    		if err := pprof.WriteHeapProfile(f); err != nil {
    			log.Fatal("could not write memory profile: ", err)
    		}

    		f.Close()
    	}
// Main problem occurs here 
go func() {
		log.Println(http.ListenAndServe("abc.herokuapp.com:6060", nil))
	}()

    }

Ok, let’s strip this problem down[quote=“PR101, post:5, topic:5311”]
// Main problem occurs here
go func() {
log.Println(http.ListenAndServe(“abc.herokuapp.com:6060”, nil))
}()
[/quote]

The problem with this part of the code is the ListenAndServe will run in another goroutine, while allowing the main goroutine to exit, terminating the program.

Try this instead

package main

import (
	"fmt"
	"html"
	"log"
	"net/http"
	_ "net/http/pprof"
)

func main() {
	http.HandleFunc("/bar", func(w http.ResponseWriter, r *http.Request) {
		fmt.Fprintf(w, "Hello, %q", html.EscapeString(r.URL.Path))
	})
	log.Println(http.ListenAndServe("abc.herokuapp.com:6060", nil))
}
1 Like

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.