Exemplo n.º 1
0
    def __call__(self, env, start_response):
        start_response_args = [None]
        input_proxy = InputProxy(env['wsgi.input'])
        env['wsgi.input'] = input_proxy

        def my_start_response(status, headers, exc_info=None):
            start_response_args[0] = (status, list(headers), exc_info)

        def iter_response(iterable):
            if start_response_args[0]:
                start_response(*start_response_args[0])
            bytes_sent = 0
            try:
                for chunk in iterable:
                    if chunk:
                        bytes_sent += len(chunk)
                    yield chunk
            finally:
                self.publish_sample(env, input_proxy.bytes_received,
                                    bytes_sent)

        try:
            iterable = self.app(env, my_start_response)
        except Exception:
            self.publish_sample(env, input_proxy.bytes_received, 0)
            raise
        else:
            return iter_response(iterable)
Exemplo n.º 2
0
    def __call__(self, env, start_response):
        start_response_args = [None]
        input_proxy = InputProxy(env['wsgi.input'])
        env['wsgi.input'] = input_proxy
        start_time = time.time()

        def my_start_response(status, headers, exc_info=None):
            start_response_args[0] = (status, list(headers), exc_info)

        def iter_response(iterable):
            iterator = iter(iterable)
            try:
                chunk = iterator.next()
                while not chunk:
                    chunk = iterator.next()
            except StopIteration:
                chunk = ''
            for h, v in start_response_args[0][1]:
                if h.lower() in ('content-length', 'transfer-encoding'):
                    break
            else:
                if not chunk:
                    start_response_args[0][1].append(('content-length', '0'))
                elif isinstance(iterable, list):
                    start_response_args[0][1].append(
                        ('content-length', str(sum(len(i) for i in iterable))))
            start_response(*start_response_args[0])
            bytes_sent = 0
            client_disconnect = False
            try:
                while chunk:
                    bytes_sent += len(chunk)
                    yield chunk
                    chunk = iterator.next()
            except GeneratorExit:  # generator was closed before we finished
                client_disconnect = True
                raise
            finally:
                status_int = int(start_response_args[0][0].split(' ', 1)[0])
                self.log_request(
                    env, status_int, input_proxy.bytes_received, bytes_sent,
                    time.time() - start_time, client_disconnect
                    or input_proxy.client_disconnect)

        try:
            iterable = self.app(env, my_start_response)
        except Exception:
            self.log_request(env, 500, input_proxy.bytes_received, 0,
                             time.time() - start_time,
                             input_proxy.client_disconnect)
            raise
        else:
            return iter_response(iterable)
Exemplo n.º 3
0
    def __call__(self, env, start_response):
        if self.req_already_logged(env):
            return self.app(env, start_response)

        self.mark_req_logged(env)

        start_response_args = [None]
        input_proxy = InputProxy(env['wsgi.input'])
        env['wsgi.input'] = input_proxy
        start_time = time.time()

        def my_start_response(status, headers, exc_info=None):
            start_response_args[0] = (status, list(headers), exc_info)

        def status_int_for_logging(client_disconnect=False, start_status=None):
            # log disconnected clients as '499' status code
            if client_disconnect or input_proxy.client_disconnect:
                ret_status_int = 499
            elif start_status is None:
                ret_status_int = int(start_response_args[0][0].split(' ',
                                                                     1)[0])
            else:
                ret_status_int = start_status
            return ret_status_int

        def iter_response(iterable):
            iterator = iter(iterable)  #获取可迭代对象的迭代器
            try:
                chunk = next(iterator)
                while not chunk:
                    chunk = next(iterator)
            except StopIteration:
                chunk = ''
            for h, v in start_response_args[0][1]:
                if h.lower() in ('content-length', 'transfer-encoding'):
                    break
            else:
                if not chunk:
                    start_response_args[0][1].append(('Content-Length', '0'))
                elif isinstance(iterable, list):
                    start_response_args[0][1].append(
                        ('Content-Length', str(sum(len(i) for i in iterable))))
            resp_headers = dict(start_response_args[0][1])
            start_response(*start_response_args[0])
            req = Request(env)

            # Log timing information for time-to-first-byte (GET requests only)
            method = self.method_from_req(req)
            if method == 'GET':
                status_int = status_int_for_logging()
                policy_index = get_policy_index(req.headers, resp_headers)
                metric_name = self.statsd_metric_name(req, status_int, method)
                metric_name_policy = self.statsd_metric_name_policy(
                    req, status_int, method, policy_index)
                if metric_name:
                    self.access_logger.timing_since(
                        metric_name + '.first-byte.timing', start_time)
                if metric_name_policy:
                    self.access_logger.timing_since(
                        metric_name_policy + '.first-byte.timing', start_time)

            bytes_sent = 0
            client_disconnect = False
            try:
                while chunk:
                    bytes_sent += len(chunk)
                    yield chunk
                    chunk = next(iterator)
            except GeneratorExit:  # generator was closed before we finished
                client_disconnect = True
                raise
            finally:
                status_int = status_int_for_logging(client_disconnect)
                self.log_request(req,
                                 status_int,
                                 input_proxy.bytes_received,
                                 bytes_sent,
                                 start_time,
                                 time.time(),
                                 resp_headers=resp_headers)
                close_method = getattr(iterable, 'close', None)
                if callable(close_method):
                    close_method()

        try:
            iterable = self.app(env, my_start_response)
        except Exception:
            exc_type, exc_value, exc_traceback = sys.exc_info()
            req = Request(env)
            status_int = status_int_for_logging(start_status=500)
            self.log_request(req, status_int, input_proxy.bytes_received, 0,
                             start_time, time.time())
            six.reraise(exc_type, exc_value, exc_traceback)
        else:
            return iter_response(iterable)
Exemplo n.º 4
0
    def __call__(self, env, start_response):
        start_response_args = [None]
        input_proxy = InputProxy(env['wsgi.input'])
        env['wsgi.input'] = input_proxy
        start_time = time.time()

        def my_start_response(status, headers, exc_info=None):
            start_response_args[0] = (status, list(headers), exc_info)

        def status_int_for_logging(client_disconnect=False, start_status=None):
            # log disconnected clients as '499' status code
            if client_disconnect or input_proxy.client_disconnect:
                return 499
            elif start_status is None:
                return int(start_response_args[0][0].split(' ', 1)[0])
            return start_status

        def iter_response(iterable):
            iterator = iter(iterable)
            try:
                chunk = iterator.next()
                while not chunk:
                    chunk = iterator.next()
            except StopIteration:
                chunk = ''
            for h, v in start_response_args[0][1]:
                if h.lower() in ('content-length', 'transfer-encoding'):
                    break
            else:
                if not chunk:
                    start_response_args[0][1].append(('content-length', '0'))
                elif isinstance(iterable, list):
                    start_response_args[0][1].append(
                        ('content-length', str(sum(len(i) for i in iterable))))
            start_response(*start_response_args[0])
            req = Request(env)

            # Log timing information for time-to-first-byte (GET requests only)
            method = self.method_from_req(req)
            if method == 'GET' and not self.req_already_logged(req):
                status_int = status_int_for_logging()
                metric_name = self.statsd_metric_name(req, status_int, method)
                if metric_name:
                    self.access_logger.timing_since(
                        metric_name + '.first-byte.timing', start_time)

            bytes_sent = 0
            client_disconnect = False
            try:
                while chunk:
                    bytes_sent += len(chunk)
                    yield chunk
                    chunk = iterator.next()
            except GeneratorExit:  # generator was closed before we finished
                client_disconnect = True
                raise
            finally:
                status_int = status_int_for_logging(client_disconnect)
                self.log_request(req, status_int, input_proxy.bytes_received,
                                 bytes_sent,
                                 time.time() - start_time)

        try:
            iterable = self.app(env, my_start_response)
        except Exception:
            req = Request(env)
            status_int = status_int_for_logging(start_status=500)
            self.log_request(req, status_int, input_proxy.bytes_received, 0,
                             time.time() - start_time)
            raise
        else:
            return iter_response(iterable)
Exemplo n.º 5
0
    def __call__(self, env, start_response):
        if self.req_already_logged(env):
            return self.app(env, start_response)

        self.mark_req_logged(env)

        start_response_args = [None]
        input_proxy = InputProxy(env['wsgi.input'])
        env['wsgi.input'] = input_proxy
        start_time = time.time()

        def my_start_response(status, headers, exc_info=None):
            start_response_args[0] = (status, list(headers), exc_info)

        def status_int_for_logging(start_status, client_disconnect=False):
            # log disconnected clients as '499' status code
            if client_disconnect or input_proxy.client_disconnect:
                return 499
            return start_status

        def iter_response(iterable):
            iterator = reiterate(iterable)
            content_length = None
            for h, v in start_response_args[0][1]:
                if h.lower() == 'content-length':
                    content_length = int(v)
                    break
                elif h.lower() == 'transfer-encoding':
                    break
            else:
                if isinstance(iterator, list):
                    content_length = sum(len(i) for i in iterator)
                    start_response_args[0][1].append(
                        ('Content-Length', str(content_length)))

            req = Request(env)
            method = self.method_from_req(req)
            if method == 'HEAD':
                content_length = 0
            if content_length is not None:
                iterator = enforce_byte_count(iterator, content_length)

            wire_status_int = int(start_response_args[0][0].split(' ', 1)[0])
            resp_headers = dict(start_response_args[0][1])
            start_response(*start_response_args[0])

            # Log timing information for time-to-first-byte (GET requests only)
            ttfb = 0.0
            if method == 'GET':
                policy_index = get_policy_index(req.headers, resp_headers)
                metric_name = self.statsd_metric_name(req, wire_status_int,
                                                      method)
                metric_name_policy = self.statsd_metric_name_policy(
                    req, wire_status_int, method, policy_index)
                ttfb = time.time() - start_time
                if metric_name:
                    self.access_logger.timing(
                        metric_name + '.first-byte.timing', ttfb * 1000)
                if metric_name_policy:
                    self.access_logger.timing(
                        metric_name_policy + '.first-byte.timing', ttfb * 1000)

            bytes_sent = 0
            client_disconnect = False
            start_status = wire_status_int
            try:
                for chunk in iterator:
                    bytes_sent += len(chunk)
                    yield chunk
            except StopIteration:  # iterator was depleted
                return
            except GeneratorExit:  # generator was closed before we finished
                client_disconnect = True
                raise
            except Exception:
                start_status = 500
                raise
            finally:
                status_int = status_int_for_logging(start_status,
                                                    client_disconnect)
                self.log_request(req,
                                 status_int,
                                 input_proxy.bytes_received,
                                 bytes_sent,
                                 start_time,
                                 time.time(),
                                 resp_headers=resp_headers,
                                 ttfb=ttfb,
                                 wire_status_int=wire_status_int)
                iterator.close()

        try:
            iterable = self.app(env, my_start_response)
        except Exception:
            req = Request(env)
            status_int = status_int_for_logging(500)
            self.log_request(req, status_int, input_proxy.bytes_received, 0,
                             start_time, time.time())
            raise
        else:
            return iter_response(iterable)