9

I would like to format the logger with brackets and left-align the text.

formatter = logging.Formatter('[%(asctime)s] [%(levelname)-8s] [%(funcName)-12s]   %(message)s')

Here is the result

[2019-09-13 16:22:56,050] [INFO    ] [main        ]   Message 1
[2019-09-13 16:22:56,050] [DEBUG   ] [do_debug    ]   Message 2
[2019-09-13 16:22:56,050] [WARNING ] [do_warning  ]   Message 3

But i would like to get something like this

[2019-09-13 16:22:56,050] [INFO]     [main]           Message 1
[2019-09-13 16:22:56,050] [DEBUG]    [do_debug]       Message 2
[2019-09-13 16:22:56,050] [WARNING]  [do_warning]     Message 3
cogimi
  • 109
  • 1
  • 2

1 Answers1

6

This is easy enough to do, as the following example shows:

import logging

logger = logging.getLogger(__name__)

def do_debug():
    logger.debug('Message 2')

def do_warning():
    logger.warning('Message 3')

def main():
    logger.info('Message 1')
    do_debug()
    do_warning()

def fmt_filter(record):
    record.levelname = '[%s]' % record.levelname
    record.funcName = '[%s]' % record.funcName
    return True

if __name__ == '__main__':
    FMT = '[%(asctime)s] %(levelname)-10s %(funcName)-12s   %(message)s'
    f = logging.Formatter(FMT)
    h = logging.StreamHandler()
    h.setFormatter(f)
    logger.setLevel(logging.DEBUG)
    logger.addHandler(h)
    logger.addFilter(fmt_filter)
    main()

When run, the above script prints:

[2020-02-01 21:36:48,758] [INFO]     [main]         Message 1
[2020-02-01 21:36:48,758] [DEBUG]    [do_debug]     Message 2
[2020-02-01 21:36:48,774] [WARNING]  [do_warning]   Message 3

You should be able to adapt the above example to your specific need, e.g. where you apply the filter, what handler you use, etc.

Vinay Sajip
  • 95,872
  • 14
  • 179
  • 191
  • 1
    This worked in my personal case, but only when I applied the filter to the handler (a StreamHandler), and not the logger itself. – jonathan Feb 02 '20 at 02:49
  • 1
    @jonathan yes, the precise deployment depends on the exact needs, but the principle of using the filter is the key point. Setting the filter on the handler is the right thing to do if there are multiple loggers using the handler, but I wanted to illustrate with a minimal example for clarity. – Vinay Sajip Feb 02 '20 at 19:16
  • Yes, the solution is perfect. Just waiting for the timeout to award the bounty. Thanks, Vinay. Out of interest, is there any benefit/loss in not overriding the Filter class with the attr modification followed a call to super()? – jonathan Feb 02 '20 at 19:52
  • 1
    Although one can subclass `Filter`, which was originally the only way to have custom filtering, at some point I added the ability to just use a callable to filter with - less work for you to have to do! But it works equally well with a `Filter` subclass and an overridden `filter()` method. – Vinay Sajip Feb 03 '20 at 16:44