モニタリング 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_FireBranchLeftEvent(PyMonitoringState *state, PyObject *codelike, int32_t offset, PyObject *target_offset)

BRANCH_LEFT イベントを発生させます。

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

BRANCH_RIGHT イベントを発生させます。

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 イベントを発生させます。

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 のインスタンスなら、それを使います。 それ以外の場合は、value を引数として新しい StopIteration インスタンスを作成します。

モニタリング状態の管理

モニタリング状態は、モニタリングスコープを使って管理できます。 通常、一つのスコープが一つの Python 関数に対応します。

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

モニタリング対象のスコープに入ります。 event_types は、そのスコープから発生し得るイベントの ID の配列です。 例えば PY_START イベントの ID は PY_MONITORING_EVENT_PY_START で、この値は sys.monitoring.events.PY_START の 2 を底とする対数に等しくなります。 state_array は、event_types 内の各イベントに対応するモニタリング状態の配列です。 領域は利用者が割り当て、イベントの有効化状態は PyMonitoring_EnterScope() が設定します。 event_types (したがって state_array も) のサイズは length で指定します。

version 引数は、利用者が state_array と一緒に領域を割り当て、0 に初期化しておく値へのポインタです。 その後は PyMonitoring_EnterScope() 自身だけが値を設定するようにしてください。 この値によって、前回の呼び出し以降にイベントの状態が変化したかどうかを判断し、変化していなければ速やかに戻ることができます。

ここでいうスコープは、関数、クラス、メソッドといった字句スコープです。 字句スコープに入るたびに PyMonitoring_EnterScope() を呼び出してください。 再帰的な Python 関数をエミュレートする場合などは、同じ state_array と version を再利用してスコープに再び入れます。 ジェネレータをエミュレートする場合など、コードに相当するオブジェクトの実行を一時停止するときは、スコープを一度出てから再び入る必要があります。

event_types に使うマクロは次のとおりです。

マクロ

イベント

PY_MONITORING_EVENT_BRANCH_LEFT

BRANCH_LEFT

PY_MONITORING_EVENT_BRANCH_RIGHT

BRANCH_RIGHT

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

PY_MONITORING_EVENT_BRANCH

バージョン 3.14 で非推奨: 代わりに PY_MONITORING_EVENT_BRANCH_LEFT と PY_MONITORING_EVENT_BRANCH_RIGHT を使ってください。

BRANCH_LEFT と BRANCH_RIGHT

int PyMonitoring_ExitScope(void)

PyMonitoring_EnterScope() で最後に入ったスコープを出ます。

int PY_MONITORING_IS_INSTRUMENTED_EVENT(uint8_t ev)

イベント ID ev に対応するイベントが ローカルイベント の場合に真を返します。

Added in version 3.13.

バージョン 3.14 で ソフト非推奨 <Soft deprecated>.