package log import ( "context" "net/http" "time" "github.com/kjk/betterguid" "github.com/sirupsen/logrus" ) type contextKey string // Request wraps the given HTTP handler with a log entry that logs how long it has been running. It also // makes a preconfigured logger for the request available as part of the request context. func Request(next http.Handler) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { remote := r.Header.Get("X-Forwarded-For") if remote == "" { remote = r.RemoteAddr } log := logrus.WithFields(logrus.Fields{ "method": r.Method, "url": r.URL, "remote": remote, "id": betterguid.New(), }) start := time.Now() defer func() { d := time.Since(start) log.WithField("duration", d).Info("request handled") }() key := contextKey("logger") ctx := context.WithValue(r.Context(), key, log) next.ServeHTTP(w, r.WithContext(ctx)) }) } // Get returns the logger for the given HTTP request. If r has no logger, a usable logger without fields is returned. func Get(r *http.Request) *logrus.Entry { return GetContext(r.Context()) } // GetContext returns the logger for the given context. If ctx has no logger, a usable logger without fields is returned. func GetContext(ctx context.Context) *logrus.Entry { val := ctx.Value(contextKey("logger")) if val == nil { return logrus.NewEntry(logrus.New()) } return val.(*logrus.Entry) }