6

Following are the contents of mylogger.py:

def get_logger(name='my_super_logger'):
    log = logging.getLogger(name)
    log.setLevel(logging.DEBUG)
    formatter = logging.Formatter(fmt='%(asctime)s %(name)s %(message)s',
                                  datefmt='%m/%d/%Y %I:%M:%S %p')
    if not len(log.handlers):
        ch = logging.StreamHandler()
        ch.setLevel(logging.DEBUG)
        ch.setFormatter(formatter)
        log.addHandler(ch)
    # print(id(log))
    return log

and following is contents of myscript.py:

from mylogger import get_logger

_logger = get_logger()

_logger.info('trying info')
_logger.debug('trying debug')

However I am facing two issues. It prints the logs twice and formatter is not working everytime:

09/18/2015 09:59:54 PM my_super_logger trying info 
INFO:my_super_logger:trying info 
09/18/2015 09:59:54 PM my_super_logger trying debug 
DEBUG:my_super_logger:trying debug 

What exactly is the issue with my get_logger code?

I need a custom formatting. However I found out that without adding a handler I cannot add a formatter. So that's why I have added StreamHandler. And the reason for if block is mentioned in this answer. Without that, I would get duplicate log messages printed.

2 Answers 2

6

The root logger is also emitting the message. Stop propagation up to the root with:

log.propagate = False

If you wanted to format all log output (so messages propagated up to the logger), set the formatter for the root logger.

You can do so with a logging.basicConfig() call provided nothing has yet been sent to the loggers, or by looping over the logger.handlers list of the root logger; you could pick out any StreamHandlers if you so wish:

root_logger = logging.getLogger()  # no name
for handler in root_logger.handlers:
    if isinstance(handler, logging.Streamhandler):
        handler.setFormatter(formatter)
Sign up to request clarification or add additional context in comments.

Comments

0

In my case of a custom handler, I had to call format manually.

I create a handler here

    logger_config = {
        "version": 1,
        "disable_existing_loggers": False,
        "formatters": {
            "standard": {"format": "%(asctime)s [%(levelname)s] %(name)s: %(message)s"},
        },
        "handlers": {
            "sns": {
                "formatter": "standard",
                "class": "app_logging.SnsHandler.SnsHandler",
                "log_level": os.environ.get("SNS_LOG_LEVEL") or "WARNING",
                "topic_arn": os.environ.get("SNS_LOG_TOPIC") or "hghghjg",
            }
        },
        "level": os.environ.get("LOG_LEVEL") or "DEBUG",
        # Root logger
        "loggers": {
            "": {
                "formatter": "standard",
                "handlers": ["sns"],
                "level": os.environ.get("LOG_LEVEL") or "DEBUG",
            },
        },
    }
    dictConfig(logger_config)

My handler class is here

from logging import Handler
import boto3


class SnsHandler(Handler):
    def __init__(self, log_level, topic_arn: str, region: str = "us-east-1") -> None:
        super().__init__(log_level)
        self.topic_arn = topic_arn
        self._sns_client = boto3.client("sns", region_name=region)

    def emit(self, record):
        msg = self.format(record)
        return self._sns_client.publish(
            TopicArn=self.topic_arn, Message=msg, Subject="Logging from the application"
        )

Note the call msg = self.format(record) in emit. The built-in handlers do this too.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.