Python: Print log count on message

Viewed 433

I want to number/count my log messages in Python using the logging module. I would like this counter to start at 1 for each logger level.

Right now I have the following configuration:

logging.basicConfig(level=logging.INFO,
                    format='%(asctime)s MyAppName %(levelname)s %(message)s',
                    datefmt="[%Y-%m-%d %H:%M:%S]")

logging.info("Entering step 1")
logging.info("Finishing step 1")
logging.info("Exiting code")

and I get this

[2021-06-10 18:01:57] MyAppName INFO Entering step 1
[2021-06-10 18:01:58] MyAppName INFO Finishing step 1
[2021-06-10 18:01:59] MyAppName INFO Exiting code

How can I easily change it, so I get the following:

[2021-06-10 18:01:57] MyAppName INFO [1] Entering step 1
[2021-06-10 18:01:58] MyAppName INFO [2] Finishing step 1
[2021-06-10 18:01:59] MyAppName INFO [3] Exiting code
1 Answers

Use a logging.addFilter() to add ContextFilter which brings in the global counter, e.g.:

import logging

thelogcount = 1

class ContextFilter(logging.Filter):
    def filter(self, record):
        global thelogcount
        record.count = thelogcount
        thelogcount += 1
        return True

logging.basicConfig(
    level = logging.DEBUG,
    format = '%(levelname)-8s: %(count)s: %(message)s')
    
logger = logging.getLogger(__name__)
logger.addFilter(ContextFilter())

logger.info("Entering step 1")
logger.info("Finishing step 1")
logger.info("Exiting code")

Output:

INFO    : 0: Entering step 1
INFO    : 1: Finishing step 1
INFO    : 2: Exiting code

Some docs about addFilter here https://docs.python.org/3/library/logging.html#filter

UPDATE

Here's a version that keeps separate counts for some levels. Personally I prefer the single numbering scheme because that makes it possible to relate the message to each other regardless of the level.

import logging

thelogcounts = { 'INFO':0, 'ERROR':0, 'DEBUG':0}

class ContextFilter(logging.Filter):
    def filter(self, record):
        global thelogcounts
        record.count = thelogcounts[record.levelname]
        thelogcounts[record.levelname] += 1
        return True

logging.basicConfig(
    level = logging.DEBUG,
    format = '%(levelname)-8s: %(count)s: %(message)s')
    
logger = logging.getLogger(__name__)
logger.addFilter(ContextFilter())

logger.info("Entering step 1")
logger.debug("Finishing step 1")
logger.error("Finishing step 1")
logger.info("Finishing step 1")
logger.info("Finishing step 1")
logger.info("Finishing step 1")
logger.info("Finishing step 1")
logger.info("Finishing step 1")
logger.debug("Finishing step 1")
logger.debug("Exiting code")
logger.error("Finishing step 1")
logger.error("Finishing step 1")
logger.error("Finishing step 1")
logger.error("Finishing step 1")
logger.error("Finishing step 1")

Output:

INFO    : 0: Entering step 1
DEBUG   : 0: Finishing step 1
ERROR   : 0: Finishing step 1
INFO    : 1: Finishing step 1
INFO    : 2: Finishing step 1
INFO    : 3: Finishing step 1
INFO    : 4: Finishing step 1
INFO    : 5: Finishing step 1
DEBUG   : 1: Finishing step 1
DEBUG   : 2: Exiting code
ERROR   : 1: Finishing step 1
ERROR   : 2: Finishing step 1
ERROR   : 3: Finishing step 1
ERROR   : 4: Finishing step 1
ERROR   : 5: Finishing step 1
Related