Exemplo n.º 1
0
    def __init__(self, source, name, propagate):
        """
        Initializes the logger
        """
        parent_invoker = inspect.stack()[1]
        if not __file__.startswith(parent_invoker[1]) or parent_invoker[3] != 'get':
            raise RuntimeError('Cannot invoke instance from outside this class. Please use LogHandler.get(source, name=None) instead')

        if name is None:
            name = 'logger'

        formatter = OVSFormatter('%(asctime)s - %(hostname)s - %(process)s/%(thread)d - {0}/%(name)s - %(sequence)s - %(levelname)s - %(message)s'.format(source))

        target_definition = LogHandler.load_target_definition(source, allow_override=True)
        if target_definition['type'] == 'redis':
            from redis import Redis
            from ovs.log.redis_logging import RedisListHandler
            self.handler = RedisListHandler(queue=target_definition['queue'],
                                            client=Redis(host=target_definition['host'],
                                                         port=target_definition['port']))
        elif target_definition['type'] == 'file':
            self.handler = logging.FileHandler(target_definition['filename'])
        else:
            self.handler = logging.StreamHandler(sys.stdout)
        self.handler.setFormatter(formatter)
        self.logger = logging.getLogger(name)
        self.logger.addHandler(self.handler)
        self.logger.propagate = propagate
        self.logger.setLevel(getattr(logging, 'DEBUG'))
        self._key = '{0}_{1}'.format(source, name)
    def __init__(self, source, name, propagate):
        """
        Initializes the logger
        """
        parent_invoker = inspect.stack()[1]
        if not __file__.startswith(
                parent_invoker[1]) or parent_invoker[3] != 'get':
            raise RuntimeError(
                'Cannot invoke instance from outside this class. Please use LogHandler.get(source, name=None) instead'
            )

        if name is None:
            name = 'logger'

        formatter = OVSFormatter(
            '%(asctime)s - %(hostname)s - %(process)s/%(thread)d - {0}/%(name)s - %(sequence)s - %(levelname)s - %(message)s'
            .format(source))

        target_definition = LogHandler.load_target_definition(
            source, allow_override=True)
        if target_definition['type'] == 'redis':
            from redis import Redis
            from ovs.log.redis_logging import RedisListHandler
            self.handler = RedisListHandler(
                queue=target_definition['queue'],
                client=Redis(host=target_definition['host'],
                             port=target_definition['port']))
        elif target_definition['type'] == 'file':
            self.handler = logging.FileHandler(target_definition['filename'])
        else:
            self.handler = logging.StreamHandler(sys.stdout)

        self.unittest_mode = False
        if os.environ.get('RUNNING_UNITTESTS') == 'True':
            self.unittest_mode = True
        self.handler.setFormatter(formatter)
        self.logger = logging.getLogger(name)
        self.logger.addHandler(self.handler)
        self.logger.propagate = propagate
        self.logger.setLevel(getattr(logging, 'DEBUG'))
        self._key = '{0}_{1}'.format(source, name)
class LogHandler(object):
    """
    Log handler.

    WARNING: This log handler might be highly unreliable if not used correctly. It can log to redis, but if Redis is
    not working as expected, it will result in lost log messages. If you want reliable logging, do not use Redis at all
    or log to files and have a separate process forward them to Redis (so logs can be re-send if Redis is unavailable)
    """

    _logs = {}  # Used by unittests

    cache = {}
    counter = itertools.count()
    propagate_cache = {}
    defaults = {'logging_target': {'type': 'console'}}

    def __init__(self, source, name, propagate):
        """
        Initializes the logger
        """
        parent_invoker = inspect.stack()[1]
        if not __file__.startswith(
                parent_invoker[1]) or parent_invoker[3] != 'get':
            raise RuntimeError(
                'Cannot invoke instance from outside this class. Please use LogHandler.get(source, name=None) instead'
            )

        if name is None:
            name = 'logger'

        formatter = OVSFormatter(
            '%(asctime)s - %(hostname)s - %(process)s/%(thread)d - {0}/%(name)s - %(sequence)s - %(levelname)s - %(message)s'
            .format(source))

        target_definition = LogHandler.load_target_definition(
            source, allow_override=True)
        if target_definition['type'] == 'redis':
            from redis import Redis
            from ovs.log.redis_logging import RedisListHandler
            self.handler = RedisListHandler(
                queue=target_definition['queue'],
                client=Redis(host=target_definition['host'],
                             port=target_definition['port']))
        elif target_definition['type'] == 'file':
            self.handler = logging.FileHandler(target_definition['filename'])
        else:
            self.handler = logging.StreamHandler(sys.stdout)

        self.unittest_mode = False
        if os.environ.get('RUNNING_UNITTESTS') == 'True':
            self.unittest_mode = True
        self.handler.setFormatter(formatter)
        self.logger = logging.getLogger(name)
        self.logger.addHandler(self.handler)
        self.logger.propagate = propagate
        self.logger.setLevel(getattr(logging, 'DEBUG'))
        self._key = '{0}_{1}'.format(source, name)

    @staticmethod
    def load_target_definition(source,
                               allow_override=False,
                               forced_target_type=None):
        """
        Load the logger target
        :param source: Source
        :type source: str
        :param allow_override: Allow override
        :type allow_override: bool
        :param forced_target_type: Override target type
        :type forced_target_type: str
        :return: Target definition
        :rtype: dict
        """
        logging_target = LogHandler.defaults['logging_target']
        try:
            from ovs.extensions.generic.configuration import Configuration
            logging_target = Configuration.get('/ovs/framework/logging')
        except:
            pass

        target_type = logging_target.get('type', 'console')
        if allow_override is True and 'OVS_LOGTYPE_OVERRIDE' in os.environ:
            target_type = os.environ['OVS_LOGTYPE_OVERRIDE']
        if allow_override is True and forced_target_type is not None:
            target_type = forced_target_type

        if target_type == 'redis':
            queue = logging_target.get('queue', '/ovs/logging')
            if '{0}' in queue:
                queue = queue.format(source)
            return {
                'type': 'redis',
                'queue': '/{0}'.format(queue.lstrip('/')),
                'host': logging_target.get('host', 'localhost'),
                'port': logging_target.get('port', 6379)
            }
        if target_type == 'file':
            return {'type': 'file', 'filename': LogHandler.load_path(source)}
        return {'type': 'console'}

    @staticmethod
    def get_sink_path(source, allow_override=False, forced_target_type=None):
        """
        Retrieve the path to sink logs to
        :param source: Source
        :type source: str
        :param allow_override: Allow override
        :type allow_override: bool
        :param forced_target_type: Override target type
        :type forced_target_type: str
        :return: The path to sink to
        :rtype: str
        """
        target_definition = LogHandler.load_target_definition(
            source, allow_override, forced_target_type)
        if target_definition['type'] == 'redis':
            sink = 'redis://{0}:{1}{2}'.format(target_definition['host'],
                                               target_definition['port'],
                                               target_definition['queue'])
        elif target_definition['type'] == 'file':
            sink = target_definition['filename']
        else:
            sink = 'console:'
        return sink

    @staticmethod
    def load_path(source):
        """
        Load path
        :param source: Source
        :return: Path
        """
        log_path = '/var/log/ovs'
        log_filename = '{0}/{1}.log'.format(log_path, source)
        if not os.path.exists(log_path):
            os.mkdir(log_path, 0777)
        if not os.path.exists(log_filename):
            open(log_filename, 'a').close()
            os.chmod(log_filename, 0o666)
        return log_filename

    @staticmethod
    def get(source, name=None, propagate=False):
        """
        Retrieve a loghandler instance
        """
        key = '{0}_{1}'.format(source, name)
        if key not in LogHandler.cache:
            logger = LogHandler(source, name, propagate)
            LogHandler.cache[key] = logger
        if key not in LogHandler.propagate_cache:
            LogHandler.propagate_cache[key] = propagate
        return LogHandler.cache[key]

    def _fix_propagate(self):
        """
        Obey propagate flag as initially called
        - celery will overwrite it to catch the logging
        """
        propagate = LogHandler.propagate_cache.get(self._key, None)
        if propagate is not None:
            self.logger.propagate = propagate

    def _log(self, msg, severity, *args, **kwargs):
        """
        Log pass-through
        """
        if self.unittest_mode is True:
            if self._key not in LogHandler._logs:
                LogHandler._logs[self._key] = {}
            LogHandler._logs[self._key][msg.strip()] = severity

        self._fix_propagate()
        if 'print_msg' in kwargs:
            del kwargs['print_msg']
            print msg
        extra = kwargs.get('extra', {})
        extra['hostname'] = socket.gethostname()
        extra['sequence'] = LogHandler.counter.next()
        kwargs['extra'] = extra
        try:
            return getattr(self.logger, severity)(msg, *args, **kwargs)
        except:
            pass

    def info(self, msg, *args, **kwargs):
        """ Info """
        return self._log(msg, 'info', *args, **kwargs)

    def error(self, msg, *args, **kwargs):
        """ Error """
        return self._log(msg, 'error', *args, **kwargs)

    def debug(self, msg, *args, **kwargs):
        """ Debug """
        return self._log(msg, 'debug', *args, **kwargs)

    def warning(self, msg, *args, **kwargs):
        """ Warning """
        return self._log(msg, 'warning', *args, **kwargs)

    def log(self, msg, *args, **kwargs):
        """ Log """
        return self._log(msg, 'log', *args, **kwargs)

    def critical(self, msg, *args, **kwargs):
        """ Critical """
        return self._log(msg, 'critical', *args, **kwargs)

    def exception(self, msg, *args, **kwargs):
        """ Exception """
        return self._log(msg, 'exception', *args, **kwargs)
Exemplo n.º 4
0
class LogHandler(object):
    """
    Log handler.

    WARNING: This log handler might be highly unreliable if not used correctly. It can log to redis, but if Redis is
    not working as expected, it will result in lost log messages. If you want reliable logging, do not use Redis at all
    or log to files and have a separate process forward them to Redis (so logs can be re-send if Redis is unavailable)
    """

    counter = itertools.count()
    cache = {}
    propagate_cache = {}

    def __init__(self, source, name, propagate):
        """
        Initializes the logger
        """
        parent_invoker = inspect.stack()[1]
        if not __file__.startswith(parent_invoker[1]) or parent_invoker[3] != 'get':
            raise RuntimeError('Cannot invoke instance from outside this class. Please use LogHandler.get(source, name=None) instead')

        if name is None:
            name = 'logger'

        formatter = OVSFormatter('%(asctime)s - %(hostname)s - %(process)s/%(thread)d - {0}/%(name)s - %(sequence)s - %(levelname)s - %(message)s'.format(source))

        target_definition = LogHandler.load_target_definition(source, allow_override=True)
        if target_definition['type'] == 'redis':
            from redis import Redis
            from ovs.log.redis_logging import RedisListHandler
            self.handler = RedisListHandler(queue=target_definition['queue'],
                                            client=Redis(host=target_definition['host'],
                                                         port=target_definition['port']))
        elif target_definition['type'] == 'file':
            self.handler = logging.FileHandler(target_definition['filename'])
        else:
            self.handler = logging.StreamHandler(sys.stdout)
        self.handler.setFormatter(formatter)
        self.logger = logging.getLogger(name)
        self.logger.addHandler(self.handler)
        self.logger.propagate = propagate
        self.logger.setLevel(getattr(logging, 'DEBUG'))
        self._key = '{0}_{1}'.format(source, name)

    @staticmethod
    def load_target_definition(source, allow_override=False):
        """
        Load the logger target
        :param source: Source
        :param allow_override: Allow override
        :return: Target definition
        """
        logging_target = {'type': 'console'}
        try:
            from ovs.extensions.generic.configuration import Configuration
            logging_target = Configuration.get('/ovs/framework/logging')
        except:
            pass

        target_type = logging_target.get('type', 'console')
        if allow_override is True and 'OVS_LOGTYPE_OVERRIDE' in os.environ:
            target_type = os.environ['OVS_LOGTYPE_OVERRIDE']

        if target_type == 'redis':
            queue = logging_target.get('queue', '/ovs/logging')
            if '{0}' in queue:
                queue = queue.format(source)
            return {'type': 'redis',
                    'queue': '/{0}'.format(queue.lstrip('/')),
                    'host': logging_target.get('host', 'localhost'),
                    'port': logging_target.get('port', 6379)}
        if target_type == 'file':
            return {'type': 'file',
                    'filename': LogHandler.load_path(source)}
        return {'type': 'console'}

    @staticmethod
    def get_sink_path(source, allow_override=False):
        """
        Retrieve the path to sink logs to
        :param source: Source
        :param allow_override: Allow override
        :return: The path to sink to
        """
        target_definition = LogHandler.load_target_definition(source, allow_override)
        if target_definition['type'] == 'redis':
            sink = 'redis://{0}:{1}{2}'.format(target_definition['host'], target_definition['port'], target_definition['queue'])
        elif target_definition['type'] == 'file':
            sink = target_definition['filename']
        else:
            sink = 'console:'
        return sink

    @staticmethod
    def load_path(source):
        """
        Load path
        :param source: Source
        :return: Path
        """
        log_path = '/var/log/ovs'
        log_filename = '{0}/{1}.log'.format(log_path, source)
        if not os.path.exists(log_path):
            os.mkdir(log_path, 0777)
        if not os.path.exists(log_filename):
            open(log_filename, 'a').close()
            os.chmod(log_filename, 0o666)
        return log_filename

    @staticmethod
    def get(source, name=None, propagate=False):
        """
        Retrieve a loghandler instance
        """
        key = '{0}_{1}'.format(source, name)
        if key not in LogHandler.cache:
            logger = LogHandler(source, name, propagate)
            LogHandler.cache[key] = logger
        if key not in LogHandler.propagate_cache:
            LogHandler.propagate_cache[key] = propagate
        return LogHandler.cache[key]

    def _fix_propagate(self):
        """
        Obey propagate flag as initially called
        - celery will overwrite it to catch the logging
        """
        propagate = LogHandler.propagate_cache.get(self._key, None)
        if propagate is not None:
            self.logger.propagate = propagate

    def _log(self, msg, severity, *args, **kwargs):
        """
        Log pass-through
        """
        self._fix_propagate()
        if 'print_msg' in kwargs:
            del kwargs['print_msg']
            print msg
        extra = kwargs.get('extra', {})
        extra['hostname'] = socket.gethostname()
        extra['sequence'] = LogHandler.counter.next()
        kwargs['extra'] = extra
        try:
            return getattr(self.logger, severity)(msg, *args, **kwargs)
        except:
            pass

    def info(self, msg, *args, **kwargs):
        """ Info """
        return self._log(msg, 'info', *args, **kwargs)

    def error(self, msg, *args, **kwargs):
        """ Error """
        return self._log(msg, 'error', *args, **kwargs)

    def debug(self, msg, *args, **kwargs):
        """ Debug """
        return self._log(msg, 'debug', *args, **kwargs)

    def warning(self, msg, *args, **kwargs):
        """ Warning """
        return self._log(msg, 'warning', *args, **kwargs)

    def log(self, msg, *args, **kwargs):
        """ Log """
        return self._log(msg, 'log', *args, **kwargs)

    def critical(self, msg, *args, **kwargs):
        """ Critical """
        return self._log(msg, 'critical', *args, **kwargs)

    def exception(self, msg, *args, **kwargs):
        """ Exception """
        return self._log(msg, 'exception', *args, **kwargs)