loguru
loguru copied to clipboard
Set a local format for a bind logger
Hi, in some methods of a class I need to always log a set of values together with the message. But this should happen only in those methods. I think the bind method is the answer, but I can't figure out how to format the message locally.
def f(i):
context_logger = logger.bind(i=i)
context_logger.info("Starting")
...
context_logger.info("Ending")
Where to put the format for context_logger only without altering any other parameter?
Hi.
The format is configured in the handler. You probably need to use a custom function to differentiate between bound and default logger.
def formatter(record):
if "i" in record["extra"]:
return "[i={extra[i]}] {level} {message}\n{exception}"
else:
return "{level} {message}\n{exception}"
logger.add(sys.stderr, format=formatter)
Is that what you're looking for?
Thank you for your answer, not quite, perhaps I am misinterpreting what the bind is for.
I try to explain what I have in mind: the "main" logger is already setup and configured with general options valid in the whole project; now, everywhere I use e.g. logger.info("Hi") and it works as expected (it is the "main" logger); but sometimes, I have a function somewhere which logs a lot, and I want to track some parameters which are repeated in every log call, so it would be boring to repeat them all the time. For example:
from loguru import logger
def a_function_without_this_need(param):
logger.info("Start")
logger.info("End")
a_function_without_this_need("Hello")
# Logs:
# Start
# End
def a_function_with_this_need(param):
logger.info("Start with param={}", param)
logger.info("Something with param={}", param)
logger.info("Something else with param={}", param)
logger.info("End with param={}", param)
a_function_with_this_need("Hello")
# Logs:
# Start with param=Hello
# Something with param=Hello
# Something else with param=Hello
# End with param=Hello
So in the second function I have to repeat the logging of param every time and it is very verbose.
I was looking for something which would work like this:
from loguru import logger
def a_function_without_this_need(param):
logger.info("Start")
logger.info("End")
a_function_without_this_need("Hello")
# Logs:
# Start
# End
# >>>>> This is untouched and keeps working as before
def a_function_with_this_need(param):
context_logger = logger.bind(param=param).format("{msg} with param={extra[param]}") # Fake code
context_logger.info("Start")
context_logger.info("Something")
context_logger.info("Something else")
context_logger.info("End")
a_function_with_this_need("Hello")
# Logs:
# Start with param=Hello
# Something with param=Hello
# Something else with param=Hello
# End with param=Hello
# >>>>> It works as before without touching the main logger and without specifing the param every time
Is there a way to achieve this in a simple way?
Thanks for the clarification. Currently, there is no easy way to achieve this. A possible workaround is to create a small utility function, although I agree this is not very satisfying.
def log(level, message):
logger.log(level, message + f" with param={param}")
log("INFO", "Start")
log("INFO", "Something")
log("INFO", "Something else")
log("INFO", "End")
This is an interesting use case, though. It's definitely something that should be possible in the future as I plan to make the message formatting customizable (see #318).
I just came to realization that you can use patch() also.
context_logger = logger.patch(lambda r: r.update(message=r["message"] + f" with param={param}"))
context_logger.info("Start")
context_logger.info("Something")
context_logger.info("Something else")
context_logger.info("End")
Be aware not to use it with opt(colors=True) because colorization won't work due to implementation details.
Thanks it work great!