diff options
Diffstat (limited to 'src/software/lmi/software/yumdb/util.py')
-rw-r--r-- | src/software/lmi/software/yumdb/util.py | 163 |
1 files changed, 163 insertions, 0 deletions
diff --git a/src/software/lmi/software/yumdb/util.py b/src/software/lmi/software/yumdb/util.py new file mode 100644 index 0000000..18fcf6b --- /dev/null +++ b/src/software/lmi/software/yumdb/util.py @@ -0,0 +1,163 @@ +# Software Management Providers +# +# Copyright (C) 2012-2013 Red Hat, Inc. All rights reserved. +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser 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 library 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. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +# +# Authors: Michal Minar <miminar@redhat.com> +# + +""" +Common utilities meant to be used only be ``yumdb`` subpackage. +""" + +from itertools import chain +import inspect +import logging +import os + +from lmi.common import cmpi_logging + +class DispatchingFormatter: + """ + Formatter class for logging module. It allows to predefine different + format string for paricular module names. + """ + def __init__(self, formatters, default): + """ + *format* in parameters description can be either ``string`` or + another formatter object. + + :param formatters (``dict``) Mapping of module names to *format*. + :param default Default *format*. + """ + for k, formatter in formatters.items(): + if isinstance(formatter, basestring): + formatters[k] = logging.Formatter(formatter) + self._formatters = formatters + if isinstance(default, basestring): + default = logging.Formatter(default) + self._default_formatter = default + + def format(self, record): + """ + Interface for logging module. + """ + formatter = self._formatters.get(record.name, self._default_formatter) + return formatter.format(record) + +# ***************************************************************************** +# Decorators +# ***************************************************************************** +def trace_function(func): + """ + Decorator for logging entries and exits of function or method. + """ + if not inspect.ismethod(func) and not inspect.isfunction(func): + raise TypeError("func must be a function") + + def _print_value(val): + """ + Used here for printing function arguments. Shortens the output + string, if that would be too long. + """ + if isinstance(val, list): + if len(val) < 2: + return str(val) + else: + return "[%s, ...]" % _print_value(val[0]) + return str(val) + + logger = logging.getLogger(__name__+'.trace_function') + module = func.__module__.split('.')[-1] + lineno = inspect.currentframe().f_back.f_lineno + + def _wrapper(self, *args, **kwargs): + """ + Wrapper for function or method, that does the logging. + """ + if logger.isEnabledFor(logging.DEBUG): + frm = inspect.currentframe() + logargs = { + "caller_file" : os.path.basename(os.path.splitext( + frm.f_back.f_code.co_filename)[0]), + "caller_lineno" : frm.f_back.f_lineno, + "module" : module, + "func" : func.__name__, + "lineno" : lineno, + "action" : "entering", + "args" : ", ".join(chain( + (_print_value(a) for a in args), + ( "%s=%s"%(k, _print_value(v)) + for k, v in kwargs.items()))) + } + + if not logargs["args"]: + logargs["args"] = "" + else: + logargs["args"] = " with args=(%s)" % logargs["args"] + logger.debug("%(caller_file)s:%(caller_lineno)d - %(action)s" + " %(module)s:%(func)s:%(lineno)d%(args)s" , logargs) + try: + result = func(self, *args, **kwargs) + if logger.isEnabledFor(logging.DEBUG): + logargs["action"] = "exiting" + logger.debug("%(caller_file)s:%(caller_lineno)d - %(action)s" + " %(module)s:%(func)s:%(lineno)d", logargs) + except Exception as exc: + if logger.isEnabledFor(logging.DEBUG): + logargs['action'] = 'exiting' + logargs['error'] = str(exc) + logger.debug("%(caller_file)s:%(caller_lineno)d - %(action)s" + " %(module)s:%(func)s:%(lineno)d with error: %(error)s", + logargs) + raise + return result + + return _wrapper + +def setup_logging(config): + """ + This is meant to be used by ``YumWorker`` process to setup logging + independent of what providers are using. Unfortunately ``YumWorker`` + can not use the same facilities as the rest of program, because + logging is done through *broker*. + """ + try: + logging.config.dictConfig(config) + cmpi_logging.logger = logging.getLogger('lmi.software.yumdb') + except Exception: #pylint: disable=W0703 + # logging is not set up but client expects us to work + # all messages are dumped to /dev/null + logging.config.dictConfig({ + 'version' : 1, + 'disable_existing_loggers' : True, + 'handlers': { + 'null' : { + 'class': 'logging.handlers.FileHandler', + 'level': 'CRITICAL', + 'filename': '/dev/null' + } + }, + 'loggers' : { + 'root' : { + 'level': 'CRITICAL', + 'handlers' : ['null'], + 'propagate' : False + } + } + }) + + |