"""Logging plugin for Henson."""

import logging
import logging.config

from henson import current_application
import structlog

from . import processors

__all__ = ('Logging',)


def get_app(app=None):
    """Return an application.

    If no application is provided through ``app``, the current
    application will be loaded from Henson.

    Args:
        app (:class:`~henson.Application`, optional): An application
          that will be returned if provided.

    Returns:
        :class:`~henson.Application`: The application.

    Raises:
        RuntimeError: There is no application.
    """
    if app is not None:
        return app

    app = current_application
    if app:
        return app

    raise RuntimeError(
        'The client is not registered to an application and no '
        'application is available.')


class Logging:

    """An interface to use structured logging.

    Args:
        app (:class:`~henson.Application`, optional): An application
          instance that has an attribute named settings that contains a
          mapping of settings to configure logging.
    """

    def __init__(self, app=None):
        """Initialize the instance."""
        self._logger = None

        self.app = app
        if app is not None:
            self.init_app(app)

    def init_app(self, app):
        """Initialize an application for structured logging.

        Args:
            app (:class:`~henson.Application`): An application instance
              that has an attribute named settings that contains a
              mapping of settings to configure logging.
        """
        app.settings.setdefault('LOG_DATE_FORMAT', None)
        app.settings.setdefault('LOG_FORMAT', '%(message)s\n')
        app.settings.setdefault('LOG_HANDLER', 'logging.StreamHandler')
        app.settings.setdefault('LOG_LEVEL', 'DEBUG')
        app.settings.setdefault('LOG_VERSION', 1)

        # TODO: The format for TimeStamper should be controllable
        # through the application settings. Right now the
        # LOG_DATE_FORMAT setting is ignored.
        app.settings.setdefault('LOG_PROCESSORS', (
            structlog.stdlib.filter_by_level,
            processors.add_logger_name,
            structlog.stdlib.add_log_level,
            structlog.processors.TimeStamper(fmt='iso'),
            structlog.processors.StackInfoRenderer(),
            structlog.processors.format_exc_info,
            structlog.processors.JSONRenderer(),
        ))
        app.settings.setdefault('LOG_CONTEXT_CLASS', dict)
        app.settings.setdefault(
            'LOG_FACTORY', structlog.stdlib.LoggerFactory())
        app.settings.setdefault(
            'LOG_WRAPPER_CLASS', structlog.stdlib.BoundLogger)

    critical = lambda s, *a, **kw: s.logger.critical(*a, **kw)
    debug = lambda s, *a, **kw: s.logger.debug(*a, **kw)
    error = lambda s, *a, **kw: s.logger.error(*a, **kw)
    info = lambda s, *a, **kw: s.logger.info(*a, **kw)
    exception = lambda s, *a, **kw: s.logger.exception(*a, **kw)
    fatal = lambda s, *a, **kw: s.logger.fatal(*a, **kw)
    log = lambda s, *a, **kw: s.logger.log(*a, **kw)
    warning = lambda s, *a, **kw: s.logger.warning(*a, **kw)

    @property
    def logger(self):
        """Return the logger.

        Returns:
            :class:`~logging.RootLogger`: The logger.
        """
        if not self._logger:
            app = get_app(self.app)

            settings = {
                'version': app.settings['LOG_VERSION'],
                'formatters': {
                    'henson': {
                        'format': app.settings['LOG_FORMAT'],
                        'datefmt': app.settings['LOG_DATE_FORMAT'],
                    },
                },
                'handlers': {
                    'henson': {
                        'class': app.settings['LOG_HANDLER'],
                        'formatter': 'henson',
                    },
                },
                'loggers': {
                    app.name: {
                        'handlers': ['henson'],
                        'level': app.settings['LOG_LEVEL'],
                    },
                }
            }

            logging.config.dictConfig(settings)

            structlog.configure(
                processors=app.settings['LOG_PROCESSORS'],
                context_class=app.settings['LOG_CONTEXT_CLASS'],
                logger_factory=app.settings['LOG_FACTORY'],
                wrapper_class=app.settings['LOG_WRAPPER_CLASS'],
                cache_logger_on_first_use=True,
            )

            self._logger = structlog.get_logger(app.name)

        return self._logger

@@ -69,47 +69,8 @@
 ig%0A%0A
-from henson import current_application%0A
 impo
@@ -138,665 +138,8 @@
 )%0A%0A%0A
-def get_app(app=None):%0A    %22%22%22Return an application.%0A%0A    If no application is provided through %60%60app%60%60, the current%0A    application will be loaded from Henson.%0A%0A    Args:%0A        app (:class:%60~henson.Application%60, optional): An application%0A          that will be returned if provided.%0A%0A    Returns:%0A        :class:%60~henson.Application%60: The application.%0A%0A    Raises:%0A        RuntimeError: There is no application.%0A    %22%22%22%0A    if app is not None:%0A        return app%0A%0A    app = current_application%0A    if app:%0A        return app%0A%0A    raise RuntimeError(%0A        'The client is not registered to an application and no '%0A        'application is available.')%0A%0A%0A
 clas
@@ -479,24 +479,49 @@
 nstance.%22%22%22%0A
+        self._app = None%0A
         self
@@ -541,31 +541,8 @@
 ne%0A%0A
-        self.app = app%0A
     
@@ -2029,16 +2029,345 @@
 ogger)%0A%0A
+        self._app = app%0A%0A    @property%0A    def app(self):%0A        %22%22%22Return the registered app.%22%22%22%0A        if not self._app:%0A            raise RuntimeError(%0A                'No application has been assigned to this instance. '%0A                'init_app must be called before referencing instance.app.')%0A        return self._app%0A%0A
     crit
@@ -3009,44 +3009,8 @@
 ger:
-%0A            app = get_app(self.app)
 %0A%0A  
@@ -3059,16 +3059,21 @@
 rsion': 
+self.
 app.sett
@@ -3187,24 +3187,29 @@
   'format': 
+self.
 app.settings
@@ -3259,16 +3259,21 @@
 tefmt': 
+self.
 app.sett
@@ -3434,16 +3434,21 @@
 class': 
+self.
 app.sett
@@ -3602,24 +3602,29 @@
             
+self.
 app.name: %7B%0A
@@ -3704,16 +3704,21 @@
 level': 
+self.
 app.sett
@@ -3901,16 +3901,21 @@
 cessors=
+self.
 app.sett
@@ -3964,24 +3964,29 @@
 ntext_class=
+self.
 app.settings
@@ -4039,16 +4039,21 @@
 factory=
+self.
 app.sett
@@ -4103,16 +4103,21 @@
 r_class=
+self.
 app.sett
@@ -4254,16 +4254,21 @@
 _logger(
+self.
 app.name

Remove get_app