loading...

插件错误处理

前言

错误处理对于建立一个成功的插件至关重要。此文档旨在使开发人员能够编写更好的代码,以更有效地处理错误并以面向服务的方式处理错误,最终使用户减少需要联系技术支持的次数。

错误信息

代码

首先,我们先看一些有效处理错误的代码,同时也展示一些有用而且方便人阅读的信息。

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)}")
image-missing