|
| 1 | +.. highlight:: c |
| 2 | + |
| 3 | +.. _monitoring: |
| 4 | + |
| 5 | +Monitorong C API |
| 6 | +================ |
| 7 | + |
| 8 | +Added in version 3.13. |
| 9 | + |
| 10 | +An extension may need to interact with the event monitoring system. Subscribing |
| 11 | +to events and registering callbacks can be done via the Python API exposed in |
| 12 | +:mod:`sys.monitoring`. |
| 13 | + |
| 14 | +Generating Execution Events |
| 15 | +=========================== |
| 16 | + |
| 17 | +The functions below make it possible for an extension to fire monitoring |
| 18 | +events as it emulates the execution of Python code. Each of these functions |
| 19 | +accepts a ``PyMonitoringState`` struct which contains concise information |
| 20 | +about the activation state of events, as well as the event arguments, which |
| 21 | +include a ``PyObject*`` representing the code object, the instruction offset |
| 22 | +and sometimes additional, event-specific arguments (see :mod:`sys.monitoring` |
| 23 | +for details about the signatures of the different event callbacks). |
| 24 | +The ``codelike`` argument should be an instance of :class:`types.CodeType` |
| 25 | +or of a type that emulates it. |
| 26 | + |
| 27 | +The VM disables tracing when firing an event, so there is no need for user |
| 28 | +code to do that. |
| 29 | + |
| 30 | +Monitoring functions should not be called with an exception set, |
| 31 | +except those listed below as working with the current exception. |
| 32 | + |
| 33 | +.. c:type:: PyMonitoringState |
| 34 | +
|
| 35 | + Representation of the state of an event type. It is allocated by the user |
| 36 | + while its contents are maintained by the monitoring API functions described below. |
| 37 | + |
| 38 | + |
| 39 | +All of the functions below return 0 on success and -1 (with an exception set) on error. |
| 40 | + |
| 41 | +See :mod:`sys.monitoring` for descriptions of the events. |
| 42 | + |
| 43 | +.. c:function:: int PyMonitoring_FirePyStartEvent(PyMonitoringState *state, PyObject *codelike, int32_t offset) |
| 44 | +
|
| 45 | + Fire a ``PY_START`` event. |
| 46 | +
|
| 47 | +
|
| 48 | +.. c:function:: int PyMonitoring_FirePyResumeEvent(PyMonitoringState *state, PyObject *codelike, int32_t offset) |
| 49 | +
|
| 50 | + Fire a ``PY_RESUME`` event. |
| 51 | +
|
| 52 | +
|
| 53 | +.. c:function:: int PyMonitoring_FirePyReturnEvent(PyMonitoringState *state, PyObject *codelike, int32_t offset, PyObject* retval) |
| 54 | +
|
| 55 | + Fire a ``PY_RETURN`` event. |
| 56 | +
|
| 57 | +
|
| 58 | +.. c:function:: int PyMonitoring_FirePyYieldEvent(PyMonitoringState *state, PyObject *codelike, int32_t offset, PyObject* retval) |
| 59 | +
|
| 60 | + Fire a ``PY_YIELD`` event. |
| 61 | +
|
| 62 | +
|
| 63 | +.. c:function:: int PyMonitoring_FireCallEvent(PyMonitoringState *state, PyObject *codelike, int32_t offset, PyObject* callable, PyObject *arg0) |
| 64 | +
|
| 65 | + Fire a ``CALL`` event. |
| 66 | +
|
| 67 | +
|
| 68 | +.. c:function:: int PyMonitoring_FireLineEvent(PyMonitoringState *state, PyObject *codelike, int32_t offset, int lineno) |
| 69 | +
|
| 70 | + Fire a ``LINE`` event. |
| 71 | +
|
| 72 | +
|
| 73 | +.. c:function:: int PyMonitoring_FireJumpEvent(PyMonitoringState *state, PyObject *codelike, int32_t offset, PyObject *target_offset) |
| 74 | +
|
| 75 | + Fire a ``JUMP`` event. |
| 76 | +
|
| 77 | +
|
| 78 | +.. c:function:: int PyMonitoring_FireBranchEvent(PyMonitoringState *state, PyObject *codelike, int32_t offset, PyObject *target_offset) |
| 79 | +
|
| 80 | + Fire a ``BRANCH`` event. |
| 81 | +
|
| 82 | +
|
| 83 | +.. c:function:: int PyMonitoring_FireCReturnEvent(PyMonitoringState *state, PyObject *codelike, int32_t offset, PyObject *retval) |
| 84 | +
|
| 85 | + Fire a ``C_RETURN`` event. |
| 86 | +
|
| 87 | +
|
| 88 | +.. c:function:: int PyMonitoring_FirePyThrowEvent(PyMonitoringState *state, PyObject *codelike, int32_t offset) |
| 89 | +
|
| 90 | + Fire a ``PY_THROW`` event with the current exception (as returned by |
| 91 | + :c:func:`PyErr_GetRaisedException`). |
| 92 | +
|
| 93 | +
|
| 94 | +.. c:function:: int PyMonitoring_FireRaiseEvent(PyMonitoringState *state, PyObject *codelike, int32_t offset) |
| 95 | +
|
| 96 | + Fire a ``RAISE`` event with the current exception (as returned by |
| 97 | + :c:func:`PyErr_GetRaisedException`). |
| 98 | +
|
| 99 | +
|
| 100 | +.. c:function:: int PyMonitoring_FireCRaiseEvent(PyMonitoringState *state, PyObject *codelike, int32_t offset) |
| 101 | +
|
| 102 | + Fire a ``C_RAISE`` event with the current exception (as returned by |
| 103 | + :c:func:`PyErr_GetRaisedException`). |
| 104 | +
|
| 105 | +
|
| 106 | +.. c:function:: int PyMonitoring_FireReraiseEvent(PyMonitoringState *state, PyObject *codelike, int32_t offset) |
| 107 | +
|
| 108 | + Fire a ``RERAISE`` event with the current exception (as returned by |
| 109 | + :c:func:`PyErr_GetRaisedException`). |
| 110 | +
|
| 111 | +
|
| 112 | +.. c:function:: int PyMonitoring_FireExceptionHandledEvent(PyMonitoringState *state, PyObject *codelike, int32_t offset) |
| 113 | +
|
| 114 | + Fire an ``EXCEPTION_HANDLED`` event with the current exception (as returned by |
| 115 | + :c:func:`PyErr_GetRaisedException`). |
| 116 | +
|
| 117 | +
|
| 118 | +.. c:function:: int PyMonitoring_FirePyUnwindEvent(PyMonitoringState *state, PyObject *codelike, int32_t offset) |
| 119 | +
|
| 120 | + Fire a ``PY_UNWIND`` event with the current exception (as returned by |
| 121 | + :c:func:`PyErr_GetRaisedException`). |
| 122 | +
|
| 123 | +
|
| 124 | +.. c:function:: int PyMonitoring_FireStopIterationEvent(PyMonitoringState *state, PyObject *codelike, int32_t offset) |
| 125 | +
|
| 126 | + Fire a ``STOP_ITERATION`` event with the current exception (as returned by |
| 127 | + :c:func:`PyErr_GetRaisedException`). |
| 128 | +
|
| 129 | +
|
| 130 | +Managing the Monitoring State |
| 131 | +----------------------------- |
| 132 | +
|
| 133 | +Monitoring states can be managed with the help of monitoring scopes. A scope |
| 134 | +would typically correspond to a python function. |
| 135 | +
|
| 136 | +.. :c:function:: int PyMonitoring_EnterScope(PyMonitoringState *state_array, uint64_t *version, const uint8_t *event_types, Py_ssize_t length) |
| 137 | +
|
| 138 | + Enter a monitored scope. ``event_types`` is an array of the event IDs for |
| 139 | + events that may be fired from the scope. For example, the ID of a ``PY_START`` |
| 140 | + event is the value ``PY_MONITORING_EVENT_PY_START``, which is numerically equal |
| 141 | + to the base-2 logarithm of ``sys.monitoring.events.PY_START``. |
| 142 | + ``state_array`` is an array with a monitoring state entry for each event in |
| 143 | + ``event_types``, it is allocated by the user but populated by |
| 144 | + ``PyMonitoring_EnterScope`` with information about the activation state of |
| 145 | + the event. The size of ``event_types`` (and hence also of ``state_array``) |
| 146 | + is given in ``length``. |
| 147 | +
|
| 148 | + The ``version`` argument is a pointer to a value which should be allocated |
| 149 | + by the user together with ``state_array`` and initialized to 0, |
| 150 | + and then set only by ``PyMonitoring_EnterScope`` itelf. It allows this |
| 151 | + function to determine whether event states have changed since the previous call, |
| 152 | + and to return quickly if they have not. |
| 153 | +
|
| 154 | + The scopes referred to here are lexical scopes: a function, class or method. |
| 155 | + ``PyMonitoring_EnterScope`` should be called whenever the lexical scope is |
| 156 | + entered. Scopes can be reentered, reusing the same *state_array* and *version*, |
| 157 | + in situations like when emulating a recursive Python function. When a code-like's |
| 158 | + execution is paused, such as when emulating a generator, the scope needs to |
| 159 | + be exited and re-entered. |
| 160 | +
|
| 161 | +
|
| 162 | +.. :c:function:: int PyMonitoring_ExitScope(void) |
| 163 | +
|
| 164 | + Exit the last scope that was entered with ``PyMonitoring_EnterScope``. |
0 commit comments