%PDF- %PDF-
Direktori : /usr/lib/python2.7/site-packages/salt/log/ |
Current File : //usr/lib/python2.7/site-packages/salt/log/mixins.py |
# -*- coding: utf-8 -*- ''' :codeauthor: Pedro Algarvio (pedro@algarvio.me) salt.log.mixins ~~~~~~~~~~~~~~~ .. versionadded:: 0.17.0 Some mix-in classes to be used in salt's logging ''' from __future__ import absolute_import, print_function, unicode_literals # Import python libs import sys import logging class LoggingProfileMixIn(object): ''' Simple mix-in class to add a trace method to python's logging. ''' def profile(self, msg, *args, **kwargs): self.log(getattr(logging, 'PROFILE', 15), msg, *args, **kwargs) class LoggingTraceMixIn(object): ''' Simple mix-in class to add a trace method to python's logging. ''' def trace(self, msg, *args, **kwargs): self.log(getattr(logging, 'TRACE', 5), msg, *args, **kwargs) class LoggingGarbageMixIn(object): ''' Simple mix-in class to add a garbage method to python's logging. ''' def garbage(self, msg, *args, **kwargs): self.log(getattr(logging, 'GARBAGE', 5), msg, *args, **kwargs) class LoggingMixInMeta(type): ''' This class is called whenever a new instance of ``SaltLoggingClass`` is created. What this class does is check if any of the bases have a `trace()` or a `garbage()` method defined, if they don't we add the respective mix-ins to the bases. ''' def __new__(mcs, name, bases, attrs): include_profile = include_trace = include_garbage = True bases = list(bases) if name == 'SaltLoggingClass': for base in bases: if hasattr(base, 'trace'): include_trace = False if hasattr(base, 'garbage'): include_garbage = False if include_profile: bases.append(LoggingProfileMixIn) if include_trace: bases.append(LoggingTraceMixIn) if include_garbage: bases.append(LoggingGarbageMixIn) return super(LoggingMixInMeta, mcs).__new__( mcs, name, tuple(bases), attrs ) class NewStyleClassMixIn(object): ''' Simple new style class to make pylint shut up! This is required because SaltLoggingClass can't subclass object directly: 'Cannot create a consistent method resolution order (MRO) for bases' ''' class ExcInfoOnLogLevelFormatMixIn(object): ''' Logging handler class mixin to properly handle including exc_info on a per logging handler basis ''' def format(self, record): ''' Format the log record to include exc_info if the handler is enabled for a specific log level ''' formatted_record = super(ExcInfoOnLogLevelFormatMixIn, self).format(record) exc_info_on_loglevel = getattr(record, 'exc_info_on_loglevel', None) exc_info_on_loglevel_formatted = getattr(record, 'exc_info_on_loglevel_formatted', None) if exc_info_on_loglevel is None and exc_info_on_loglevel_formatted is None: return formatted_record # If we reached this far it means the log record was created with exc_info_on_loglevel # If this specific handler is enabled for that record, then we should format it to # include the exc_info details if self.level > exc_info_on_loglevel: # This handler is not enabled for the desired exc_info_on_loglevel, don't include exc_info return formatted_record # If we reached this far it means we should include exc_info if not record.exc_info_on_loglevel_instance and not exc_info_on_loglevel_formatted: # This should actually never occur return formatted_record if record.exc_info_on_loglevel_formatted is None: # Let's cache the formatted exception to avoid recurring conversions and formatting calls if self.formatter is None: # pylint: disable=access-member-before-definition self.formatter = logging._defaultFormatter record.exc_info_on_loglevel_formatted = self.formatter.formatException( record.exc_info_on_loglevel_instance ) # Let's format the record to include exc_info just like python's logging formatted does if formatted_record[-1:] != '\n': formatted_record += '\n' try: formatted_record += record.exc_info_on_loglevel_formatted except UnicodeError: # According to the standard library logging formatter comments: # # Sometimes filenames have non-ASCII chars, which can lead # to errors when s is Unicode and record.exc_text is str # See issue 8924. # We also use replace for when there are multiple # encodings, e.g. UTF-8 for the filesystem and latin-1 # for a script. See issue 13232. formatted_record += record.exc_info_on_loglevel_formatted.decode(sys.getfilesystemencoding(), 'replace') # Reset the record.exc_info_on_loglevel_instance because it might need # to "travel" through a multiprocessing process and it might contain # data which is not pickle'able record.exc_info_on_loglevel_instance = None return formatted_record