Ticket #1089: sugar-base-trace.patch

File sugar-base-trace.patch, 3.5 KB (added by sascha_silbe, 15 years ago)

sugar.logger: add decorator trace() and log level 'trace' / TRACE

  • src/sugar/logger.py

    diff --git a/src/sugar/logger.py b/src/sugar/logger.py
    index a27a9be..2ad1717 100644
    a b  
    2020STABLE.
    2121"""
    2222
     23import __builtin__
     24import array
     25import collections
    2326import errno
     27import logging
    2428import sys
    2529import os
    26 import logging
     30import repr
     31import decorator
     32
     33
     34# new loglevel TRACE for tracing function calls
     35# use SUGAR_LOGGER_LEVEL=trace to enable
     36TRACE=5
     37logging.addLevelName(TRACE, 'TRACE')
     38
    2739
    2840# Let's keep this self contained so that it can be easily
    2941# pasted in external sugar service like the datastore.
    def get_logs_dir(): 
    3850_levels = { 'error'   : logging.ERROR,
    3951            'warning' : logging.WARNING,
    4052            'debug'   : logging.DEBUG,
    41             'info'    : logging.INFO }
     53            'info'    : logging.INFO,
     54            'trace'   : TRACE,
     55            'all'     : 0,
     56}
    4257def set_level(level):
    4358    if level in _levels:
    4459        logging.getLogger('').setLevel(_levels[level])
    def _except_hook(exctype, value, traceback): 
    6176        sys.excepthook = sys.__excepthook__
    6277
    6378    sys.excepthook(exctype, value, traceback)
    64        
     79
    6580def start(log_filename=None):
    6681    # remove existing handlers, or logging.basicConfig() won't have no effect.
    6782    root_logger = logging.getLogger('')
    6883    for handler in root_logger.handlers:
    6984        root_logger.removeHandler(handler)
    70    
     85
    7186    class SafeLogWrapper(object):
    7287        """Small file-like wrapper to gracefully handle ENOSPC errors when
    7388        logging."""
    def start(log_filename=None): 
    116131
    117132    sys.excepthook = _except_hook
    118133
     134
     135class TraceRepr(repr.Repr) :
     136
     137    # better handling of subclasses of basic types, e.g. for DBus
     138    _types = [int, long, bool, tuple, list, array.array, set, frozenset,
     139        collections.deque, dict, str]
     140    def repr1(self, x, level):
     141        for t in self._types :
     142            if isinstance(x, t) :
     143                return getattr(self, 'repr_'+t.__name__)(x, level)
     144
     145        return repr.Repr.repr1(self, x, level)
     146
     147    def repr_int(self, x, level) :
     148        return __builtin__.repr(x)
     149
     150    def repr_bool(self, x, level) :
     151        return __builtin__.repr(x)
     152
     153
     154def trace(logger=None, logger_name=None, skip_args=[], skip_kwargs=[],
     155    maxsize_list=30, maxsize_dict=30, maxsize_string=300) :
     156
     157    # size-limit repr()
     158    _trace_repr = TraceRepr()
     159    _trace_repr.maxlist = maxsize_list
     160    _trace_repr.maxdict = maxsize_dict
     161    _trace_repr.maxstring = maxsize_string
     162    _trace_repr.maxother = maxsize_string
     163    _trace_logger = logger or logging.getLogger(logger_name)
     164
     165    def _trace(f, *args, **kwargs) :
     166        # don't do expensive formatting if loglevel TRACE is not enabled
     167        enabled = _trace_logger.isEnabledFor(TRACE)
     168        if enabled :
     169            params_formatted = ", ".join(
     170                [_trace_repr.repr(a)
     171                    for (idx, a) in enumerate(args) if idx not in skip_args]+\
     172                ['%s=%s' % (k,_trace_repr.repr(v))
     173                    for (k,v) in kwargs.items() if k not in skip_kwargs])
     174
     175            _trace_logger.log(TRACE, "%s(%s) invoked", f.__name__,
     176                params_formatted)
     177
     178        try :
     179            res=f(*args, **kwargs)
     180        except :
     181            _trace_logger.exception("Exception occured in %s", f.__name__)
     182            raise
     183
     184        if enabled :
     185            _trace_logger.log(TRACE, "%s(%s) returned %s", f.__name__,
     186                params_formatted, _trace_repr.repr(res))
     187
     188        return res
     189
     190    return decorator.decorator(_trace)
     191
     192