Esempio n. 1
0
class FrontikApplication(Application):
    request_id = 0

    class DefaultConfig:
        pass

    def __init__(self, **settings):
        self.start_time = time.time()

        tornado_settings = settings.get('tornado_settings')
        if tornado_settings is None:
            tornado_settings = {}

        self.config = self.application_config()
        self.app = settings.get('app')
        self.app_module = settings.get('app_module')
        self.app_root = settings.get('app_root')

        self.xml = frontik.producers.xml_producer.XMLProducerFactory(self)
        self.json = frontik.producers.json_producer.JsonProducerFactory(self)

        AsyncHTTPClient.configure(
            'tornado.curl_httpclient.CurlAsyncHTTPClient',
            max_clients=options.max_http_clients)
        self.tornado_http_client = AsyncHTTPClient()

        if options.max_http_clients_connects is not None:
            self.tornado_http_client._multi.setopt(
                pycurl.M_MAXCONNECTS, options.max_http_clients_connects)

        self.service_discovery_client = None
        self.http_client_factory = None

        self.router = FrontikRouter(self)

        core_handlers = [
            (r'/version/?', VersionHandler),
            (r'/status/?', StatusHandler),
            (r'.*', self.router),
        ]

        if options.debug:
            core_handlers.insert(0, (r'/pydevd/?', PydevdHandler))

        self.service_discovery_client = get_async_service_discovery(
            options, hostname=socket.gethostname())

        self.available_integrations = None

        super().__init__(core_handlers, **tornado_settings)

    async def init(self):
        self.transforms.insert(0, partial(DebugTransform, self))

        self.available_integrations, integration_futures = integrations.load_integrations(
            self)
        await asyncio.gather(
            *[future for future in integration_futures if future])

        kafka_cluster = options.http_client_metrics_kafka_cluster
        send_metrics_to_kafka = kafka_cluster and kafka_cluster in options.kafka_clusters

        if kafka_cluster and kafka_cluster not in options.kafka_clusters:
            app_logger.warning(
                'kafka cluster for http client metrics "%s" is not present in "kafka_clusters" option, '
                'metrics will be disabled', kafka_cluster)
        else:
            app_logger.info('kafka metrics are %s',
                            'enabled' if send_metrics_to_kafka else 'disabled')

        kafka_producer = self.get_kafka_producer(
            kafka_cluster) if send_metrics_to_kafka else None

        self.http_client_factory = HttpClientFactory(
            self.app,
            self.tornado_http_client,
            getattr(self.config, 'http_upstreams', {}),
            statsd_client=self.statsd_client,
            kafka_producer=kafka_producer)

    def find_handler(self, request, **kwargs):
        request_id = request.headers.get('X-Request-Id')
        if request_id is None:
            request_id = FrontikApplication.next_request_id()

        context = partial(request_context.RequestContext, {
            'request': request,
            'request_id': request_id
        })

        def wrapped_in_context(func):
            def wrapper(*args, **kwargs):
                token = request_context.initialize(request, request_id)

                try:
                    with StackContext(context):
                        return func(*args, **kwargs)
                finally:
                    request_context.reset(token)

            return wrapper

        delegate = wrapped_in_context(super().find_handler)(request, **kwargs)
        delegate.headers_received = wrapped_in_context(
            delegate.headers_received)
        delegate.data_received = wrapped_in_context(delegate.data_received)
        delegate.finish = wrapped_in_context(delegate.finish)
        delegate.on_connection_close = wrapped_in_context(
            delegate.on_connection_close)

        return delegate

    def reverse_url(self, name, *args, **kwargs):
        return self.router.reverse_url(name, *args, **kwargs)

    def application_urls(self):
        return [('',
                 FileMappingRouter(
                     importlib.import_module(f'{self.app_module}.pages')))]

    def application_404_handler(self, request):
        return ErrorHandler, {'status_code': 404}

    def application_config(self):
        return FrontikApplication.DefaultConfig()

    def application_version_xml(self):
        version = etree.Element('version')
        version.text = 'unknown'
        return [version]

    def application_version(self):
        return None

    @staticmethod
    def next_request_id():
        FrontikApplication.request_id += 1
        return str(FrontikApplication.request_id)

    def get_current_status(self):
        cur_uptime = time.time() - self.start_time
        if cur_uptime < 60:
            uptime_value = '{:.2f} seconds'.format(cur_uptime)
        elif cur_uptime < 3600:
            uptime_value = '{:.2f} minutes'.format(cur_uptime / 60)
        else:
            uptime_value = '{:.2f} hours and {:.2f} minutes'.format(
                cur_uptime / 3600, (cur_uptime % 3600) / 60)

        return {
            'uptime': uptime_value,
            'datacenter': options.datacenter,
            'workers': {
                'total':
                len(self.http_client_factory.tornado_http_client._curls),
                'free':
                len(self.http_client_factory.tornado_http_client._free_list)
            }
        }

    def log_request(self, handler):
        if not options.log_json:
            super().log_request(handler)
            return

        request_time = int(1000.0 * handler.request.request_time())
        extra = {
            'ip': handler.request.remote_ip,
            'rid': request_context.get_request_id(),
            'status': handler.get_status(),
            'time': request_time,
            'method': handler.request.method,
            'uri': handler.request.uri,
        }

        handler_name = request_context.get_handler_name()
        if handler_name:
            extra['controller'] = handler_name

        JSON_REQUESTS_LOGGER.info('', extra={CUSTOM_JSON_EXTRA: extra})

    def get_kafka_producer(
        self, producer_name: str
    ) -> 'Optional[AIOKafkaProducer]':  # pragma: no cover
        pass

    def get_sentry_logger(
        self, request: 'HTTPServerRequest'
    ) -> 'Optional[SentryLogger]':  # pragma: no cover
        pass
Esempio n. 2
0
File: app.py Progetto: hhru/frontik
class FrontikApplication(Application):
    request_id = 0

    class DefaultConfig:
        pass

    def __init__(self, **settings):
        self.start_time = time.time()

        tornado_settings = settings.get('tornado_settings')
        if tornado_settings is None:
            tornado_settings = {}

        self.config = self.application_config()
        self.app = settings.get('app')
        self.app_root = settings.get('app_root')

        self.xml = frontik.producers.xml_producer.XMLProducerFactory(self)
        self.json = frontik.producers.json_producer.JsonProducerFactory(self)

        self.http_client_factory = HttpClientFactory(self, getattr(self.config, 'http_upstreams', {}))

        self.router = FrontikRouter(self)
        self.available_integrations, self.default_init_futures = integrations.load_integrations(self)

        super().__init__([
            (r'/version/?', VersionHandler),
            (r'/status/?', StatusHandler),
            (r'.*', self.router),
        ], **tornado_settings)

        self.transforms.insert(0, partial(DebugTransform, self))

    def find_handler(self, request, **kwargs):
        request_id = request.headers.get('X-Request-Id')
        if request_id is None:
            request_id = FrontikApplication.next_request_id()

        context = partial(request_context.RequestContext, {'request_id': request_id})

        def wrapped_in_context(func):
            def wrapper(*args, **kwargs):
                token = request_context.initialize(request_id)

                try:
                    with StackContext(context):
                        return func(*args, **kwargs)
                finally:
                    request_context.reset(token)

            return wrapper

        delegate = wrapped_in_context(super().find_handler)(request, **kwargs)
        delegate.headers_received = wrapped_in_context(delegate.headers_received)
        delegate.data_received = wrapped_in_context(delegate.data_received)
        delegate.finish = wrapped_in_context(delegate.finish)
        delegate.on_connection_close = wrapped_in_context(delegate.on_connection_close)

        return delegate

    def reverse_url(self, name, *args, **kwargs):
        return self.router.reverse_url(name, *args, **kwargs)

    def application_urls(self):
        return [
            ('', FileMappingRouter(importlib.import_module(f'{self.app}.pages')))
        ]

    def application_404_handler(self, request):
        return ErrorHandler, {'status_code': 404}

    def application_config(self):
        return FrontikApplication.DefaultConfig()

    def application_version_xml(self):
        version = etree.Element('version')
        version.text = 'unknown'
        return [version]

    def application_version(self):
        return None

    def init_async(self):
        return []

    @staticmethod
    def next_request_id():
        FrontikApplication.request_id += 1
        return str(FrontikApplication.request_id)

    def get_current_status(self):
        cur_uptime = time.time() - self.start_time
        if cur_uptime < 60:
            uptime_value = '{:.2f} seconds'.format(cur_uptime)
        elif cur_uptime < 3600:
            uptime_value = '{:.2f} minutes'.format(cur_uptime / 60)
        else:
            uptime_value = '{:.2f} hours and {:.2f} minutes'.format(cur_uptime / 3600, (cur_uptime % 3600) / 60)

        return {
            'uptime': uptime_value,
            'datacenter': options.datacenter,
            'workers': {
                'total': options.max_http_clients,
                'free': len(self.http_client_factory.tornado_http_client._free_list)
            }
        }

    def log_request(self, handler):
        if not options.log_json:
            super().log_request(handler)
            return

        request_time = int(1000.0 * handler.request.request_time())
        extra = {
            'ip': handler.request.remote_ip,
            'rid': request_context.get_request_id(),
            'status': handler.get_status(),
            'time': request_time,
            'method': handler.request.method,
            'uri': handler.request.uri,
        }

        handler_name = request_context.get_handler_name()
        if handler_name:
            extra['controller'] = handler_name

        JSON_REQUESTS_LOGGER.info('', extra={CUSTOM_JSON_EXTRA: extra})
Esempio n. 3
0
class FrontikApplication(Application):
    request_id = 0

    class DefaultConfig(object):
        pass

    def __init__(self, **settings):
        self.start_time = time.time()

        tornado_settings = settings.get('tornado_settings')
        if tornado_settings is None:
            tornado_settings = {}

        self.app_settings = settings
        self.config = self.application_config()
        self.app = settings.get('app')

        self.xml = frontik.producers.xml_producer.XMLProducerFactory(self)
        self.json = frontik.producers.json_producer.JsonProducerFactory(self)

        AsyncHTTPClient.configure(
            'tornado.curl_httpclient.CurlAsyncHTTPClient',
            max_clients=options.max_http_clients)
        self.http_client = self.curl_http_client = AsyncHTTPClient()

        self.router = FrontikRouter(self)
        self.loggers_initializers = bootstrap_app_loggers(self)

        super(FrontikApplication, self).__init__([
            (r'/version/?', VersionHandler),
            (r'/status/?', StatusHandler),
            (r'.*', self.router),
        ], **tornado_settings)

        self.transforms.insert(0, partial(DebugTransform, self))

    def __call__(self, request):
        request_id = request.headers.get('X-Request-Id')
        if request_id is None:
            request_id = FrontikApplication.next_request_id()

        with StackContext(partial(RequestContext, {'request_id': request_id})):
            return super(FrontikApplication, self).__call__(request)

    def reverse_url(self, name, *args, **kwargs):
        return self.router.reverse_url(name, *args, **kwargs)

    def application_urls(self):
        return [('',
                 FileMappingRouter(
                     importlib.import_module('{}.pages'.format(self.app))))]

    def application_404_handler(self, request):
        return ErrorHandler, {'status_code': 404}

    def application_config(self):
        return FrontikApplication.DefaultConfig()

    def application_version_xml(self):
        version = etree.Element('version')
        version.text = 'unknown'
        return [version]

    def init_async(self):
        init_future = Future()
        init_future.set_result(None)
        return init_future

    @staticmethod
    def next_request_id():
        FrontikApplication.request_id += 1
        return str(FrontikApplication.request_id)

    def get_current_status(self):
        cur_uptime = time.time() - self.start_time
        if cur_uptime < 60:
            uptime_value = '{:.2f} seconds'.format(cur_uptime)
        elif cur_uptime < 3600:
            uptime_value = '{:.2f} minutes'.format(cur_uptime / 60)
        else:
            uptime_value = '{:.2f} hours and {:.2f} minutes'.format(
                cur_uptime / 3600, (cur_uptime % 3600) / 60)

        return {
            'uptime': uptime_value,
            'workers': {
                'total': options.max_http_clients,
                'free': len(self.curl_http_client._free_list)
            }
        }

    def log_request(self, handler):
        super(FrontikApplication, self).log_request(handler)
        if isinstance(getattr(handler, 'log', None), request.RequestLogger):
            handler.log.stage_tag('flush')
            handler.log.log_stages(handler.get_status())