1

I'm trying to find a way to add a correlation/request id for logs in our project to make it easier to navigate through them and debug when some issues occur. I found this article. From the example there, there is a middleware to add the correlationID and then retrieve it in some handler function.

Middleware function:

const ContextKeyRequestID ContextKey = "requestID"

func reqIDMiddleware1(next http.Handler) http.Handler {
    return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {

        ctx := r.Context()
        
        id := uuid.New()

        ctx = context.WithValue(ctx, ContextKeyRequestID, id.String())

        r = r.WithContext(ctx)
        
        log.Debugf("Incoming request %s %s %s %s", r.Method, r.RequestURI, r.RemoteAddr, id.String())

        next.ServeHTTP(w, r)
        
        log.Debugf("Finished handling http req. %s", id.String())
    })
}

Handler:

const LogFieldKeyRequestID = "requestID"

func handleSomeRequest() http.HandlerFunc {
    return func(w http.ResponseWriter, r *http.Request) {

        ctx := r.Context()

        reqIDRaw := ctx.Value(ContextKeyRequestID) // reqIDRaw at this point is of type 'interface{}'
        
        reqID, ok := reqIDRaw.(string)
        if !ok {
            // handler error
        }
        
        // if reached here, reqID is ready to be used
        
        // let's use it with logrus FieldLogger!
        logger := log.WithField(LogFieldKeyRequestID, reqID)
        
        // Do something, then log what you did
        logger.Debugf("What I just did!")
        
        // Do more, log more. Handle this request seriously
    }
}

But I was wondering if there is a way to achieve this without having to refactor all the existing handlers and changing the logging functionality, through some automatic configuration that would add id for each log, in my case our project is quite big, and doing it in the way described above would require a lot of changes.

marc_s
  • 732,580
  • 175
  • 1,330
  • 1,459
indee423
  • 121
  • 1
  • 11
  • 1
    I doubt there is, and I couldn't image how another solution should work anyway. If you could change it on a global level, it would lead to consistency problem when there are multiple requests at the same time. I'ld recommend you to wrap all you `Handlers` in a `WithLogger` middleware which creates a logger with that correlation key and puts it into the request context, so every `Handler` can retrieve it from there with something like `logger := correlationLogger.GetLogger(ctx)`. – NotX Jan 04 '23 at 18:12

1 Answers1

2

Have you looked at WithContext and Hooks?

You still have to modify your code but you can centralize some behaviours.

https://go.dev/play/p/4YxJMK6Zl5D