Log with context in golang http server


(Ram Mohan) #1

Is there a way to log all the related logs with some context. say some unique ID for that session/request.

  1. HTTP handle Function may call some other common functions (which may be call by other Handler functions) and all those function logs should have this unique ID to relate all the logs of that session.

(Norbert Melzer) #2

We have some HTTP tool at work that does exactly that.

I recall we use zap for logging and “derive” a new logger using With() which is then injected into a request context.

I will extract the relevant code path for you once I can access the VPN.


(Ram Mohan) #3

Great, will be waiting for your reply :slight_smile:


(Norbert Melzer) #4

Sorry to leave you waiting, I still can’t access our companies VPN due to some firmware update on our firewalls. If our IT departement doesn’t fix that in the next 2 hours I’ll have to do an office day rather than remote. So I think I should be able to post our solution to that problem in ~4 hours or sooner.


(Norbert Melzer) #5

Its basically this:

package service

import (
	"net/http"
	"sync"
	"time"

	"go.uber.org/zap"
)

type HandleFunc func(*zap.Logger, http.ResponseWriter, *http.Request)

type Handler struct {
	f HandleFunc
}

func (h *Handler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	rid := requestID()

	logger := zap.L().With(zap.String("request_url", r.RequestURI), zap.Int64("request_id", rid), zap.String("method", r.Method))

	logger.Info("Received request")
	start := time.Now()

	h.f(logger, w, r)

	duration := time.Since(start)
	logger.Info("Finished request", zap.Duration("duration", duration))
}

func NewHandler(f HandleFunc) *Handler {
	return &Handler{f: f}
}

And then we use it like this:

http.Handle("/foo", service.NewHandler(service.Foo))
zap.L().Panic("HTTP server crashed", zap.Error(http.ListenAndServe(addr, nil)))

(Ram Mohan) #6

I am using mux and handlers for routing and CORS, is there any way we can pass on this logger to those handlers?

looks like we are overriding HandleFunc and Handler here in this example.


(Norbert Melzer) #7

Sorry, we are not using mux, in our case it’s just 2 endpoints that needed to be served and that way was a suitable workaround.

You need to check whether or not you can use a similar technic with mux.


(Ram Mohan) #8

Thanks a lot. i will figure it out. and post if a find one.