summaryrefslogtreecommitdiffstats
path: root/src/software/openlmi/software/yumdb/util.py
blob: f2af151945854d0c14f608f1f8f6124676876ed8 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
from itertools import chain
import inspect
import logging
import os

from openlmi.software.yumdb import errors

class DispatchingFormatter:
    def __init__(self, formatters, default):
        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):
        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:
            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):
    try:
        logging.config.dictConfig(config)
    except Exception:   #pylint: disable=W0703
        # logging is not set up but client expects us to work
        pass