Loguru: Changing format of handler

Created on 11 Dec 2018  路  7Comments  路  Source: Delgan/loguru

It appears that you cannot change the format (easily), but have to start a new logger/sink for it (and then stop the previous one), or am I missing something?

I think it would be good to have a method to update the format of a handler (which would take care of handling caches etc) maybe.

Currently I am using:

log_format = loguru._defaults.LOGURU_FORMAT + ' ({extra[reqid]}:{extra[ip]}:{extra[user]})'
logger = loguru.logger
logger.start(sys.stderr, format=log_format)
logger = logger.bind(reqid='-', ip='-', user="-")
logger.stop(0)

And then later bind extra per request:

def get_logger_for_request(request):
    global request_id
    request_id += 1
    ip = request.headers.get("x-real-ip", "?")
    return logger.bind(reqid=request_id, ip=ip, user="?")

Something like logger._handlers[0].set_format(loguru._defaults.LOGURU_FORMAT + ' ({extra[reqid]}:{extra[ip]}:{extra[user]})') could replace the first block here.

I've found that there is Handler.update_format, which looked promising, but then it is only about updating formats for color.

Another way would be to use LOGURU_AUTOINIT=0, but I wonder what you think about changing the format on the fly.

question

Most helpful comment

@jcmcken The underlying datetime object is indeed timezone aware.

Moreover, when using "{time}" in your format, the timezone offset will be part of the formatted datetime.

logger.remove()
logger.add(sys.stderr, format="{time} - {message}")
logger.info("Test")
# => '2018-12-15T09:06:12.354664+0100 - Test'

You don't see that in the demonstration gif because I chosen to not use ISO8601 for the default logger format in order to reduce verbosity. The default logger format is more like format="{time:YYYY-MM-DD HH:mm:ss.SSS} {message}", it's just the local time naively displayed.

There are two things to distinguish: the default time format and the default logger format.

If you want to display timezone by default, you can set the LOGURU_FORMAT environment variable to the format you would prefer, like for example "<g>{time}</g> {level} <lvl>{message}</lvl>". See also the tokens available for datetime formatting.

All 7 comments

Hi @blueyed, thanks for your interest on Loguru. 馃槈

I don't think that updating the format of an handler is what you really need here.
It looks more like you would prefer the default handler to be started with another format.

Ideally, you could just do: export LOGURU_FORMAT="... ({extra[reqid]}:{extra[ip]}:{extra[user]})"

But if you want this just for one of yours scripts, I would suggest to use logger.configure():

logger.configure(
    handlers=[{"sink": sys.stderr, "format"=log_format}],
    extra={"reqid": "-", "ip": "-", user="-"}
)

Actually, depending on your program, you may have to use .configure() as for example, if you from loguru import logger in another module, it will not automatically "inherit" from the default values of your extra dict (.configure() adds extra to the root logger so it's ok).

As you talk about changing the format "on-the-fly", I just wan to say as a side note that this is possible by passing a function to the format argument, so the format can be dynamically modifed at run-time. But that would be of no use here.

Oh, please, don't use Loguru internals, one day it will break unexpectedly! 馃槢

@Delgan is LOGURU_FORMAT available also on Windows ?

Can configure be added into README ? I like this library as I like such helpers but I really have strong opinion about ISO8601 datetime everywhere (timezones are such help when debugging).

I would like to add loguru as dependency but I have to configure it to have proper format and demanding LOGURU_FORMAT this way is not something I can easily do as dependency :)

Btw thanks to https://github.com/vitalets/github-trending-repos/issues/11 for pointing that repo :)

Hey @alkuzad.

Yes, you can set the format as an environment variable on Windows too, for example:

setx LOGURU_FORMAT "<g>{time}</g> {name} <lvl>{message}</lvl>"

Also note that when using "{time}" for formatting without specifiers, the default is ISO8601 with timezone information.

In the end, if you want to share a program using loguru, you should indeed not rely on environment variables but properly use .add() or .configure() (which is already mentionned in the README, see: Suitable for scripts and libraries).

Just set the format you prefer at the beginning of your script. 馃檪

Should the default timestamp of messages include the timezone offset? I don't see that in the README animation. Or are you saying the underlying datetime object is timezone aware.

@jcmcken The underlying datetime object is indeed timezone aware.

Moreover, when using "{time}" in your format, the timezone offset will be part of the formatted datetime.

logger.remove()
logger.add(sys.stderr, format="{time} - {message}")
logger.info("Test")
# => '2018-12-15T09:06:12.354664+0100 - Test'

You don't see that in the demonstration gif because I chosen to not use ISO8601 for the default logger format in order to reduce verbosity. The default logger format is more like format="{time:YYYY-MM-DD HH:mm:ss.SSS} {message}", it's just the local time naively displayed.

There are two things to distinguish: the default time format and the default logger format.

If you want to display timezone by default, you can set the LOGURU_FORMAT environment variable to the format you would prefer, like for example "<g>{time}</g> {level} <lvl>{message}</lvl>". See also the tokens available for datetime formatting.

@blueyed Are you satisfied with the proposed solution and did you manage to configure your logger correctly?

@Delgan
Thanks for your help, I am the following in a log module, where I import logger from across the app:

import sys

import loguru

# log_format = '<green>{time:YYYY-MM-DD HH:mm:ss.SSS}</green> | <level>{level: <8}</level> | <cyan>{name}</cyan>:<cyan>{function}</cyan>:<cyan>{line}</cyan> - <level>{message}</level> ({extra})'
log_format = loguru._defaults.LOGURU_FORMAT + ' ({extra[reqid]}:{extra[ip]}:{extra[user]})'

logger = loguru.logger

logger.configure(
    handlers=[
        {"sink": sys.stderr, "format": log_format},
    ],
    extra={"reqid": "-", "ip": "-", "user": "-"},
)
Was this page helpful?
0 / 5 - 0 ratings

Related issues

af6140 picture af6140  路  5Comments

AllanLRH picture AllanLRH  路  6Comments

flybaozi picture flybaozi  路  4Comments

oz123 picture oz123  路  4Comments

filantus picture filantus  路  5Comments