""" Configuration functions for the logging package. """ from __future__ import absolute_import import logging import sys from . import buildlogger from . import formatters from . import loggers _DEFAULT_FORMAT = "[%(name)s] %(message)s" def using_buildlogger(logging_config): """ Returns true if buildlogger is set as a handler on the "fixture" or "tests" loggers, and false otherwise. """ for logger_name in (loggers.FIXTURE_LOGGER_NAME, loggers.TESTS_LOGGER_NAME): logger_info = logging_config[logger_name] if _get_buildlogger_handler_info(logger_info) is not None: return True return False def apply_config(logging_config): """ Adds all handlers specified by the configuration to the "executor", "fixture", and "tests" loggers. """ logging_components = (loggers.EXECUTOR_LOGGER_NAME, loggers.FIXTURE_LOGGER_NAME, loggers.TESTS_LOGGER_NAME) if not all(component in logging_config for component in logging_components): raise ValueError("Logging configuration should contain %s, %s, and %s components" % logging_components) # Configure the executor, fixture, and tests loggers. for component in logging_components: logger = loggers.LOGGERS_BY_NAME[component] logger_info = logging_config[component] _configure_logger(logger, logger_info) # Configure the buildlogger logger. loggers._BUILDLOGGER_FALLBACK.addHandler(_fallback_buildlogger_handler()) def apply_buildlogger_global_handler(logger, logging_config, build_id=None, build_config=None): """ Adds a buildlogger.BuildloggerGlobalHandler to 'logger' if specified to do so by the configuration. """ logger_info = logging_config[loggers.FIXTURE_LOGGER_NAME] handler_info = _get_buildlogger_handler_info(logger_info) if handler_info is None: # Not configured to use buildlogger. return if all(x is not None for x in (build_id, build_config)): log_format = logger_info.get("format", _DEFAULT_FORMAT) formatter = formatters.ISO8601Formatter(fmt=log_format) handler = buildlogger.BuildloggerGlobalHandler(build_id, build_config, **handler_info) handler.setFormatter(formatter) else: handler = _fallback_buildlogger_handler() # Fallback handler already has formatting configured. logger.addHandler(handler) def apply_buildlogger_test_handler(logger, logging_config, build_id=None, build_config=None, test_id=None): """ Adds a buildlogger.BuildloggerTestHandler to 'logger' if specified to do so by the configuration. """ logger_info = logging_config[loggers.TESTS_LOGGER_NAME] handler_info = _get_buildlogger_handler_info(logger_info) if handler_info is None: # Not configured to use buildlogger. return if all(x is not None for x in (build_id, build_config, test_id)): log_format = logger_info.get("format", _DEFAULT_FORMAT) formatter = formatters.ISO8601Formatter(fmt=log_format) handler = buildlogger.BuildloggerTestHandler(build_id, build_config, test_id, **handler_info) handler.setFormatter(formatter) else: handler = _fallback_buildlogger_handler() # Fallback handler already has formatting configured. logger.addHandler(handler) def _configure_logger(logger, logger_info): """ Adds the handlers specified by the configuration to 'logger'. """ log_format = logger_info.get("format", _DEFAULT_FORMAT) formatter = formatters.ISO8601Formatter(fmt=log_format) for handler_info in logger_info.get("handlers", []): handler_class = handler_info["class"] if handler_class == "logging.FileHandler": handler = logging.FileHandler(filename=handler_info["filename"], mode=handler_info.get("mode", "w")) elif handler_class == "logging.NullHandler": handler = logging.NullHandler() elif handler_class == "logging.StreamHandler": handler = logging.StreamHandler(sys.stdout) elif handler_class == "buildlogger": continue # Buildlogger handlers are applied when running tests. else: raise ValueError("Unknown handler class '%s'" % (handler_class)) handler.setFormatter(formatter) logger.addHandler(handler) def _fallback_buildlogger_handler(): """ Returns a handler that writes to stderr. """ log_format = "[buildlogger:%(name)s] %(message)s" formatter = formatters.ISO8601Formatter(fmt=log_format) handler = logging.StreamHandler(sys.stderr) handler.setFormatter(formatter) return handler def _get_buildlogger_handler_info(logger_info): """ Returns the buildlogger handler information if it exists, and None otherwise. """ for handler_info in logger_info["handlers"]: handler_info = handler_info.copy() if handler_info.pop("class") == "buildlogger": return handler_info return None