hynek / structlog

Simple, powerful, and fast logging for Python.
https://www.structlog.org/
Other
3.43k stars 212 forks source link

Document clean way to add custom log levels #47

Open heikoheiko opened 9 years ago

heikoheiko commented 9 years ago

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

hynek commented 9 years ago

Do you have any API or wishes in mind?

heikoheiko commented 9 years ago

no not really. maybe something like .addLevelName( int_level, str_name)

hynek commented 9 years ago

So I’m a bit ignorant about stdlib here, how does one add log levels there?

fxfitz commented 9 years ago

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")

rydrman commented 6 years ago

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

sharmapankaj7 commented 5 years ago

Custom log level not working with structlog.

Reference - https://stackoverflow.com/q/54505487/6233947

sharmapankaj7 commented 5 years ago

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

pdebelak commented 5 years ago

@pankajsharma1 This is technically possible, but very difficult. See possible solution at https://stackoverflow.com/a/56467981/3945932.

darklow commented 2 years ago

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

image

alexbalandi commented 7 months ago

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?

hynek commented 7 months ago

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.

leandrodesouzadev commented 1 month ago

@Pankajsharma1 This is technically possible, but very difficult. See possible solution at https://stackoverflow.com/a/56467981/3945932.

Is this still the only to achieve such functionality? I would like to setup a few more logging levels, and this seems not that "friendly". And I don't want just to add some colors, but use this information later for filtering.