Issue while wrapping logger in custom class

Viewed 99

I'm new to python and trying to create wrapper over logging to reuse changes needed to modify formatting etc.

I've written my wrapper class in following way -

import logging
import sys
from datetime import datetime

class CustomLogger:
    """This is custom logger class"""
    _format_spec = f"[%(name)-24s | %(asctime)s | %(levelname)s ] (%(filename)-32s : %(lineno)-4d) ==> %(message)s"
    _date_format_spec = f"%Y-%m-%d @ %I:%M:%S %p"

    def __init__(self, name, level=logging.DEBUG, format_spec=None):
        """"""
        self.name        = name
        self.level       = level
        self.format_spec = format_spec if format_spec else CustomLogger._format_spec

        # Complete logging configuration.
        self.logger = self.get_logger(self.name, self.level)

    def get_file_handler(self, name, level):
        """This is a method to get a file handler"""
        today        = datetime.now().strftime(format="%Y-%m-%d")
        file_handler = logging.FileHandler("{}-{}.log".format(name, today))
        file_handler.setLevel(level)
        file_handler.setFormatter(logging.Formatter(self.format_spec,
                                                    datefmt=CustomLogger._date_format_spec))
        return file_handler

    def get_stream_handler(self, level):
        """This is a method to get a stream handler"""
        stream_handler = logging.StreamHandler(sys.stdout)
        stream_handler.setLevel(level)
        stream_handler.setFormatter(logging.Formatter(self.format_spec,
                                                      datefmt=CustomLogger._date_format_spec))
        return stream_handler

    def get_logger(self, name, level):
        """This is a method to get a logger"""
        logger = logging.getLogger(name)
        logger.addHandler(self.get_file_handler(name, level))
        # logger.addHandler(self.get_stream_handler(level))
        return logger

    def info(self, msg):
        """info message logger method"""
        self.logger.info(msg)

    def error(self, msg):
        """error message logger method"""
        self.logger.error(msg)

    def debug(self, msg):
        """debug message logger method"""
        self.logger.debug(msg)

    def warn(self, msg):
        """warning message logger method"""
        self.logger.warn(msg)

    def critical(self, msg):
        """critical message logger method"""
        self.logger.critical(msg)

    def exception(self, msg):
        """exception message logger method"""
        self.logger.exception(msg)

But when I try to use my CustomLogger, nothing goes into the log file.

def main():
    """This main function"""
    logger = CustomLogger(name="debug", level=logging.DEBUG)
    logger.info("Called  main")


if __name__ == "__main__":
    main()

If I do similar thing without class/function wrapper, it works. Not sure where I'm going wrong. Any pointer will help.

Further update on the question

After making this (custom_logger.py) as a package and using in actual application (app.py), I'm noticing it always prints custom_logger.py as filename but not app.py.

How to fix this? I'm ok with rewriting the CustomLogger class if required.

1 Answers

I missed to do setLevel() for the logger. After doing that, problem is resolved. I also added pid for the file handler file-name to avoid any future issue with multi-process env.

Let me know if there's anything I can do better here wrt any other potential issues.

Related