Esempio n. 1
0
    def wrapper(message, *args, **kwargs):
        logger = get_logger()
        logger = logger.new(callback=func.__qualname__)
        start = time.time()

        publish_time = message.publish_time
        message_age = time.time() - publish_time.timestamp()

        try:
            result = func(message, *args, **kwargs)
        except Exception:
            end = time.time()
            logger.error(
                "pubsub_message_processed",
                duration=end - start,
                success=False,
                exc_info=True,
                message=message.data,
                message_age=message_age,
                attributes=message.attributes,
                connection_id=message.attributes.get("connection_id"),
            )
            raise

        end = time.time()
        logger.info(
            "pubsub_message_processed",
            duration=end - start,
            success=True,
            connection_id=message.attributes.get("connection_id"),
        )
        return result
def validate_content_type(response: Response) -> Response:
    """Checks if the response content-type is compatible with the request's
    Accept header. If a mismatch is found, log the request.

    Use with flask.after_request hook i.e.

        app.after_request(validate_content_type)

    Note: this currently does very basic validation to cover the common cases.
    It does not support multiple mimetypes or wildcard subtypes (for now).

    If an exception is raised during the request, after_request hooks are not run.
    """
    headers = request.headers
    accept_header = headers.get("Accept", WILDCARD_ACCEPT_HEADER)

    accept_headers = accept_header.split(",")

    if not any(
            is_valid_content_type(h, response.content_type)
            for h in accept_headers):
        logger = get_logger()

        logger.warning(
            "Incompatible request Accept header and response content-type",
            args=dict(request.view_args)
            if request.view_args is not None else None,
            headers=dict(headers),
            url=request.full_path,
            request_accept_header=accept_header,
            response_content_type=response.content_type,
        )

    return response
Esempio n. 3
0
    async def dispatch(
        self, request: Request, call_next: RequestResponseEndpoint
    ) -> Response:
        logger = get_logger()
        start = time.time()

        try:
            response = await call_next(request)
            self._bind_request_context(logger, request)

            if response.status_code >= 400:
                # Error handlers in FastAPI turn raised exceptions into Response objects.
                # They are invoked before middlewares, thus we cannot catch `HTTPException` in here
                # Maybe we should try creating custom APIRouter instead of using middleware:
                # https://github.com/tiangolo/fastapi/issues/954#issuecomment-617683548

                self._override_content_type(response)

                end = time.time()
                logger.error(
                    "rest_request_processed",
                    duration=end - start,
                    success=False,
                    status_code=response.status_code,
                )

                return response

        except Exception:
            self._bind_request_context(logger, request)
            end = time.time()
            logger.error(
                "rest_request_processed",
                duration=end - start,
                success=False,
                exc_info=True,
                status_code=500,
            )
            return JSONResponse(
                status_code=500,
                content={"detail": "An unknown error occurred"},
                media_type=LoggingMiddleware.JSON_PROBLEM_CONTENT_TYPE,
            )

        end = time.time()
        logger.info(
            "rest_request_processed",
            duration=end - start,
            success=True,
            status_code=response.status_code,
        )
        return response
Esempio n. 4
0
def log_duration(key_name):
    """Logs duration of block and binds result to structlog

    Arguments:
        key_name {str} -- Key to bind the result
    """
    log = get_logger()
    start_time = time.time()

    yield

    end_time = time.time()
    log.bind(**{key_name: end_time - start_time})
Esempio n. 5
0
def check_permissions(original_payload: Any, request_url: str,
                      **kwargs: Any) -> bool:
    start = time.time()
    signed_jwt = generate_jwt(original_payload)
    try:
        response = make_jwt_request(signed_jwt, request_url)
    except Exception:
        raise UserPermissionsRequestException()

    logger = base_logger.get_logger()
    end = time.time()

    try:
        response_json = response.json()

        authorised = response.status_code == 200 and response_json.get(
            "grantAccess")
        if not authorised:
            logger.warning(
                "Authorisation failed",
                response_json=response_json,
                status_code=response.status_code,
                response_headers=response.headers,
                url=request_url,
                original_payload=original_payload,
                duration=end - start,
                **kwargs,
            )
            return False
        logger.info(
            "Called user permissions",
            response_json=response_json,
            status_code=response.status_code,
            url=request_url,
            duration=end - start,
        )
        return True
    except Exception:
        logger.warning(
            "Authorisation failed",
            status_code=response.status_code,
            response_headers=response.headers,
            url=request_url,
            original_payload=original_payload,
            exc_info=True,
            duration=end - start,
        )
        raise UserPermissionsPayloadException()
Esempio n. 6
0
    def decorated_function(*args, **kwargs):
        headers = dict(request.headers)

        connection_id_from_path = request.view_args.get("connection_id")
        partner_id_from_path = request.view_args.get("partner_id")

        logger = base_logger.get_logger()
        logger = logger.new(callback=func.__qualname__)
        start = time.time()

        try:
            result = func(*args, **kwargs)
        except APIException as exception:
            end = time.time()
            logger.error(
                "rest_request_processed",
                duration=end - start,
                success=False,
                exc_info=True,
                connection_id=connection_id_from_path,
                partner_id=partner_id_from_path,
                headers=headers,
                args=dict(request.view_args),
                status_code=exception.status,
                url=request.full_path,
            )
            raise exception

        end = time.time()
        logger.info(
            "rest_request_processed",
            duration=end - start,
            success=True,
            connection_id=connection_id_from_path,
            partner_id=partner_id_from_path,
            headers=headers,
            args=dict(request.view_args),
            status_code=result.status_code,
            url=request.full_path,
        )
        return result
Esempio n. 7
0
def test_get_logger():
    logger = get_logger()
    assert logger is not None
    logger.info("test logger")