Source code for simudo.util.logging
# copyright 2019 Eduard Christian Dumitrescu
# license: CC0 / https://creativecommons.org/publicdomain/zero/1.0/
import logging
import os
from cached_property import cached_property
from .setattr_init_mixin import SetattrInitMixin
__all__ = [
    'NameLevelFilter',
    'TypicalLoggingSetup']
def is_under(prefix, x):
    return x == prefix or prefix == '' or x.startswith(prefix + '.')
[docs]class NameLevelFilter(logging.Filter):
    def __init__(self, name_levelno_rules, *args, **kwargs):
        self.name_levelno_rules = name_levelno_rules
        super().__init__(*args, **kwargs)
[docs]    def filter(self, record):
        name, level = record.name, record.levelno
        for rule_name, rule_level in self.name_levelno_rules:
            if is_under(rule_name, name):
                return level >= rule_level
        return False  
[docs]class TypicalLoggingSetup(SetattrInitMixin):
    """Class that sets up logging and filtering in a typical way for Simudo.
Parameters
----------
dolfin: bool, optional
    Configure the dolfin log level as well. Note that this imports
    ``dolfin``, which takes a while. Only use it if you're okay with
    that. (default: True)
truncate: bool, optional
    Truncate (delete) the log file contents before starting to write
    to it. (default: False)
"""
    dolfin = True
    truncate = True
    @property
    def _mode(self):
        return "w" if self.truncate else "a"
[docs]    def ensure_parent_dir(self, filename):
        try:
            os.makedirs(os.path.dirname(filename))
        except OSError:
            pass 
    @cached_property
    def logfile_formatter(self):
        return logging.Formatter(
            '%(asctime)s %(name)-12s %(levelname)-8s %(message)s',
            datefmt='%Y-%m-%d %H:%M:%S')
    @cached_property
    def console_formatter(self):
        return logging.Formatter(
            '%(asctime)s %(name)-12s: %(levelname)-8s %(message)s',
            datefmt='%H:%M:%S')
    @property
    def debug_filename(self):
        return self.filename_prefix + 'debug.log'
    @property
    def info_filename(self):
        return self.filename_prefix + 'info.log'
    @cached_property
    def stream_debug(self):
        self.ensure_parent_dir(self.debug_filename)
        h = logging.FileHandler(filename=self.debug_filename, mode=self._mode)
        h.setFormatter(self.logfile_formatter)
        return h
    @cached_property
    def stream_info(self):
        self.ensure_parent_dir(self.info_filename)
        h = logging.FileHandler(filename=self.info_filename, mode=self._mode)
        h.setFormatter(self.logfile_formatter)
        return h
    @cached_property
    def stream_console(self):
        h = logging.StreamHandler()
        h.setFormatter(self.console_formatter)
        return h
[docs]    def setup_handlers(self):
        for h in (self.stream_debug,
                  self.stream_info,
                  self.stream_console):
            logging.getLogger('').addHandler(h) 
[docs]    def setup_filters(self):
        self.stream_debug.addFilter(NameLevelFilter([
            ('FFC', logging.INFO),
            ('UFL', logging.INFO),
            # ('assign', logging.DEBUG),
            ('matplotlib', logging.INFO),
            ('', logging.INFO)]))
        self.stream_info.addFilter(NameLevelFilter([
            ('FFC', logging.ERROR),
            ('UFL', logging.ERROR),
            ('', logging.INFO)]))
        self.stream_console.addFilter(NameLevelFilter([
            ('FFC', logging.ERROR),
            ('UFL', logging.ERROR),
            ('', logging.INFO)])) 
[docs]    def setup_logging(self):
        logging.getLogger('').setLevel(logging.NOTSET) 
[docs]    def setup_dolfin_loglevel(self):
        if self.dolfin:
            import dolfin
            dolfin.set_log_level(50) 
[docs]    def setup(self):
        self.setup_logging()
        self.setup_handlers()
        self.setup_filters()
        self.setup_dolfin_loglevel()