view logging_module.py @ 4:901857c9b24f draft

Uploaded
author jaredgk
date Wed, 17 Oct 2018 17:30:37 -0400
parents 3830d29fca6a
children
line wrap: on
line source

import sys
import logging



def initLogger(filename='pipeline.log', filelevel='INFO',
               streamlevel='WARNING', resetlog=True):
    """General logger initialization for PPP functions.

    Messages from WARNING level and higher will be logged to file and to
    stderr. By default, INFO level will also be written to logfile. Both
    levels are flexible.

    Level groupings:
        ERROR: Error messages should be generated by an exception call
        WARNING: Non-terminal behavior that may be unusual (i.e. lists
            with no values, blank strings)
        INFO: Every major (user-facing) function should have the following:
            -Message for function start
            -List of input arguments and options
            -Basic sanity checks (dimensions of input data)
            -Statements before or after major function calls
            -Message for function end
        DEBUG: Mainly for developer use/debugging. Generate logs for
            sub-functions that match INFO level for major functions.
            Possible care should be used if there are lots of loops called.

    Use: Call with either the individual function (in __name__=="__main__"
    statement) or in pipeline file.

    Parameters
    ----------
    filename : str ("pipeline.log")
        Name of file that log will be written to

    filelevel : {'INFO','DEBUG','WARNING','ERROR'}
        Set minimum level of log messages that are written to log file.
        Note that this acts as a de facto minumum for 'streamlevel' as well.

    streamlevel : {'WARNING','DEBUG','INFO','ERROR'}
        Set minimum level of log messages that are output to stream.

    resetlog : bool (True)
        If true, will overwrite logfile when opening. Set to false if log is
        being initialized multiple times

    Returns
    -------
    None

    Exceptions
    ----------
    If filelevel or streamlevel are not a valid logging level

    """
    log_levels = ['DEBUG','INFO','WARNING','ERROR']
    if filelevel is not None and filelevel.upper() not in log_levels:
        raise Exception('filelevel value %s is not a valid level' %
                         filelevel)
    if streamlevel is not None and streamlevel.upper() not in log_levels:
        raise Exception('streamlevel value %s is not a valid level' %
                         streamlevel)
    fmt_def = "%(asctime)s - %(funcName)s - %(levelname)s: %(message)s"
    fmt_notime = "%(funcName)s - %(levelname)s: %(message)s"
    fmtr = logging.Formatter(fmt=fmt_def)
    fmtr_notime = logging.Formatter(fmt=fmt_notime)
    filelogger = logging.getLogger()
    filelogger.setLevel('INFO')
    if streamlevel is not None:
        s_handler = logging.StreamHandler()
        s_handler.setFormatter(fmtr_notime)
        s_handler.setLevel(streamlevel)
        filelogger.addHandler(s_handler)
    logmode = 'a'
    if resetlog:
        logmode = 'w'
    if filelevel is not None:
        f_handler = logging.FileHandler(filename,mode=logmode)
        f_handler.setFormatter(fmtr)
        f_handler.setLevel(filelevel)
        #filelogger.setLevel(filelevel)
        filelogger.addHandler(f_handler)
    #Formats exception messages to be sent to appropriate loggers
    def exp_handler(etype,val,tb):
        logging.error("%s" % (val), exc_info=(etype,val,tb))

    sys.excepthook = exp_handler


def logArgs(args, func_name=None, print_nones=False):
    header = "Arguments"
    if func_name is not None:
        header+=" for"+func_name
    for arg in vars(args):
        val = vars(args)[arg]
        if val is not None or print_nones:
            logging.info('Argument %s: %s' % (arg,val))