gafusion / omas

Ordered Multidimensional Array Structure
http://gafusion.github.io/omas
MIT License
30 stars 15 forks source link

logging instead of custom printd/printe etc. #150

Closed dboeckenhoff closed 3 years ago

dboeckenhoff commented 3 years ago

I propose to use the standard builting python logging module instead of the custom printd definitions. That would allow better integration in other workflows which use omas as api.

orso82 commented 3 years ago

@dboeckenhoff we're certainly open to such suggestions!

One feature that printd provides is the ability to filter what gets printed based on a topic. Is such feature available in the logging module? Or perhaps what you are suggesting is to keep using printd but have it write the output with the logging module?

dboeckenhoff commented 3 years ago

@orso82 Yes that should be possible with custom levels in Loggers (not the global level). For the start and easy refactoring, printd could directly route to logging. On the long run printd could be replaced completely by subclassing logging.Logger I propose.

orso82 commented 3 years ago

Ok, with the progression of starting by routing first to logger, and then subclassing at a later stage.

But I still do not understand how to map the printd concept of debug "topics", to the logger concept of "levels". The two concepts do not seem to be compatible to me.

Right now, let's say, that I have the following messages:

printd('this is a warning in a NetCDF',topic='NetCDF')
printd('this is a critical error in a NetCDF',topic='NetCDF')
printd('this is a warning in a JSON',topic='JSON')
printd('this is a critical error in a JSON',topic='JSON')

and the user can select what topic to see, for example with: os.environ['OMAS_DEBUG_TOPIC']='NetCDF' to see:

>> this is a warning in a NetCDF
>> this is a critical error in a NetCDF

Could you please exemplify how you would replicate this with the logger module?

dboeckenhoff commented 3 years ago

@orso82 Sure, find here an MWE:

import logging
import os
logging.basicConfig()  # here you could switch the level to show debug also -> level=logging.DEBUG

class TopicFilter(logging.Filter):
    """
    This is a filter which injects contextual information into the log based on a topic.

    """
    def __init__(self, topic=None, **kwargs):
        if topic is None:
            topic = ['']
        if not isinstance(topic, list):
            topic = [topic]
        self.topics = topic
        super().__init__(**kwargs)

    def filter(self, record):
        topic_selected = os.environ.get('OMAS_DEBUG_TOPIC', '')
        if topic_selected in self.topics:
            return True
        else:
            return False

class TopicLogger(logging.Logger):
    def select_topic(self, topic):
        self.addFilter(TopicFilter(topic))

if __name__ == '__main__':
    os.environ['OMAS_DEBUG_TOPIC']='NetCDF'  # switch here to change the topic

    logger = logging.getLogger("0")
    logger.addFilter(TopicFilter('NetCDF'))
    logger.debug('this is a debug in a NetCDF (will not be logged due to level)')
    logger.warning('this is a warning in a NetCDF')
    logger.error('this is a critical error in a NetCDF')

    logger = logging.getLogger("1")
    logger.addFilter(TopicFilter('JSON'))
    logger.debug('this is a debug in a JSON (will not be logged due to level)')
    logger.warning('this is a warning in a JSON')
    logger.error('this is a critical error in a JSON')

    logger = TopicLogger("2")  # This is a variant of the above with a "select_topic" convenience function. Could be directly backed in TopicLogger.__init__
    logger.select_topic('TXT')
    logger.debug('this is a debug in a TXT (will not be logged due to level)')
    logger.warning('this is a warning in a TXT')
    logger.error('this is a critical error in a TXT')
github-actions[bot] commented 3 years ago

Stale issue message