Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Golang requestId logging

Tags:

logging

go

I am writing a web application using golang. I am new to this language. I am trying to find what is the best way followed to log requestid in golang webapp. I have decided to use either go's log library (https://golang.org/pkg/log/) or logrus (https://github.com/sirupsen/logrus). It looks to me both of these does not provide anything related to requestId logging. So for generating requestId and using it through out the api's flow I have arrived to following approach for now

Use any one of the uid generation library listed here(https://golanglibs.com/search?q=id+generator&sort=top) to generate requestid. And set it in the context(https://golang.org/pkg/context/) at the start of processing the request by using http.Handler wrapper . And use this context in all the places wherever I want to log.

But to achieve this I need to pass the context object to all the functions where I need to log something. It does not sound good to me since I am touching all the function's prototype(i.e.adding context param). Is there any better way to do this? Something like ThreadLocal object. And it can be accessed from anywhere within the thread and using which we can get the request id wherever we need?

like image 684
Shanmugam Sundaram Avatar asked Aug 07 '18 07:08

Shanmugam Sundaram


1 Answers

Go deliberately does not support the equivalent of thread locals, as they often get abused and used incorrectly. A code should not depend on which goroutine executes it. It would also limit a function from launching further goroutines (or it would complicate things to also setup goroutine-specific context).

Instead if your functions need extra info (such as a logger), you have to pass the extra info them explicitly.

Of course a function may need many extra info, and the things needed may change or "grow" over time, so best is to create a wrapper for such extra info, and pass this single extra wrapper value. Should you need another info (e.g. a logged in user ID or a database connection or anything else), you may simply add that to the wrapper, and you don't have to change any signatures.

Whether this wrapper is a parameter, or you make your functions methods of the wrapper (and thus the wrapper will be the receiver) is entirely up to you and is only an implementation detail.

See related questions:

Why does a goroutine have no identity

Does Go have something like ThreadLocal from Java?

like image 163
icza Avatar answered Nov 15 '22 10:11

icza