Closed dboeckenhoff closed 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?
@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.
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?
@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')
Stale issue message
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.