summaryrefslogtreecommitdiffstats
path: root/src/software/lmi/software/yumdb/util.py
diff options
context:
space:
mode:
Diffstat (limited to 'src/software/lmi/software/yumdb/util.py')
-rw-r--r--src/software/lmi/software/yumdb/util.py163
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
+ }
+ }
+ })
+
+