Open xFGhoul opened 2 years ago
In Loguru, there is only one logger
object.
Every logged message will pass through all handlers added so far, so you may need to filter
them.
See Creating independent loggers with separate set of handlers.
I don't understand, these examples aren't really providing me what I'm looking for
and if I was to be more specific:
if __name__ == "__main__":
logger.configure(**LOGGING_CONFIG)
logger.info("this actually goes through the 'sink' i want")
# -- Initialize Thread
logger.info("Initializng Thread") # -- This still works
THREAD = CLASS(...)
Thread = Thread(name="Thread", target=THREAD.start)
Thread.start()
logger.info("Thread Successfully Started") # -- this now logs what THREAD.start started logging, even though the 'sinks' which is what I assume is the file chosen to be logged too
if there is only one
logger
object, why is it not noticing that there are 2 different sinks? im not using logger.add
, is that something I need to do?
Can you please provide a fully reproducible example with the expected output? Sorry but I have trouble understanding the issue you're facing.
You don't need to call logger.add()
because you used logger.configure()
which itself will add the handlers internally (after removing the existing ones). Based on your LOGGING_CONFIG
dict, only one handler will be added (logging to a file).
The issue is that I have two loggers essentially:
when my main
program starts, it calls logger.configure()
with this config:
LOGGING_CONFIG: Final[Dict] = {
"handlers": [
{
"sink": LOGGING_PATH,
"format": "[{time:YYYY-MM-DD HH:mm:ss}] {module}::{name}({line}) - {message}",
"enqueue": True,
"mode": "w",
"rotation": "daily",
"level": "INFO",
"serialize": False,
"backtrace": False,
"catch": False,
},
],
}
now as my program runs it goes smoothly, logging exactly to what LOGGING_PATH
file it should be logged too,
then as I initialize a core thread that needs to be run:
ImportantClass = AnImportantClass(debug=True, logs_path=..., webhook_url=...)
ImportantThread = Thread(name="Something Important", target=ImportantClass.start)
ImportantThread.start()
now, in the __init__
of AnImportantClass
, it also calls logger.configure()
with this config:
LOGGING_CONFIG: Dict = {
"handlers": [
{
"sink": self.logs_path,
"format": "[{time:YYYY-MM-DD HH:mm:ss}] {module}::{function}({line}) - {message}",
"enqueue": True,
"rotation": "daily",
"level": "INFO",
"mode": "w",
"serialize": False,
"backtrace": False,
"catch": False,
},
],
}
now when this gets called, instantly what the first program LOGGING_PATH
that was being written too starts being written to self.logs_path
, so my question is why does the two logging paths get conflicted
and yes, I have tested not initializing this thread and it does work correctly so I have pin pointed the issue down to the __init__
method, now my theory is that it overwrites the original logger.configure()
like you mentioned, so I guess my question is now how do I instead use both loggers at the same time?
@Delgan any update on my issue?
You can use .add()
instead of .configure()
, it won't remove the existing handlers.
You can use
.add()
instead of.configure()
, it won't remove the existing handlers.
.add()
does nothing
it also starts printing logging to stdout
I think you're confusion comes from the fact that there is only one logger but two handlers, from the way Loguru works. All logged messages will go through all added handlers if they are not filtered.
Can you please clarify what is the expected output of your configuration? Does LOGGING_PATH
and self.logs_path
represent the same file?
I think you're confusion comes from the fact that there is only one logger but two handlers, from the way Loguru works. All logged messages will go through all added handlers if they are not filtered.
Can you please clarify what is the expected output of your configuration? Does
LOGGING_PATH
andself.logs_path
represent the same file?
the expected output is that
no, self.logs_path
is part of ImportantClass
own constructor, LOGGING_PATH
is my "main" logger
to put it simply, the issue is that:
a.txt
b.txt
a.txt
now routes to b.txt
Thanks for the details.
It's pretty clear now that you'll need to use a custom filter
to create independent loggers with separate set of handlers.
To summarize and explain the issues you faced:
.configure()
is called to initialize "b.txt"
handler, then all existing handlers are removed (thus including the one logging to "a.txt"
) and all logs messages will be emitted to "b.txt"
only.add()
is called to initialize "b.txt"
, then both handlers co-exist and all logs messages are emitted to both "a.txt"
and "b.txt"
.For this reason, you need a way to select which logs go to which handler. This is usually done using custom filter
and .bind()
:
from loguru import logger
logger_a = logger.bind(name="a")
logger.add("a.txt", filter=lambda r: r["extra"].get("name") == "a")
logger_b = logger.bind(name="b")
logger.add("b.txt", filter=lambda r: r["extra"].get("name") == "b")
logger_a.info("Logged to 'a.txt' only")
logger_b.info("Logged to 'b.txt' only")
logger.info("Not logged to any file")
I have 2 loggers, one for my main thread, and the other is a logger for a class, the config dict looks something like this:
now in my main code i do something like:
now the last
logger.info("blah blah blah v2")
will log toother_logger
's config setup, and not the one set up, thats its supposed to first, why? and how do I fix this?