Source code for lazyflow.utility.tracer

###############################################################################
#   lazyflow: data flow based lazy parallel computation framework
#
#       Copyright (C) 2011-2014, the ilastik developers
#                                <team@ilastik.org>
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the Lesser GNU General Public License
# as published by the Free Software Foundation; either version 2.1
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Lesser General Public License for more details.
#
# See the files LICENSE.lgpl2 and LICENSE.lgpl3 for full text of the
# GNU Lesser General Public License version 2.1 and 3 respectively.
# This information is also available on the ilastik web site at:
#		   http://ilastik.org/license/
###############################################################################
import logging
import inspect

[docs]class Tracer(object): """ Context manager to simplify function entry/exit logging trace statements. Example Usage: >>> # Create a TRACE logger >>> import sys, logging >>> traceLogger = logging.getLogger("TRACE.examplemodule1") >>> traceLogger.addHandler( logging.StreamHandler(sys.stdout) ) >>> # Use the context manager >>> def f(): ... with Tracer(traceLogger): ... print "Function f is running..." >>> # If TRACE logging isn't enabled, there's no extra output >>> f() Function f is running... >>> # Enable TRACE logging to see enter/exit log statements. >>> traceLogger.setLevel(logging.DEBUG) >>> f() (enter) f Function f is running... (exit) f >>> # Disable TRACE logging by setting the level above DEBUG. >>> traceLogger.setLevel(logging.INFO) """ def __init__(self, logger, level=logging.DEBUG, msg='', determine_caller=True, caller_name=''): if type(logger) == str: self._logger = logging.getLogger(logger) else: self._logger = logger self._level = level self._determine_caller = determine_caller self._msg = msg self._caller = caller_name def __enter__(self): if self._logger.isEnabledFor( self._level ): if self._determine_caller and self._caller == '': stack = inspect.stack() self._caller = stack[1][3] self._logger.log(self._level, "(enter) " + self._caller + ' ' + self._msg) def __exit__(self, *args): if self._logger.isEnabledFor( self._level ): self._logger.log(self._level, "(exit) " + self._caller)
from functools import wraps
[docs]def traceLogged(logger, level=logging.DEBUG, msg='', caller_name=''): """ Returns a decorator that logs the entry and exit of its target function. Uses the the :py:class:`Tracer` context manager internally. Example Usage: >>> # Create a TRACE logger >>> import sys, logging >>> traceLogger = logging.getLogger("TRACE.examplemodule2") >>> traceLogger.addHandler( logging.StreamHandler(sys.stdout) ) >>> # Decorate a function to allow entry/exit trace logging. >>> @traceLogged(traceLogger) ... def f(): ... print "Function f is running..." >>> # If TRACE logging isn't enabled, there's no extra output >>> f() Function f is running... >>> # Enable TRACE logging to see enter/exit log statements. >>> traceLogger.setLevel(logging.DEBUG) >>> f() (enter) f Function f is running... (exit) f >>> # Disable TRACE logging by setting the level above DEBUG. >>> traceLogger.setLevel(logging.INFO) """ def decorator(func): """A closure that logs the entry and exit of func using the logger.""" if caller_name != '': name = caller_name elif hasattr(func, 'im_func'): name = func.im_func.func_name else: name = func.func_name @wraps(func) def wrapper(*args, **kwargs): with Tracer(logger, level=level, msg=msg, determine_caller=False, caller_name=name): return func(*args, **kwargs) wrapper.__wrapped__ = func # Emulate python 3 behavior of @wraps return wrapper return decorator
if __name__=='__main__': import sys logger = logging.getLogger(__name__) handler = logging.StreamHandler(sys.stdout) handler.setFormatter( logging.Formatter("%(levelname)s %(thread)d %(name)s:%(funcName)s:%(lineno)d %(message)s") ) logger.addHandler(handler) logger.setLevel(logging.DEBUG) def func1(): with Tracer(logger): print "I'm func 1" @traceLogged(logger) def func2(): print "I'm func 2" func1() func2() # Execute doctests import doctest doctest.testmod()