# 监控 C API

在 3.13 版中添加。

一个扩展可能需要与事件监视系统进行交互。 订阅事件和注册回调都可通过在 `sys.monitoring` 中暴露的 Python API 来完成。

# 生成执行事件

下面的函数使得扩展可以在模拟执行 Python 代码时触发监控事件。 这样的函数都接受一个 `PyMonitoringState` 结构体，其中包含有关事件激活状态的简明信息以及事件参数 ，此类参数包括代表代码对象的 `PyObject*`、指令偏移量，有时还包括额外的、事件专属的参数（请参阅 `sys.monitoring` 了解有关不同事件回调签名的详情）。 `codelike` 参数应为 `types.CodeType` 的实例或是某个模拟它的类型。

VM 会在触发事件时禁用跟踪，因此用户不需要额外的操作。

监控函数被调用时不应设置异常，除非是下面列出的用于处理当前异常的函数。

type PyMonitoringState

  事件类型状态的表示形式。 它由用户分配，但其内容则由下文描述的监控 API 函数来维护。

下面的所有函数均在成功时返回 0 并在失败时返回 -1 (同时设置一个异常)。

请参阅 `sys.monitoring` 获取事件的描述。

int PyMonitoring_FirePyStartEvent(PyMonitoringState *state, PyObject *codelike, int32_t offset)

  发出 `PY_START` 事件。

int PyMonitoring_FirePyResumeEvent(PyMonitoringState *state, PyObject *codelike, int32_t offset)

  发出 `PY_RESUME` 事件。

int PyMonitoring_FirePyReturnEvent(PyMonitoringState *state, PyObject *codelike, int32_t offset, PyObject *retval)

  发出 `PY_RETURN` 事件。

int PyMonitoring_FirePyYieldEvent(PyMonitoringState *state, PyObject *codelike, int32_t offset, PyObject *retval)

  发出 `PY_YIELD` 事件。

int PyMonitoring_FireCallEvent(PyMonitoringState *state, PyObject *codelike, int32_t offset, PyObject *callable, PyObject *arg0)

  发出 `CALL` 事件。

int PyMonitoring_FireLineEvent(PyMonitoringState *state, PyObject *codelike, int32_t offset, int lineno)

  发出 `LINE` 事件。

int PyMonitoring_FireJumpEvent(PyMonitoringState *state, PyObject *codelike, int32_t offset, PyObject *target_offset)

  发出 `JUMP` 事件。

int PyMonitoring_FireBranchEvent(PyMonitoringState *state, PyObject *codelike, int32_t offset, PyObject *target_offset)

  发出 `BRANCH` 事件。

int PyMonitoring_FireCReturnEvent(PyMonitoringState *state, PyObject *codelike, int32_t offset, PyObject *retval)

  发出 `C_RETURN` 事件。

int PyMonitoring_FirePyThrowEvent(PyMonitoringState *state, PyObject *codelike, int32_t offset)

  使用当前（即 `PyErr_GetRaisedException()` 返回的）异常发出 `PY_THROW` 事件。

int PyMonitoring_FireRaiseEvent(PyMonitoringState *state, PyObject *codelike, int32_t offset)

  使用当前（即 `PyErr_GetRaisedException()` 所返回的）异常发出 `RAISE` 事件。event with the current ).

int PyMonitoring_FireCRaiseEvent(PyMonitoringState *state, PyObject *codelike, int32_t offset)

  使用当前（即 `PyErr_GetRaisedException()` 所返回的）异常发出 `C_RAISE` 事件。

int PyMonitoring_FireReraiseEvent(PyMonitoringState *state, PyObject *codelike, int32_t offset)

  使用当前（即 `PyErr_GetRaisedException()` 所返回的）异常发出 `RERAISE` 事件。

int PyMonitoring_FireExceptionHandledEvent(PyMonitoringState *state, PyObject *codelike, int32_t offset)

  使用当前（即 `PyErr_GetRaisedException()` 所返回的）异常发出 `EXCEPTION_HANDLED` 事件。

int PyMonitoring_FirePyUnwindEvent(PyMonitoringState *state, PyObject *codelike, int32_t offset)

  使用当前（即 `PyErr_GetRaisedException()` 所返回的）异常发出 `PY_UNWIND` 事件。

int PyMonitoring_FireStopIterationEvent(PyMonitoringState *state, PyObject *codelike, int32_t offset, PyObject *value)

  发出 `STOP_ITERATION` 事件。 如果 `value` 是一个 `StopIteration` 实例，它将被使用。 在其他情况下，将新建一个 `StopIteration` 实例并以 `value` 作为其参数。

## 管理监控状态

监控状态可在监控作用域的协助下进行管理。 一个作用域通常对应一个 python 函数。

int PyMonitoring_EnterScope(PyMonitoringState *state_array, uint64_t *version, const uint8_t *event_types, Py_ssize_t length)

  Enter a monitored scope. `event_types` is an array of the event IDs for events that may be fired from the scope. For example, the ID of a `PY_START` event is the value `PY_MONITORING_EVENT_PY_START`, which is numerically equal to the base-2 logarithm of `sys.monitoring.events.PY_START`. `state_array` is an array with a monitoring state entry for each event in `event_types`, it is allocated by the user but populated by `PyMonitoring_EnterScope()` with information about the activation state of the event. The size of `event_types` (and hence also of `state_array`) is given in `length`.

  The `version` argument is a pointer to a value which should be allocated by the user together with `state_array` and initialized to 0, and then set only by `PyMonitoring_EnterScope()` itelf. It allows this function to determine whether event states have changed since the previous call, and to return quickly if they have not.

  The scopes referred to here are lexical scopes: a function, class or method. `PyMonitoring_EnterScope()` should be called whenever the lexical scope is entered. Scopes can be reentered, reusing the same state_array and version, in situations like when emulating a recursive Python function. When a code-like's execution is paused, such as when emulating a generator, the scope needs to be exited and re-entered.

  The macros for event_types are:

  Macro | Event
  --- | ---
  PY_MONITORING_EVENT_BRANCH | `BRANCH`
  PY_MONITORING_EVENT_CALL | `CALL`
  PY_MONITORING_EVENT_C_RAISE | `C_RAISE`
  PY_MONITORING_EVENT_C_RETURN | `C_RETURN`
  PY_MONITORING_EVENT_EXCEPTION_HANDLED | `EXCEPTION_HANDLED`
  PY_MONITORING_EVENT_INSTRUCTION | `INSTRUCTION`
  PY_MONITORING_EVENT_JUMP | `JUMP`
  PY_MONITORING_EVENT_LINE | `LINE`
  PY_MONITORING_EVENT_PY_RESUME | `PY_RESUME`
  PY_MONITORING_EVENT_PY_RETURN | `PY_RETURN`
  PY_MONITORING_EVENT_PY_START | `PY_START`
  PY_MONITORING_EVENT_PY_THROW | `PY_THROW`
  PY_MONITORING_EVENT_PY_UNWIND | `PY_UNWIND`
  PY_MONITORING_EVENT_PY_YIELD | `PY_YIELD`
  PY_MONITORING_EVENT_RAISE | `RAISE`
  PY_MONITORING_EVENT_RERAISE | `RERAISE`
  PY_MONITORING_EVENT_STOP_ITERATION | `STOP_ITERATION`

int PyMonitoring_ExitScope(void)

  Exit the last scope that was entered with `PyMonitoring_EnterScope()`.