插件错误处理
前言
错误处理对于建立一个成功的插件至关重要。此文档旨在使开发人员能够编写更好的代码,以更有效地处理错误并以面向服务的方式处理错误,最终使用户减少需要联系技术支持的次数。
错误信息
代码
首先,我们先看一些有效处理错误的代码,同时也展示一些有用而且方便人阅读的信息。
action.py
import json
...
def run(self, params={}):
business_object_id = params["business_object_id"]
public_id = params["public_id"]
url = self.base_url() + "/api/V1/getbusinessobject/busobid/{busobid}/publicid/{publicid}".format(
busobid=business_object_id,
publicid=public_id
)
response = self.session().get(url)
if response.status_code not in range(200, 299):
raise Exception(
cause="Received HTTP %d status code from Cherwell. Please verify your Cherwell server status and try again.",
assistance="If the issue persists please contact support.",
data=f"{response.status_code}, {response.text}"
)
try:
response_data = response.json()
except json.decoder.JSONDecodeError:
raise Exception(
cause="Received an unexpected response from Cherwell ",
assistance="(non-JSON or no response was received).",
data=response.text
)
return { "success": True, "raw_response": response_data }
现在让我们分析一下这个例子。
第1部分 - 状态代码检查
if response.status_code not in range(200, 299):
raise Exception(
cause="Received HTTP %d status code from Cherwell. Please verify your Cherwell server status and try again.",
assistance="If the issue persists please contact support.",
data=f"{response.status_code} {response.text}"
)
本节是错误处理的第一关。具体而言,它将处理HTTP响应的状态代码。
在涉及状态码时,应该注意的是,当某些情况出现时,并非所有API都使用正确的HTTP状态代码。因此,您在遵循使用通用状态码之前应查阅并利用相关API文档。
请注意,此代码使用if
语句来验证状态代码的范围是否在200-299之间。200表示“OK”。如果状态代码不在该范围内,那么我们将通过抛出PluginException
并向用户解释问题然后停止集成的执行。
第2部分 - 有效负载验证
import json
try:
response_data = response.json()
except json.decoder.JSONDecodeError:
raise Exception(
data=response.text
)
本部分尝试从响应中获取JSON内容。如果负载不是JSON,或者它根本不存在,则此调用将失败并抛出JSONDecodeError。此异常如果未经处理的话对查看日志的用户没什么用,因为它不包含有关响应的任何类型的信息。
我们可以做的是告知用户所收到的响应的格式是不合法的,然后显示出响应的文本。这将给出来自服务器的响应,可能可以向用户提供问题的更多信息以及纠正的方法。
在某些情况下可以让用户查看可能有助于解决其问题的产品文档。在下面,用户被告知去查阅一份相关的文档,然后为插件的某个行为提供一个json对象。
raise Exception(
cause="Okta: Create user failed unexpectedly.",
assistance="Make sure any provided objects, such as profile or credentials, match the Okta schemas. "
"For more details, see https://developer.okta.com/docs/api/resources/users#request-parameters")
是否抛出例外
处理错误时,作为开发人员的您可以采取两种常规动作。
第一种是记录错误但继续执行。这可以通过集成SDK
方法向用户提供错误消息来完成,这在不需要停止执行插件代码时使用。
class STR_UPCASEACTIONS(Actions):
def __init__(self):
# 初始化
self.name = "str_upcase"
self.inputModel = STR_UPCASEINPUT
self.outputModel = STR_UPCASEOUTPUT
self.connModel = CONNECTION
# 打印 log 到stdout
self.log = Core().print_to_stdout
# 或则打印 log 到stderr
# self.log = Core().print_to_stderr
第二个方法是抛出Exception,它将暂停插件的代码执行。这是通过raise Exception(cause="reason", assistance="helpful message")
抛出的,然后向用户提供错误原因和辅助消息(如上节中详述),以便进行修复。当您的代码中出现致命错误或错误情况时,通常会使用此方法 - 例如收到HTTP 500错误,响应无效,身份验证无效等。
应该处理哪些潜在的错误?
此列表并不包括所有的潜在错误。考虑到这一点,请遵循此常规列表并根据您的集成进行调整。
1. 确保用户输入正确。看一下我们当前的插件列表,这对于自由形式的JSON blob更为重要。请对是否需要验证输入做出判断。
2. 检查响应里的HTTP状态码。根据API文档并对它们列出的所有情况进行处理并根据文档自定义错误消息。如果没有相关文档,请检查最常见的文档。注意:某些API在发生错误时在其响应中提供错误消息。如果是这种情况,请将该错误消息提供给用户。
3. 检查响应的负载类型。例如,如果您期望获得JSON响应,但是您得到明文响应甚至是XML,那么您的插件代码是否会中断?如果是的话 - 请处理这个情况。Try / except子句非常适合这种情况。如果可能的话,请将完整的响应文本提供给用户。
4. 检查所需数据是否存在。我们所有需要的数据都存在于响应中吗?如果没有,我们是否可以继续执行,或者这是一个致命的错误,我们是否需要抛出PluginException?请做出判断并查阅相关文档。
惯例
尽可能标准化这些。
示例
JSONDecode
import json
try:
response_data = response.json()
except json.decoder.JSONDecodeError as e:
raise Exception(f"{self.__class__} - {str(e)}")