import logging

from nameko.extensions import DependencyProvider
from raven import Client
from raven.transport.eventlet import EventletHTTPTransport


class SentryReporter(DependencyProvider):
    """ Send exceptions generated by entrypoints to a sentry server.
    """
    def setup(self):
        sentry_config = self.container.config.get('SENTRY')

        dsn = sentry_config['DSN']
        kwargs = sentry_config.get('CLIENT_CONFIG', {})

        self.client = Client(dsn, transport=EventletHTTPTransport, **kwargs)

    def worker_result(self, worker_ctx, result, exc_info):
        if exc_info is None:
            return

        exc = exc_info[1]
        call_id = worker_ctx.call_id
        parent_call_id = worker_ctx.immediate_parent_call_id

        expected_exceptions = getattr(
            worker_ctx.entrypoint, 'expected_exceptions', tuple())

        level = logging.ERROR
        if expected_exceptions and isinstance(exc, expected_exceptions):
            level = logging.WARNING

        message = (
            'Unhandled exception in call {}: '
            '{} {!r}'.format(call_id, exc_info[0].__name__, str(exc))
        )

        logger = '{}.{}'.format(
            worker_ctx.service_name, worker_ctx.entrypoint.method_name)

        data = {
            'logger': logger,
            'level': level,
            'message': message,
            'tags': {
                'call_id': call_id,
                'parent_call_id': parent_call_id,
            },
        }

        extra = {'exc': exc}

        self.client.captureException(
            exc_info, message=message, extra=extra, data=data)
