structlog
structlog copied to clipboard
Document clean way to add custom log levels
Is there a different way, other than accessing a private member like in below snippet?
structlog.stdlib.TRACE = TRACE = 5
structlog.stdlib._NAME_TO_LEVEL['trace'] = TRACE
logging.addLevelName(TRACE, "TRACE")
https://github.com/ethereum/pyethereum/issues/202
Do you have any API or wishes in mind?
no not really. maybe something like .addLevelName( int_level, str_name)
So I’m a bit ignorant about stdlib here, how does one add log levels there?
stdlib logging levels are defined as integers (defaults are: https://docs.python.org/2/library/logging.html#logging-levels).
For example, Logger.debug("OMG DEBUG MESSAGE")
would be equivalent to Logger.msg(Logger.DEBUG, "OMG DEBUG MESSAGE")
Has any more thought gone into this? It seems to me that a really good first step would be the ability for internal processes that use the logging level to resolve any integer to its closest recognized level. For example, say we have the standard recognized levels:
CRITICAL = 50
ERROR = 40
WARNING = 30
INFO = 20
DEBUG = 10
NOTSET = 0
in this case, logging at any level from 1-10 is simply understood as DEBUG
, and anything over 50 is understood as CRITICAL
This would at least allow custom loggers to understand newly defined levels without breaking anything in the structlog stdlib
Custom log level not working with structlog.
Reference - https://stackoverflow.com/q/54505487/6233947
I tried above mentioned steps also structlog.stdlib.TRACE = TRACE = 5 structlog.stdlib._NAME_TO_LEVEL['trace'] = TRACE logging.addLevelName(TRACE, "TRACE")
But it is still not working for me with latest version
@pankajsharma1 This is technically possible, but very difficult. See possible solution at https://stackoverflow.com/a/56467981/3945932.
Less invasive way and no monkey patching by extending ConsoleRenderer
if you only want it to look different:
class MyConsoleRenderer(ConsoleRenderer):
def __call__(self, logger: WrappedLogger, name: str, event_dict: EventDict) -> str:
custom_level = event_dict.pop('l', None)
if custom_level:
event_dict['level'] = custom_level
level = event_dict.get('level', None)
event = event_dict.get('event', None)
if event:
if level == 'success':
event_dict['event'] = colorama.Fore.LIGHTBLUE_EX + _pad(event, self._pad_event) + self._styles.reset
return super().__call__(logger, name, event_dict)
console_renderer = MyConsoleRenderer()
console_renderer._level_to_color['success'] = colorama.Fore.LIGHTBLUE_EX
# Change processor of formatter to `MyConsoleRenderer` and now you can use:
log.msg("It Happened!", l='success')
# PS. Same way I made debug dim grey as you see in the screenshot
Hello! Is the code provided by @darklow currently the best way to add custom log level or is there a cleaner API as of now?
For console output, I think you can have it more elegantly with the new columns configuration: https://www.structlog.org/en/stable/console-output.html#console-output-configuration
Have a look at https://www.structlog.org/en/stable/api.html#structlog.dev.LogLevelColumnFormatter and its implementation.