diff options
Diffstat (limited to 'wqflask/utility/logger.py')
-rw-r--r-- | wqflask/utility/logger.py | 137 |
1 files changed, 137 insertions, 0 deletions
diff --git a/wqflask/utility/logger.py b/wqflask/utility/logger.py new file mode 100644 index 00000000..86ee1c52 --- /dev/null +++ b/wqflask/utility/logger.py @@ -0,0 +1,137 @@ +# 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. + +import logging +import string +from inspect import isfunction +from pprint import pformat as pf +from inspect import stack + +from utility.tools import LOG_LEVEL, LOG_LEVEL_DEBUG, LOG_SQL, LOG_FORMAT + +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,level=0,*args): + """Call logging.debug for multiple args. Use level=num to filter on +LOG_LEVEL_DEBUG. + + """ + if level <= LOG_LEVEL_DEBUG: + 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""" + self.collect(self.logger.error,*args) + + 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""" + # 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): + 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 |