Loguru: How to give a unified id to sign related log

Created on 24 Jan 2019  ·  6Comments  ·  Source: Delgan/loguru

hi,I read through the readme and api reference but did not find out how to give a unified id to sign related log .

just like this
default

with unified log_id I can parse and get related log generated by a http request or a func.

I have a producer-consumer model. When the consumer get data and start to work, i want to give a
unified log_id ,and the consumer will call many functions, i need the all process log have unified log_id.

question

All 6 comments

I find this, logger.bind can do
logger.add(writer, format="{extra[a]} {message}")
logger_bound = logger.bind(a=0)

but it return a new logger object.
a anoner module need get a global logger_bound? How can i do it?

Hello @zhouxiaomao.

Indeed, the .bind() method seems the way to go.

How are you implementing this currently, using standard logging?

With Loguru, you could for example assign self.logger = logger.bind(log_id=123456) to your Consumer while initializing it.
Alternatively, this can be done in-line like: logger.bind(log_id=request.id).info("Message").

Also, note that if you need to set a default value for everyone, you can use logger.configure(extra={"log_id": 0}).

Please, show me some code, maybe I could help you more precisely. 👍

yes, I do it with standard logging.

mycode just like this

main.py
from loguru import logger

from mytask import do_it

logger.add("file.log", format="{time:YYYY-MM-DD HH:mm:ss} {extra[log_id]} {message}")
with RedisQueue(xxx) as rq:
data = rq.get()
if data:
logger.info(f"{data}")
# here I want to give a unified log_id ,the below functions log all have this log_id
do_it()

mytask.py

from loguru import logger

def func1():
logger.info("1111")

def func2():
logger.info("2222")

def do_it():
logger.info("xxxx")

if i use logger.bind(log_id=xxxx).info("Message"), in task.py func1 and func2 all func need to add a param to pass log_id when main generated?

have another way? log_id just as global, only init once, and below func logger can auto get it until i reinit it.

Thanks for the code sample. How did you implement this with standard logging? Are you using LoggerAdaptater?

In my opinion, if you want to add context over your functions, you should encapsulate them into a class.

For example:

class Task:

    def __init__(self, log_id):
        self.logger = logger.bind(log_id=log_id)

    def func1(self):
        self.logger.info("1111")

    def func2(self):
        self.logger.info("2222")

    def do_it(self):
        self.logger.info("xxxx")

And in main.py:

if data:
    task = Task(123)
    task.do_it()

This avoids relying on a global state, and this is probably more future-proof (imagine you want to call your function from different places in different threads).

Otherwise, you can use .configure() before calling do_it(), this should work too.

I do this with standard logging through threading.currentThread().__dict__['log_id'], main thread and child thread all have own logger. thread-safe by default, but not multiprocess-safe especially in rotating.

thanks very much for your help.
.configure() maybe works better for me. I'll try that.

Thanks again for your patient explanation and replying.

Keep in mind that this is not the intended use case for .configure(), though. 😄

Don't hesitate to ask me if you encounter other problems.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

Gopichand995 picture Gopichand995  ·  4Comments

HarveySummers picture HarveySummers  ·  4Comments

shmilylty picture shmilylty  ·  5Comments

heckad picture heckad  ·  4Comments

ghost picture ghost  ·  4Comments