异常排查 ======== 在使用DeepFOS时,可能会遇到一些异常信息。 本章节将介绍DeepFOS的常见异常类型,异常的排查方法等等,以便于您快速定位异常来源。 .. |debug文件| replace:: :doc:`debug文件` -------- 异常类型 -------- 本文将使用DeepFOS包的常见异常类型分为以下几类: #. 网络异常_ #. 外部API调用异常_ #. Python内建异常及DeepFOS的Bug引发的异常_ #. DeepFOS主动抛出异常_ 接下来将针对这些异常类型,列举典型的报错信息,以及可能导致该异常的原因。 -------- 网络异常 -------- 这类异常通常在本地调试时出现,并且报错有明显特征,一般会出现 ``Connection, Timeout`` 等字样。 造成这类报错的原因可能有: 1. 使用了VPN ------------ 您使用的环境的域名可能不能被国外的DNS服务器解析,因此如果您使用了VPN,可能导致无法访问某些环境。 典型报错 ^^^^^^^^ 出现 ``check_host_name`` 字样。 解决方案 ^^^^^^^^ 关闭VPN。 .. _forget_debug : 2. 没有在代码入口最上方import debug文件 --------------------------------------- 为了能够在本地调试, |debug文件| 中进行了各种环境的预配置,如果没有导入debug文件, 或者在导入debug文件前已经导入了deepfos的模块,很可能导致预配置无法生效。 典型报错 ^^^^^^^^ .. code-block:: py3tb :emphasize-lines: 14 Traceback (most recent call last): File "C:\Work\deepfos\_local_test\test1.py", line 10, in dim = Dimension('tttt') File "C:\Work\deepfos\deepfos\element\dimension.py", line 81, in __init__ super().__init__(element_name, folder_id, path) File "C:\Work\deepfos\deepfos\element\base.py", line 47, in __init__ ele_detail = self.init_element() File "C:\Work\deepfos\deepfos\element\base.py", line 53, in init_element ele_info = self.get_element_info() File "C:\Work\deepfos\deepfos\element\base.py", line 78, in get_element_info ele_list = api.elements.get_element_info_by_name(ele_name, ele_type) File "C:\Work\deepfos\deepfos\api\base.py", line 337, in sync_call raise exc from None deepfos.exceptions.APIRequestError: HTTPConnectionPool(host='app-server', port=80): Max retries exceeded with url: /elements/get-element-info-by-name/base-info?elementName=tttt&elementType=DIM (Caused by NewConnectionError(': Failed to establish a new connection: [Errno 11001] getaddrinfo failed')) 报错内容的最后一行 ``HTTPConnectionPool(host='app-server', port=80)`` 提示您访问了域名为 ``app-server`` 的地址, 这代表 |debug文件| 配置的 ``host`` 没有生效。 解决方案 ^^^^^^^^ 请参考“ :ref:`如何让本地代码和线上代码一致` ”,修改主入口文件。 3. 没有有效的网络连接 --------------------- DeepFOS包要求在有有效网络连接的环境运行,必须确保您的电脑能够正确访问先胜云系统。 典型报错 ^^^^^^^^ .. code-block:: py3tb :emphasize-lines: 14 Traceback (most recent call last): File "C:\Work\deepfos\_local_test\test1.py", line 11, in dim = Dimension('tttt') File "C:\Work\deepfos\deepfos\element\dimension.py", line 81, in __init__ super().__init__(element_name, folder_id, path) File "C:\Work\deepfos\deepfos\element\base.py", line 47, in __init__ ele_detail = self.init_element() File "C:\Work\deepfos\deepfos\element\base.py", line 53, in init_element ele_info = self.get_element_info() File "C:\Work\deepfos\deepfos\element\base.py", line 78, in get_element_info ele_list = api.elements.get_element_info_by_name(ele_name, ele_type) File "C:\Work\deepfos\deepfos\api\base.py", line 337, in sync_call raise exc from None deepfos.exceptions.APIRequestError: HTTPSConnectionPool(host='alpha.deepfos.com', port=443): Max retries exceeded with url: /seepln-server/app-server/elements/get-element-info-by-name/base-info?elementName=tttt&elementType=DIM (Caused by NewConnectionError(': Failed to establish a new connection: [Errno 11001] getaddrinfo failed')) 报错内容和 :ref:`上一节` 的报错十分相似,但是host的内容不再是形如 ``app-server`` 的无效域名,说明您的配置生效, 但是您的电脑不能访问先胜云系统。 解决方案 ^^^^^^^^ 切换到有有效网络连接的环境 --------------- 外部API调用异常 --------------- DeeFOS SDK封装了几乎所有组件的常用restful API,由于网络请求的不确定性,调用则这些API可能会出现异常 .. hint:: 本小节的 **“外部API”** 指的是先胜云系统的组件API,外部是相对于DeepFOS SDK而言的。 DeepFOS SDK把这类异常分为两大类 - 请求异常: ``APIRequestError`` - 响应异常: ``APIResponseError`` 1. 请求异常 ----------- 请求异常发生在发送HTTP请求过程中,通常连接超时,服务无效等会导致这类错误。 出现这类错误说明请求没有到达服务端,可能需要检查网络连接和组件服务的有效性。 典型报错 ^^^^^^^^ .. code-block:: py3tb :emphasize-lines: 14 Traceback (most recent call last): File "C:\Work\deepfos\_local_test\test1.py", line 11, in dim = Dimension('tttt') File "C:\Work\deepfos\deepfos\element\dimension.py", line 81, in __init__ super().__init__(element_name, folder_id, path) File "C:\Work\deepfos\deepfos\element\base.py", line 47, in __init__ ele_detail = self.init_element() File "C:\Work\deepfos\deepfos\element\base.py", line 53, in init_element ele_info = self.get_element_info() File "C:\Work\deepfos\deepfos\element\base.py", line 78, in get_element_info ele_list = api.elements.get_element_info_by_name(ele_name, ele_type) File "C:\Work\deepfos\deepfos\api\base.py", line 337, in sync_call raise exc from None deepfos.exceptions.APIRequestError: HTTPSConnectionPool(host='alpha.deepfos.com', port=443): Max retries exceeded with url: /seepln-server/app-server/elements/get-element-info-by-name/base-info?elementName=tttt&elementType=DIM (Caused by NewConnectionError(': Failed to establish a new connection: [Errno 11001] getaddrinfo failed')) 解决方案 ^^^^^^^^ #. 检查网络连接是否有效 #. 检查请求的接口是否可以正常访问 2. 响应异常 ----------- 响应异常发生在解析服务端的HTTP响应过程中。下述任何情况都可能导致响应异常: 1. HTTP状态码非2xx 2. 返回内容无法解析为JSON 3. 返回的JSON缺少必须字段: `status, data` 4. status字段值为 ``False`` 5. 返回的JSON无法依据Model定义反序列化 典型报错 - 1 ^^^^^^^^^^^^ .. code-block:: py3tb :emphasize-lines: 1,2,12 2021-08-17 18:27:04.230 | WARNING | deepfos.api.base:parse_reponse:422 - Call api: https://alpha.deepfos.com/seepln-server/dimension-server1-0/dimension/query/select-dimension-member-by-name-function failed. Bad response because status is False. Detail: {"status":false,"data":null,"code":999999,"message":"维度表达式不正确"} 2021-08-17 18:27:04.230 | WARNING | deepfos.api.base:check_response:511 - curl -X POST -H 'Accept: */*' -H 'Accept-Encoding: gzip, deflate' -H 'Connection: keep-alive' -H 'Content-Length: 333' -H 'Content-Type: application/json;charset=UTF8' -H 'User-Agent: python-requests/2.25.1' -H 'app: ehcdge005' -H 'cookie: deepfos_users=%7B%22color%22%3A%221%22%2C%22email%22%3A%22wei.wei%40proinnova.com.cn%22%2C%22nickName%22%3A%22Androiddown%22%2C%22token%22%3A%22FA8A64B5623403471566D1BAC673E19309D91D76056A2A889204BA1762B238B0%22%2C%22type%22%3A1%2C%22userId%22%3A%22c3c3e8fc-a6e2-443e-9091-75c19217c92c%22%2C%22username%22%3A%22jP5C29m6PW%22%7D; deepfos_token=FA8A64B5623403471566D1BAC673E19309D91D76056A2A889204BA1762B238B0' -H 'language: zh-cn' -H 'space: ehcdge' -H 'token: FA8A64B5623403471566D1BAC673E19309D91D76056A2A889204BA1762B238B0' -H 'user: c3c3e8fc-a6e2-443e-9091-75c19217c92c' -d '{"check_express": null, "dimensionMemberNames": "Account{Base1(#root, 0)}", "duplicate": true, "folderId": "DIR956996be86cb", "ignoreIllegalMember": true, "outFormat": null, "path": null, "resultString": "", "reverse_order": "0", "role": null, "roleFolderId": null, "rolegroup": null, "rsMapping": null, "rsName": null, "web": false}' https://alpha.deepfos.com/seepln-server/dimension-server1-0/dimension/query/select-dimension-member-by-name-function Traceback (most recent call last): File "C:\Work\deepfos\_local_test\test_dim.py", line 8, in dim.query("Base1(#root, 0)") File "C:\Work\deepfos\deepfos\element\dimension.py", line 387, in query return self.api.query.select_dimension_member_by_name_function(payload) File "C:\Work\deepfos\deepfos\api\base.py", line 340, in sync_call return handle_reponse(flag, obj, err, exception, model) File "C:\Work\deepfos\deepfos\api\base.py", line 308, in handle_reponse raise exc deepfos.exceptions.APIResponseError: 维度表达式不正确 出现这类报错时,在报错的最后一行一般会有接口返回的错误提示, 如果设置了: ``OPTION.api.dump_on_failure = True`` 在错误栈 ``Traceback (most recent call last):`` 的前一行,会打印一条包含本次请求信息的curl命令行。如果您判断是外部API的Bug,可以将curl命令行的内容复制并且发送给对应的开发人员。 在curl的前一行,会有包含本次请求完整返回和错误直接原因的简单说明。 解决方案 - 1 ^^^^^^^^^^^^ 由于导致异常的原因多种多样,需要使用者结合报错的内容进行判断。 但是总体应该符合以下原则: 1. 如果出现第5类情况: 返回的JSON无法依据Model定义反序列化,联系DeepFOS SDK开发者。 2. 其余4类情况: #. 首先根据报错内容自我检查请求参数是否符合要求, #. 使用postman导入curl请求查看请求参数是否符合预期(可选,需要有一定开发经验) #. 不符合,联系DeepFOS SDK开发者 #. 符合,进入下一步 #. 联系接口开发者,提供curl命令行,协助排查Bug。 典型报错 - 2 ^^^^^^^^^^^^ .. code-block:: py3tb :emphasize-lines: 16 Traceback (most recent call last): File "C:\Work\deepfos\_local_test\test1.py", line 11, in dim = Dimension('tttt1') File "C:\Work\deepfos\deepfos\element\dimension.py", line 81, in __init__ super().__init__(element_name, folder_id, path) File "C:\Work\deepfos\deepfos\element\base.py", line 47, in __init__ ele_detail = self.init_element() File "C:\Work\deepfos\deepfos\element\base.py", line 53, in init_element ele_info = self.get_element_info() File "C:\Work\deepfos\deepfos\element\base.py", line 78, in get_element_info ele_list = api.elements.get_element_info_by_name(ele_name, ele_type) File "C:\Work\deepfos\deepfos\api\base.py", line 340, in sync_call return handle_reponse(flag, obj, err, exception, model) File "C:\Work\deepfos\deepfos\api\base.py", line 308, in handle_reponse raise exc deepfos.exceptions.APIResponseError: [code: 401] ErrMsg from server: {"status":false,"data":null,"code":401,"message":"UNAUTHORIZED"}] 出现 ``code 401`` 或者 ``UNAUTHORIZED``,通常由于cookie/token失效。 解决方案 - 2 ^^^^^^^^^^^^ 更新 |debug文件| 中的para1参数。关于如何获取para1参数,请参考 :ref:`这一节` 内容。 -------------------------------------- Python内建异常及DeepFOS的Bug引发的异常 -------------------------------------- Python是一门强类型的动态类型语言,这种特性导致它比其他语言更容易抛出异常,例如 ``str`` 类型与 ``int`` 类型相加将导致 ``TypeError`` 等等,诸如此类的Python内建异常,需要多使用Python,积累开发经验,以便出现问题能够迅速定位。 值得一说的是,如果这种内建异常出现在DeepFOS的代码中,那么这可能是DeepFOS的一个Bug,欢迎您通过Issue向我们反馈。具体的流程可以参考 :ref:`这一小节` 内容。 ------------------- DeepFOS主动抛出异常 ------------------- 在代码运行过程中,由于用户输入或者接口调用等获取的数据不符合预期,导致原有逻辑已经没有继续执行的必要,这时候通常主动抛出异常。 DeepFOS在抛出异常时会附带尽可能详尽的说明,以便您能够定位导致该异常的原因。 典型报错 -------- .. code-block:: py3tb :emphasize-lines: 12 Traceback (most recent call last): File "C:\Work\deepfos\_local_test\test_sml.py", line 6, in sml = SmartList('project_approve_status2') File "C:\Work\deepfos\deepfos\element\smartlist.py", line 30, in __init__ super().__init__(element_name, folder_id, path) File "C:\Work\deepfos\deepfos\element\base.py", line 47, in __init__ ele_detail = self.init_element() File "C:\Work\deepfos\deepfos\element\base.py", line 53, in init_element ele_info = self.get_element_info() File "C:\Work\deepfos\deepfos\element\base.py", line 86, in get_element_info raise ElementNotFoundError( deepfos.exceptions.ElementNotFoundError: element name: project_approve_status2, element type: SML. 解决方案 -------- 结合异常的名称和异常的详细内容,一般能够定位问题的原因。如果出现一些让你感到费解的错误或者某些报错缺乏友好提示,您也可以通过提Issue的方式反馈给我们。