diff options
Diffstat (limited to 'gn3/utility/logger.py')
-rw-r--r-- | gn3/utility/logger.py | 163 |
1 files changed, 163 insertions, 0 deletions
diff --git a/gn3/utility/logger.py b/gn3/utility/logger.py new file mode 100644 index 0000000..4245a02 --- /dev/null +++ b/gn3/utility/logger.py @@ -0,0 +1,163 @@ +""" +# GeneNetwork logger +# +# The standard python logging module is very good. This logger adds a +# few facilities on top of that. Main one being that it picks up +# settings for log levels (global and by module) and (potentially) +# offers some fine grained log levels for the standard levels. +# +# All behaviour is defined here. Global settings (defined in +# default_settings.py). +# +# To use logging and settings put this at the top of a module: +# +# import utility.logger +# logger = utility.logger.getLogger(__name__ ) +# +# To override global behaviour set the LOG_LEVEL in default_settings.py +# or use an environment variable, e.g. +# +# env LOG_LEVEL=INFO ./bin/genenetwork2 +# +# To override log level for a module replace that with, for example, +# +# import logging +# import utility.logger +# logger = utility.logger.getLogger(__name__,level=logging.DEBUG) +# +# We'll add more overrides soon. +""" +# todo incomplete file + +# pylint: disable-all +import logging +import datetime +from inspect import isfunction +from inspect import stack + +from pprint import pformat as pf + + +# from utility.tools import LOG_LEVEL, LOG_LEVEL_DEBUG, LOG_SQL + +LOG_SQL = True + + +class GNLogger: + """A logger class with some additional functionality, such as + multiple parameter logging, SQL logging, timing, colors, and lazy + functions. + + """ + + def __init__(self, name): + self.logger = logging.getLogger(name) + + def setLevel(self, value): + """Set the undelying log level""" + self.logger.setLevel(value) + + def debug(self, *args): + """Call logging.debug for multiple args. Use (lazy) debugf and +level=num to filter on LOG_LEVEL_DEBUG. + + """ + self.collect(self.logger.debug, *args) + + def debug20(self, *args): + """Call logging.debug for multiple args. Use level=num to filter on +LOG_LEVEL_DEBUG (NYI). + + """ + if level <= LOG_LEVEL_DEBUG: + if self.logger.getEffectiveLevel() < 20: + self.collect(self.logger.debug, *args) + + def info(self, *args): + """Call logging.info for multiple args""" + self.collect(self.logger.info, *args) + + def warning(self, *args): + """Call logging.warning for multiple args""" + self.collect(self.logger.warning, *args) + # self.logger.warning(self.collect(*args)) + + def error(self, *args): + """Call logging.error for multiple args""" + now = datetime.datetime.utcnow() + time_str = now.strftime('%H:%M:%S UTC %Y%m%d') + l = [time_str]+list(args) + self.collect(self.logger.error, *l) + + def infof(self, *args): + """Call logging.info for multiple args lazily""" + # only evaluate function when logging + if self.logger.getEffectiveLevel() < 30: + self.collectf(self.logger.debug, *args) + + def debugf(self, level=0, *args): + """Call logging.debug for multiple args lazily and handle + LOG_LEVEL_DEBUG correctly + + """ + # only evaluate function when logging + if level <= LOG_LEVEL_DEBUG: + if self.logger.getEffectiveLevel() < 20: + self.collectf(self.logger.debug, *args) + + def sql(self, sqlcommand, fun=None): + """Log SQL command, optionally invoking a timed fun""" + if LOG_SQL: + caller = stack()[1][3] + if caller in ['fetchone', 'fetch1', 'fetchall']: + caller = stack()[2][3] + self.info(caller, sqlcommand) + if fun: + result = fun(sqlcommand) + if LOG_SQL: + self.info(result) + return result + + def collect(self, fun, *args): + """Collect arguments and use fun to output""" + out = "."+stack()[2][3] + for a in args: + if len(out) > 1: + out += ": " + if isinstance(a, str): + out = out + a + else: + out = out + pf(a, width=160) + fun(out) + + def collectf(self, fun, *args): + """Collect arguments and use fun to output one by one""" + out = "."+stack()[2][3] + for a in args: + if len(out) > 1: + out += ": " + if isfunction(a): + out += a() + else: + if isinstance(a, str): + out = out + a + else: + out = out + pf(a, width=160) + fun(out) + +# Get the module logger. You can override log levels at the +# module level + + +def getLogger(name, level=None): + """method to get logger""" + gnlogger = GNLogger(name) + _logger = gnlogger.logger + + # if level: + # logger.setLevel(level) + # else: + # logger.setLevel(LOG_LEVEL) + + # logger.info("Log level of "+name+" set to "+logging.getLevelName(logger.getEffectiveLevel())) + return gnlogger |