diff --git a/commonctx/logger.go b/commonctx/logger.go index fa498db..e58e8ee 100644 --- a/commonctx/logger.go +++ b/commonctx/logger.go @@ -19,12 +19,12 @@ func GetLogger(ctx context.Context) *logrus.Entry { return nil } -func GetLoggerWithFields(ctx context.Context, fields logrus.Fields) *logrus.Entry { +func GetContextAndLoggerWithFields(ctx context.Context, fields logrus.Fields) (context.Context, *logrus.Entry) { if log := ctx.Value(LoggerKey); log != nil { log := log.(*logrus.Entry) log = log.WithFields(fields) - AddMainLogger(ctx, log) - return log + ctx = AddMainLogger(ctx, log) + return ctx, log } - return nil + return ctx, nil } diff --git a/middleware/recovery.go b/middleware/recovery.go index d38120c..82a71fc 100644 --- a/middleware/recovery.go +++ b/middleware/recovery.go @@ -21,15 +21,14 @@ func (rm *recoveryMiddleware) ServeHTTP(w http.ResponseWriter, r *http.Request) defer func() { if err := recover(); err != nil { // log the error - log := commonctx.GetLoggerWithFields(r.Context(), logrus.Fields{ + ctx, log := commonctx.GetContextAndLoggerWithFields(r.Context(), logrus.Fields{ "error": err, "stacktrace": fmt.Sprintf("%v\n%s", err, getStackrace()), }) - if log == nil { - fmt.Print("Impossible to log the panic as the logger is not part of the context\n") - } else { + if log != nil { log.Error("A Panic happened and has been caught") } + r = r.WithContext(ctx) // execute the recovery function rm.respFunc(w, r) } diff --git a/middleware/request_id.go b/middleware/request_id.go new file mode 100644 index 0000000..c1c1fe2 --- /dev/null +++ b/middleware/request_id.go @@ -0,0 +1,38 @@ +package middleware + +import ( + "net/http" + + "github.com/google/uuid" +) + +const requestIDHeaderKey = "X-Request-ID" + +type requestIDMiddleware struct { + handler http.Handler +} + +func (rm *requestIDMiddleware) ServeHTTP(w http.ResponseWriter, r *http.Request) { + requestID := r.Header.Get(requestIDHeaderKey) + if _, err := uuid.Parse(requestID); err != nil { + // no request ID or invalid. let's generate a new one + requestID = uuid.New().String() + } + + // XXX: Add request_id to the context, push the context to r & edit logger middleware to add the request_id as fields + + // add the request ID to the response query + w.Header().Set(requestIDHeaderKey, requestID) + + // and exec the next handler + rm.handler.ServeHTTP(w, r) +} + +// NewRequestIDMiddleware will declare a new middleware on the provided handler. It will analyse the incoming +// query to find a x-request-id header. It will had it to the response and also to the context. +// If request-id header doesn't exist. A new one will be generated. +func NewRequestIDMiddleware(h http.Handler) http.Handler { + return &requestIDMiddleware{ + handler: h, + } +}