Monitoring apps with expvar and Go

Piotr Rojek
2 min readDec 12, 2015

--

There are many ways to do monitoring and integration with Go apps. One of the ways is to expose variables through HTTP/JSON protocol with the help of `expvar`.

Let’s make a very simple web app:

package main
import ( “fmt” “net/http”)
func handler(w http.ResponseWriter, r *http.Request) { fmt.Fprintf(w, “Hey! I love %s!\n”, r.URL.Path[1:])}
func main() { http.HandleFunc(“/”, handler) http.ListenAndServe(“:8080”, nil)}

So when you visit e.g. http://localhost:8080/Go you will see “Hey! I love Go!”.

With that done — let’s expose some variables. Firstly add `expvar` to our import section. Then let’s declare and implement a simple counter. Add this in the root of the document:

var counter = expvar.NewInt(“counter”)

Then in the handler before `fmt.Fprintf` call:

counter.Add(1)

Now if run your app and go to `http://localhost:8080/debug/vars` — you should see your counter along with `memstats` and other statstics.

Let’s add more metrics. Declare `expvar` map where we can store hits for each request:

var hits = expvar.NewMap(“hits”).Init()

Add this after calling the counter in the handler:

hits.Add(r.URL.Path[1:], 1)

which means we’re incrementing the counter for specific address. You can also show the counter in the app itself:

fmt.Fprintln(w, “People loving it:”, hits.Get(r.URL.Path[1:]))

If you go your app and hit different endpoints a few times you could see the counter incrementing.

One thing to remember is once you restart you app the statistics are gone, so it’s your responsibility to preserve the data you care about. Depending on the case you may want to wrap the `expvar` as a middleware.

There are a lot of tools to visualize these statistics, e.g. written in Go expvarmon.

--

--

Piotr Rojek

Devouted Gopher. Deep Learning enthusiast. I love Open Source and knowledge sharing. Przemyśl, PL / Los Angeles, CA / København, DK.