Source code for aodncore.pipeline.log

"""This module provides logging related objects for dynamically constructing logging configurations and retrieving
configured :py:class:`LoggerAdapter`/:py:class:`Logger` instances
"""

import logging
import os

from ..util import validate_nonstring_iterable

# custom SYSINFO logging level
SYSINFO = 15
logging.addLevelName(SYSINFO, 'SYSINFO')

__all__ = [
    'SYSINFO',
    'WorkerLoggingConfigBuilder',
    'get_watchservice_logging_config',
    'get_pipeline_logger'
]


[docs]class WorkerLoggingConfigBuilder(object): def __init__(self, pipeline_config): self.pipeline_config = pipeline_config liblevel = self.pipeline_config['logging'].get('liblevel', 'WARN') self._dict_config = { 'version': 1, 'formatters': { 'pipeline_formatter': { 'format': self.pipeline_config['logging']['pipeline_format'] } }, 'filters': {}, 'handlers': {}, 'loggers': { 'botocore': { 'level': liblevel }, 'paramiko': { 'level': liblevel }, 's3transfer': { 'level': liblevel }, 'transitions': { 'level': liblevel } } }
[docs] def add_watch_config(self, name, formatter='pipeline_formatter', level=None): """Add logging configuration for a single pipeline watch :param name: name of the pipeline for which the config is being generated :param formatter: name of the formatter to use for handler :param level: logging level :return: dict containing handlers/loggers for a single watch """ if level is None: level = self.pipeline_config['logging']['level'] handler_name = "{name}_handler".format(name=name) self._dict_config['handlers'][handler_name] = { 'level': level, 'class': 'logging.FileHandler', 'formatter': formatter, 'filename': os.path.join(self.pipeline_config['logging']['log_root'], 'process', "{name}.log".format(name=name)), 'delay': True } self._dict_config['loggers'][name] = { 'handlers': [handler_name], 'level': level, 'propagate': False } return self
[docs] def add_watches(self, watches): validate_nonstring_iterable(watches) for watch in watches: self.add_watch_config(watch)
[docs] def build(self): return self._dict_config
[docs]def get_watchservice_logging_config(pipeline_config): """Generate logging configuration for the 'watchservice' service, suitable for use by :py:meth:`logging.config.dictConfig` :param pipeline_config: :py:attr:`LazyConfigManager.pipeline_config` instance :return: rendered watchservice logging config """ watchservice_logging_config = { 'version': 1, 'formatters': { 'watchservice_formatter': { 'format': pipeline_config['logging']['watchservice_format'] } }, 'filters': {}, 'handlers': { 'watchservice_handler': { 'level': pipeline_config['logging']['level'], 'class': 'logging.StreamHandler', 'formatter': 'watchservice_formatter' } }, 'loggers': { 'watchservice': { 'handlers': ['watchservice_handler'], 'level': pipeline_config['logging']['level'], 'propagate': False } } } return watchservice_logging_config
[docs]def get_pipeline_logger(name, extra=None, logger_function=logging.getLogger): """Return a logger adapter prepared with given extra metadata and SYSINFO logging level :param name: logger name :param extra: extra dict to pass to :py:class:`LoggerAdapter` :param logger_function: factory function which accepts a logger name and returns a :py:class:`Logger` instance :return: :py:class:`Logger` instance """ if extra is None: extra = {} logger = logger_function(name) logger_adapter = logging.LoggerAdapter(logger, extra) # patch a sysinfo helper method into the logger setattr(logger_adapter, 'sysinfo', lambda *args: logger_adapter.log(SYSINFO, *args)) return logger_adapter