Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Logging from a child module ignores the added root logger stream handler

Tags:

python

logging

My goal is to redirect logging messages from a certain function into a file. This function is defined in another module. I added StreamHandler to a main logger, but a message from a child_call function is not saved to tmp.log as expected.

# main.py

import logging
import os
import sys
from child_logger import child_call

logging.basicConfig(format='%(name)s:%(filename)s:%(lineno)d:%(message)s', 
      level=logging.INFO, stream=sys.stdout)

logger = logging.getLogger(__name__)
logger.info('here it is')

with open('tmp.log', 'w') as f:
    logger_stream_handler = logging.StreamHandler(stream=f)
    logger_stream_handler.setLevel(logging.INFO)

    logger.addHandler(logger_stream_handler)
    logger.info('I am outer')
    child_call()
    logger.removeHandler(logger_stream_handler)


# child_logger.py

import logging
logger = logging.getLogger(__name__)

def child_call():
    logger.info('I am inner')

Here is the output:

%python logger_test.py                                                
__main__:logger_test.py:18:here it is                                                                                                                                                
__main__:logger_test.py:25:I am outer                                                                                                                                          
child_logger:child_logger.py:9:I am inner

%cat tmp.log  
I am outer

I am expecting to see 'I am inner' in tmp.log. As far as I understood the logging module, there is a hierarchy of Logger objects created, messages from children should propagate to a root Logger by default and the root should handle all messages. What am I missing ?

like image 536
sbond Avatar asked Oct 31 '22 01:10

sbond


1 Answers

The problem is that your loggers are not correctly chained. They need to have the same root name. For example:

# main.py
logger = logging.getLogger("parent")

# child_logger.py
logger = logging.getLogger("parent.child")

Both of your log retrievals just ask for a logger with __name__, which is set to the name of the module, except for the top level, which gets "__main__". You are ending up with the equivalent of this:

# main.py
logger = logging.getLogger("__main__")

# child_logger.py
logger = logging.getLogger("child_logger")

You need to enforce a common parent logging name scheme to create the correct logger inheritance hierarchy.

like image 81
skrrgwasme Avatar answered Nov 15 '22 07:11

skrrgwasme