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
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
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})
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()
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
def test_get_logger(): logger = get_logger() assert logger is not None logger.info("test logger")