X-Git-Url: https://git.arvados.org/arvados.git/blobdiff_plain/41e15e626cc301d867c48ebb1f945bbec6b7d555..63b1a5c12557bb11505f9dcfcc955f328b51e118:/sdk/go/httpserver/logger.go diff --git a/sdk/go/httpserver/logger.go b/sdk/go/httpserver/logger.go index 9577718c76..8886f9517d 100644 --- a/sdk/go/httpserver/logger.go +++ b/sdk/go/httpserver/logger.go @@ -9,8 +9,9 @@ import ( "net/http" "time" - "git.curoverse.com/arvados.git/sdk/go/stats" - "github.com/Sirupsen/logrus" + "git.arvados.org/arvados.git/sdk/go/ctxlog" + "git.arvados.org/arvados.git/sdk/go/stats" + "github.com/sirupsen/logrus" ) type contextKey struct { @@ -19,18 +20,23 @@ type contextKey struct { var ( requestTimeContextKey = contextKey{"requestTime"} - loggerContextKey = contextKey{"logger"} ) +// HandlerWithContext returns an http.Handler that changes the request +// context to ctx (replacing http.Server's default +// context.Background()), then calls next. +func HandlerWithContext(ctx context.Context, next http.Handler) http.Handler { + return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + next.ServeHTTP(w, r.WithContext(ctx)) + }) +} + // LogRequests wraps an http.Handler, logging each request and -// response via logger. -func LogRequests(logger logrus.FieldLogger, h http.Handler) http.Handler { - if logger == nil { - logger = logrus.StandardLogger() - } +// response. +func LogRequests(h http.Handler) http.Handler { return http.HandlerFunc(func(wrapped http.ResponseWriter, req *http.Request) { w := &responseTimer{ResponseWriter: WrapResponseWriter(wrapped)} - lgr := logger.WithFields(logrus.Fields{ + lgr := ctxlog.FromContext(req.Context()).WithFields(logrus.Fields{ "RequestID": req.Header.Get("X-Request-Id"), "remoteAddr": req.RemoteAddr, "reqForwardedFor": req.Header.Get("X-Forwarded-For"), @@ -42,7 +48,7 @@ func LogRequests(logger logrus.FieldLogger, h http.Handler) http.Handler { }) ctx := req.Context() ctx = context.WithValue(ctx, &requestTimeContextKey, time.Now()) - ctx = context.WithValue(ctx, &loggerContextKey, lgr) + ctx = ctxlog.Context(ctx, lgr) req = req.WithContext(ctx) logRequest(w, req, lgr) @@ -52,11 +58,7 @@ func LogRequests(logger logrus.FieldLogger, h http.Handler) http.Handler { } func Logger(req *http.Request) logrus.FieldLogger { - if lgr, ok := req.Context().Value(&loggerContextKey).(logrus.FieldLogger); ok { - return lgr - } else { - return logrus.StandardLogger() - } + return ctxlog.FromContext(req.Context()) } func logRequest(w *responseTimer, req *http.Request, lgr *logrus.Entry) { @@ -66,21 +68,31 @@ func logRequest(w *responseTimer, req *http.Request, lgr *logrus.Entry) { func logResponse(w *responseTimer, req *http.Request, lgr *logrus.Entry) { if tStart, ok := req.Context().Value(&requestTimeContextKey).(time.Time); ok { tDone := time.Now() + writeTime := w.writeTime + if !w.wrote { + // Empty response body. Header was sent when + // handler exited. + writeTime = tDone + } lgr = lgr.WithFields(logrus.Fields{ "timeTotal": stats.Duration(tDone.Sub(tStart)), - "timeToStatus": stats.Duration(w.writeTime.Sub(tStart)), - "timeWriteBody": stats.Duration(tDone.Sub(w.writeTime)), + "timeToStatus": stats.Duration(writeTime.Sub(tStart)), + "timeWriteBody": stats.Duration(tDone.Sub(writeTime)), }) } respCode := w.WroteStatus() if respCode == 0 { respCode = http.StatusOK } - lgr.WithFields(logrus.Fields{ + fields := logrus.Fields{ "respStatusCode": respCode, "respStatus": http.StatusText(respCode), "respBytes": w.WroteBodyBytes(), - }).Info("response") + } + if respCode >= 400 { + fields["respBody"] = string(w.Sniffed()) + } + lgr.WithFields(fields).Info("response") } type responseTimer struct {