17db96d56Sopenharmony_ci.. highlight:: shell-session 27db96d56Sopenharmony_ci 37db96d56Sopenharmony_ci.. _instrumentation: 47db96d56Sopenharmony_ci 57db96d56Sopenharmony_ci=============================================== 67db96d56Sopenharmony_ciInstrumenting CPython with DTrace and SystemTap 77db96d56Sopenharmony_ci=============================================== 87db96d56Sopenharmony_ci 97db96d56Sopenharmony_ci:author: David Malcolm 107db96d56Sopenharmony_ci:author: Łukasz Langa 117db96d56Sopenharmony_ci 127db96d56Sopenharmony_ciDTrace and SystemTap are monitoring tools, each providing a way to inspect 137db96d56Sopenharmony_ciwhat the processes on a computer system are doing. They both use 147db96d56Sopenharmony_cidomain-specific languages allowing a user to write scripts which: 157db96d56Sopenharmony_ci 167db96d56Sopenharmony_ci - filter which processes are to be observed 177db96d56Sopenharmony_ci - gather data from the processes of interest 187db96d56Sopenharmony_ci - generate reports on the data 197db96d56Sopenharmony_ci 207db96d56Sopenharmony_ciAs of Python 3.6, CPython can be built with embedded "markers", also 217db96d56Sopenharmony_ciknown as "probes", that can be observed by a DTrace or SystemTap script, 227db96d56Sopenharmony_cimaking it easier to monitor what the CPython processes on a system are 237db96d56Sopenharmony_cidoing. 247db96d56Sopenharmony_ci 257db96d56Sopenharmony_ci.. impl-detail:: 267db96d56Sopenharmony_ci 277db96d56Sopenharmony_ci DTrace markers are implementation details of the CPython interpreter. 287db96d56Sopenharmony_ci No guarantees are made about probe compatibility between versions of 297db96d56Sopenharmony_ci CPython. DTrace scripts can stop working or work incorrectly without 307db96d56Sopenharmony_ci warning when changing CPython versions. 317db96d56Sopenharmony_ci 327db96d56Sopenharmony_ci 337db96d56Sopenharmony_ciEnabling the static markers 347db96d56Sopenharmony_ci--------------------------- 357db96d56Sopenharmony_ci 367db96d56Sopenharmony_cimacOS comes with built-in support for DTrace. On Linux, in order to 377db96d56Sopenharmony_cibuild CPython with the embedded markers for SystemTap, the SystemTap 387db96d56Sopenharmony_cidevelopment tools must be installed. 397db96d56Sopenharmony_ci 407db96d56Sopenharmony_ciOn a Linux machine, this can be done via:: 417db96d56Sopenharmony_ci 427db96d56Sopenharmony_ci $ yum install systemtap-sdt-devel 437db96d56Sopenharmony_ci 447db96d56Sopenharmony_cior:: 457db96d56Sopenharmony_ci 467db96d56Sopenharmony_ci $ sudo apt-get install systemtap-sdt-dev 477db96d56Sopenharmony_ci 487db96d56Sopenharmony_ci 497db96d56Sopenharmony_ciCPython must then be :option:`configured with the --with-dtrace option 507db96d56Sopenharmony_ci<--with-dtrace>`: 517db96d56Sopenharmony_ci 527db96d56Sopenharmony_ci.. code-block:: none 537db96d56Sopenharmony_ci 547db96d56Sopenharmony_ci checking for --with-dtrace... yes 557db96d56Sopenharmony_ci 567db96d56Sopenharmony_ciOn macOS, you can list available DTrace probes by running a Python 577db96d56Sopenharmony_ciprocess in the background and listing all probes made available by the 587db96d56Sopenharmony_ciPython provider:: 597db96d56Sopenharmony_ci 607db96d56Sopenharmony_ci $ python3.6 -q & 617db96d56Sopenharmony_ci $ sudo dtrace -l -P python$! # or: dtrace -l -m python3.6 627db96d56Sopenharmony_ci 637db96d56Sopenharmony_ci ID PROVIDER MODULE FUNCTION NAME 647db96d56Sopenharmony_ci 29564 python18035 python3.6 _PyEval_EvalFrameDefault function-entry 657db96d56Sopenharmony_ci 29565 python18035 python3.6 dtrace_function_entry function-entry 667db96d56Sopenharmony_ci 29566 python18035 python3.6 _PyEval_EvalFrameDefault function-return 677db96d56Sopenharmony_ci 29567 python18035 python3.6 dtrace_function_return function-return 687db96d56Sopenharmony_ci 29568 python18035 python3.6 collect gc-done 697db96d56Sopenharmony_ci 29569 python18035 python3.6 collect gc-start 707db96d56Sopenharmony_ci 29570 python18035 python3.6 _PyEval_EvalFrameDefault line 717db96d56Sopenharmony_ci 29571 python18035 python3.6 maybe_dtrace_line line 727db96d56Sopenharmony_ci 737db96d56Sopenharmony_ciOn Linux, you can verify if the SystemTap static markers are present in 747db96d56Sopenharmony_cithe built binary by seeing if it contains a ".note.stapsdt" section. 757db96d56Sopenharmony_ci 767db96d56Sopenharmony_ci:: 777db96d56Sopenharmony_ci 787db96d56Sopenharmony_ci $ readelf -S ./python | grep .note.stapsdt 797db96d56Sopenharmony_ci [30] .note.stapsdt NOTE 0000000000000000 00308d78 807db96d56Sopenharmony_ci 817db96d56Sopenharmony_ciIf you've built Python as a shared library 827db96d56Sopenharmony_ci(with the :option:`--enable-shared` configure option), you 837db96d56Sopenharmony_cineed to look instead within the shared library. For example:: 847db96d56Sopenharmony_ci 857db96d56Sopenharmony_ci $ readelf -S libpython3.3dm.so.1.0 | grep .note.stapsdt 867db96d56Sopenharmony_ci [29] .note.stapsdt NOTE 0000000000000000 00365b68 877db96d56Sopenharmony_ci 887db96d56Sopenharmony_ciSufficiently modern readelf can print the metadata:: 897db96d56Sopenharmony_ci 907db96d56Sopenharmony_ci $ readelf -n ./python 917db96d56Sopenharmony_ci 927db96d56Sopenharmony_ci Displaying notes found at file offset 0x00000254 with length 0x00000020: 937db96d56Sopenharmony_ci Owner Data size Description 947db96d56Sopenharmony_ci GNU 0x00000010 NT_GNU_ABI_TAG (ABI version tag) 957db96d56Sopenharmony_ci OS: Linux, ABI: 2.6.32 967db96d56Sopenharmony_ci 977db96d56Sopenharmony_ci Displaying notes found at file offset 0x00000274 with length 0x00000024: 987db96d56Sopenharmony_ci Owner Data size Description 997db96d56Sopenharmony_ci GNU 0x00000014 NT_GNU_BUILD_ID (unique build ID bitstring) 1007db96d56Sopenharmony_ci Build ID: df924a2b08a7e89f6e11251d4602022977af2670 1017db96d56Sopenharmony_ci 1027db96d56Sopenharmony_ci Displaying notes found at file offset 0x002d6c30 with length 0x00000144: 1037db96d56Sopenharmony_ci Owner Data size Description 1047db96d56Sopenharmony_ci stapsdt 0x00000031 NT_STAPSDT (SystemTap probe descriptors) 1057db96d56Sopenharmony_ci Provider: python 1067db96d56Sopenharmony_ci Name: gc__start 1077db96d56Sopenharmony_ci Location: 0x00000000004371c3, Base: 0x0000000000630ce2, Semaphore: 0x00000000008d6bf6 1087db96d56Sopenharmony_ci Arguments: -4@%ebx 1097db96d56Sopenharmony_ci stapsdt 0x00000030 NT_STAPSDT (SystemTap probe descriptors) 1107db96d56Sopenharmony_ci Provider: python 1117db96d56Sopenharmony_ci Name: gc__done 1127db96d56Sopenharmony_ci Location: 0x00000000004374e1, Base: 0x0000000000630ce2, Semaphore: 0x00000000008d6bf8 1137db96d56Sopenharmony_ci Arguments: -8@%rax 1147db96d56Sopenharmony_ci stapsdt 0x00000045 NT_STAPSDT (SystemTap probe descriptors) 1157db96d56Sopenharmony_ci Provider: python 1167db96d56Sopenharmony_ci Name: function__entry 1177db96d56Sopenharmony_ci Location: 0x000000000053db6c, Base: 0x0000000000630ce2, Semaphore: 0x00000000008d6be8 1187db96d56Sopenharmony_ci Arguments: 8@%rbp 8@%r12 -4@%eax 1197db96d56Sopenharmony_ci stapsdt 0x00000046 NT_STAPSDT (SystemTap probe descriptors) 1207db96d56Sopenharmony_ci Provider: python 1217db96d56Sopenharmony_ci Name: function__return 1227db96d56Sopenharmony_ci Location: 0x000000000053dba8, Base: 0x0000000000630ce2, Semaphore: 0x00000000008d6bea 1237db96d56Sopenharmony_ci Arguments: 8@%rbp 8@%r12 -4@%eax 1247db96d56Sopenharmony_ci 1257db96d56Sopenharmony_ciThe above metadata contains information for SystemTap describing how it 1267db96d56Sopenharmony_cican patch strategically placed machine code instructions to enable the 1277db96d56Sopenharmony_citracing hooks used by a SystemTap script. 1287db96d56Sopenharmony_ci 1297db96d56Sopenharmony_ci 1307db96d56Sopenharmony_ciStatic DTrace probes 1317db96d56Sopenharmony_ci-------------------- 1327db96d56Sopenharmony_ci 1337db96d56Sopenharmony_ciThe following example DTrace script can be used to show the call/return 1347db96d56Sopenharmony_cihierarchy of a Python script, only tracing within the invocation of 1357db96d56Sopenharmony_cia function called "start". In other words, import-time function 1367db96d56Sopenharmony_ciinvocations are not going to be listed: 1377db96d56Sopenharmony_ci 1387db96d56Sopenharmony_ci.. code-block:: none 1397db96d56Sopenharmony_ci 1407db96d56Sopenharmony_ci self int indent; 1417db96d56Sopenharmony_ci 1427db96d56Sopenharmony_ci python$target:::function-entry 1437db96d56Sopenharmony_ci /copyinstr(arg1) == "start"/ 1447db96d56Sopenharmony_ci { 1457db96d56Sopenharmony_ci self->trace = 1; 1467db96d56Sopenharmony_ci } 1477db96d56Sopenharmony_ci 1487db96d56Sopenharmony_ci python$target:::function-entry 1497db96d56Sopenharmony_ci /self->trace/ 1507db96d56Sopenharmony_ci { 1517db96d56Sopenharmony_ci printf("%d\t%*s:", timestamp, 15, probename); 1527db96d56Sopenharmony_ci printf("%*s", self->indent, ""); 1537db96d56Sopenharmony_ci printf("%s:%s:%d\n", basename(copyinstr(arg0)), copyinstr(arg1), arg2); 1547db96d56Sopenharmony_ci self->indent++; 1557db96d56Sopenharmony_ci } 1567db96d56Sopenharmony_ci 1577db96d56Sopenharmony_ci python$target:::function-return 1587db96d56Sopenharmony_ci /self->trace/ 1597db96d56Sopenharmony_ci { 1607db96d56Sopenharmony_ci self->indent--; 1617db96d56Sopenharmony_ci printf("%d\t%*s:", timestamp, 15, probename); 1627db96d56Sopenharmony_ci printf("%*s", self->indent, ""); 1637db96d56Sopenharmony_ci printf("%s:%s:%d\n", basename(copyinstr(arg0)), copyinstr(arg1), arg2); 1647db96d56Sopenharmony_ci } 1657db96d56Sopenharmony_ci 1667db96d56Sopenharmony_ci python$target:::function-return 1677db96d56Sopenharmony_ci /copyinstr(arg1) == "start"/ 1687db96d56Sopenharmony_ci { 1697db96d56Sopenharmony_ci self->trace = 0; 1707db96d56Sopenharmony_ci } 1717db96d56Sopenharmony_ci 1727db96d56Sopenharmony_ciIt can be invoked like this:: 1737db96d56Sopenharmony_ci 1747db96d56Sopenharmony_ci $ sudo dtrace -q -s call_stack.d -c "python3.6 script.py" 1757db96d56Sopenharmony_ci 1767db96d56Sopenharmony_ciThe output looks like this: 1777db96d56Sopenharmony_ci 1787db96d56Sopenharmony_ci.. code-block:: none 1797db96d56Sopenharmony_ci 1807db96d56Sopenharmony_ci 156641360502280 function-entry:call_stack.py:start:23 1817db96d56Sopenharmony_ci 156641360518804 function-entry: call_stack.py:function_1:1 1827db96d56Sopenharmony_ci 156641360532797 function-entry: call_stack.py:function_3:9 1837db96d56Sopenharmony_ci 156641360546807 function-return: call_stack.py:function_3:10 1847db96d56Sopenharmony_ci 156641360563367 function-return: call_stack.py:function_1:2 1857db96d56Sopenharmony_ci 156641360578365 function-entry: call_stack.py:function_2:5 1867db96d56Sopenharmony_ci 156641360591757 function-entry: call_stack.py:function_1:1 1877db96d56Sopenharmony_ci 156641360605556 function-entry: call_stack.py:function_3:9 1887db96d56Sopenharmony_ci 156641360617482 function-return: call_stack.py:function_3:10 1897db96d56Sopenharmony_ci 156641360629814 function-return: call_stack.py:function_1:2 1907db96d56Sopenharmony_ci 156641360642285 function-return: call_stack.py:function_2:6 1917db96d56Sopenharmony_ci 156641360656770 function-entry: call_stack.py:function_3:9 1927db96d56Sopenharmony_ci 156641360669707 function-return: call_stack.py:function_3:10 1937db96d56Sopenharmony_ci 156641360687853 function-entry: call_stack.py:function_4:13 1947db96d56Sopenharmony_ci 156641360700719 function-return: call_stack.py:function_4:14 1957db96d56Sopenharmony_ci 156641360719640 function-entry: call_stack.py:function_5:18 1967db96d56Sopenharmony_ci 156641360732567 function-return: call_stack.py:function_5:21 1977db96d56Sopenharmony_ci 156641360747370 function-return:call_stack.py:start:28 1987db96d56Sopenharmony_ci 1997db96d56Sopenharmony_ci 2007db96d56Sopenharmony_ciStatic SystemTap markers 2017db96d56Sopenharmony_ci------------------------ 2027db96d56Sopenharmony_ci 2037db96d56Sopenharmony_ciThe low-level way to use the SystemTap integration is to use the static 2047db96d56Sopenharmony_cimarkers directly. This requires you to explicitly state the binary file 2057db96d56Sopenharmony_cicontaining them. 2067db96d56Sopenharmony_ci 2077db96d56Sopenharmony_ciFor example, this SystemTap script can be used to show the call/return 2087db96d56Sopenharmony_cihierarchy of a Python script: 2097db96d56Sopenharmony_ci 2107db96d56Sopenharmony_ci.. code-block:: none 2117db96d56Sopenharmony_ci 2127db96d56Sopenharmony_ci probe process("python").mark("function__entry") { 2137db96d56Sopenharmony_ci filename = user_string($arg1); 2147db96d56Sopenharmony_ci funcname = user_string($arg2); 2157db96d56Sopenharmony_ci lineno = $arg3; 2167db96d56Sopenharmony_ci 2177db96d56Sopenharmony_ci printf("%s => %s in %s:%d\\n", 2187db96d56Sopenharmony_ci thread_indent(1), funcname, filename, lineno); 2197db96d56Sopenharmony_ci } 2207db96d56Sopenharmony_ci 2217db96d56Sopenharmony_ci probe process("python").mark("function__return") { 2227db96d56Sopenharmony_ci filename = user_string($arg1); 2237db96d56Sopenharmony_ci funcname = user_string($arg2); 2247db96d56Sopenharmony_ci lineno = $arg3; 2257db96d56Sopenharmony_ci 2267db96d56Sopenharmony_ci printf("%s <= %s in %s:%d\\n", 2277db96d56Sopenharmony_ci thread_indent(-1), funcname, filename, lineno); 2287db96d56Sopenharmony_ci } 2297db96d56Sopenharmony_ci 2307db96d56Sopenharmony_ciIt can be invoked like this:: 2317db96d56Sopenharmony_ci 2327db96d56Sopenharmony_ci $ stap \ 2337db96d56Sopenharmony_ci show-call-hierarchy.stp \ 2347db96d56Sopenharmony_ci -c "./python test.py" 2357db96d56Sopenharmony_ci 2367db96d56Sopenharmony_ciThe output looks like this: 2377db96d56Sopenharmony_ci 2387db96d56Sopenharmony_ci.. code-block:: none 2397db96d56Sopenharmony_ci 2407db96d56Sopenharmony_ci 11408 python(8274): => __contains__ in Lib/_abcoll.py:362 2417db96d56Sopenharmony_ci 11414 python(8274): => __getitem__ in Lib/os.py:425 2427db96d56Sopenharmony_ci 11418 python(8274): => encode in Lib/os.py:490 2437db96d56Sopenharmony_ci 11424 python(8274): <= encode in Lib/os.py:493 2447db96d56Sopenharmony_ci 11428 python(8274): <= __getitem__ in Lib/os.py:426 2457db96d56Sopenharmony_ci 11433 python(8274): <= __contains__ in Lib/_abcoll.py:366 2467db96d56Sopenharmony_ci 2477db96d56Sopenharmony_ciwhere the columns are: 2487db96d56Sopenharmony_ci 2497db96d56Sopenharmony_ci - time in microseconds since start of script 2507db96d56Sopenharmony_ci 2517db96d56Sopenharmony_ci - name of executable 2527db96d56Sopenharmony_ci 2537db96d56Sopenharmony_ci - PID of process 2547db96d56Sopenharmony_ci 2557db96d56Sopenharmony_ciand the remainder indicates the call/return hierarchy as the script executes. 2567db96d56Sopenharmony_ci 2577db96d56Sopenharmony_ciFor a :option:`--enable-shared` build of CPython, the markers are contained within the 2587db96d56Sopenharmony_cilibpython shared library, and the probe's dotted path needs to reflect this. For 2597db96d56Sopenharmony_ciexample, this line from the above example: 2607db96d56Sopenharmony_ci 2617db96d56Sopenharmony_ci.. code-block:: none 2627db96d56Sopenharmony_ci 2637db96d56Sopenharmony_ci probe process("python").mark("function__entry") { 2647db96d56Sopenharmony_ci 2657db96d56Sopenharmony_cishould instead read: 2667db96d56Sopenharmony_ci 2677db96d56Sopenharmony_ci.. code-block:: none 2687db96d56Sopenharmony_ci 2697db96d56Sopenharmony_ci probe process("python").library("libpython3.6dm.so.1.0").mark("function__entry") { 2707db96d56Sopenharmony_ci 2717db96d56Sopenharmony_ci(assuming a :ref:`debug build <debug-build>` of CPython 3.6) 2727db96d56Sopenharmony_ci 2737db96d56Sopenharmony_ci 2747db96d56Sopenharmony_ciAvailable static markers 2757db96d56Sopenharmony_ci------------------------ 2767db96d56Sopenharmony_ci 2777db96d56Sopenharmony_ci.. object:: function__entry(str filename, str funcname, int lineno) 2787db96d56Sopenharmony_ci 2797db96d56Sopenharmony_ci This marker indicates that execution of a Python function has begun. 2807db96d56Sopenharmony_ci It is only triggered for pure-Python (bytecode) functions. 2817db96d56Sopenharmony_ci 2827db96d56Sopenharmony_ci The filename, function name, and line number are provided back to the 2837db96d56Sopenharmony_ci tracing script as positional arguments, which must be accessed using 2847db96d56Sopenharmony_ci ``$arg1``, ``$arg2``, ``$arg3``: 2857db96d56Sopenharmony_ci 2867db96d56Sopenharmony_ci * ``$arg1`` : ``(const char *)`` filename, accessible using ``user_string($arg1)`` 2877db96d56Sopenharmony_ci 2887db96d56Sopenharmony_ci * ``$arg2`` : ``(const char *)`` function name, accessible using 2897db96d56Sopenharmony_ci ``user_string($arg2)`` 2907db96d56Sopenharmony_ci 2917db96d56Sopenharmony_ci * ``$arg3`` : ``int`` line number 2927db96d56Sopenharmony_ci 2937db96d56Sopenharmony_ci.. object:: function__return(str filename, str funcname, int lineno) 2947db96d56Sopenharmony_ci 2957db96d56Sopenharmony_ci This marker is the converse of :c:func:`function__entry`, and indicates that 2967db96d56Sopenharmony_ci execution of a Python function has ended (either via ``return``, or via an 2977db96d56Sopenharmony_ci exception). It is only triggered for pure-Python (bytecode) functions. 2987db96d56Sopenharmony_ci 2997db96d56Sopenharmony_ci The arguments are the same as for :c:func:`function__entry` 3007db96d56Sopenharmony_ci 3017db96d56Sopenharmony_ci.. object:: line(str filename, str funcname, int lineno) 3027db96d56Sopenharmony_ci 3037db96d56Sopenharmony_ci This marker indicates a Python line is about to be executed. It is 3047db96d56Sopenharmony_ci the equivalent of line-by-line tracing with a Python profiler. It is 3057db96d56Sopenharmony_ci not triggered within C functions. 3067db96d56Sopenharmony_ci 3077db96d56Sopenharmony_ci The arguments are the same as for :c:func:`function__entry`. 3087db96d56Sopenharmony_ci 3097db96d56Sopenharmony_ci.. object:: gc__start(int generation) 3107db96d56Sopenharmony_ci 3117db96d56Sopenharmony_ci Fires when the Python interpreter starts a garbage collection cycle. 3127db96d56Sopenharmony_ci ``arg0`` is the generation to scan, like :func:`gc.collect()`. 3137db96d56Sopenharmony_ci 3147db96d56Sopenharmony_ci.. object:: gc__done(long collected) 3157db96d56Sopenharmony_ci 3167db96d56Sopenharmony_ci Fires when the Python interpreter finishes a garbage collection 3177db96d56Sopenharmony_ci cycle. ``arg0`` is the number of collected objects. 3187db96d56Sopenharmony_ci 3197db96d56Sopenharmony_ci.. object:: import__find__load__start(str modulename) 3207db96d56Sopenharmony_ci 3217db96d56Sopenharmony_ci Fires before :mod:`importlib` attempts to find and load the module. 3227db96d56Sopenharmony_ci ``arg0`` is the module name. 3237db96d56Sopenharmony_ci 3247db96d56Sopenharmony_ci .. versionadded:: 3.7 3257db96d56Sopenharmony_ci 3267db96d56Sopenharmony_ci.. object:: import__find__load__done(str modulename, int found) 3277db96d56Sopenharmony_ci 3287db96d56Sopenharmony_ci Fires after :mod:`importlib`'s find_and_load function is called. 3297db96d56Sopenharmony_ci ``arg0`` is the module name, ``arg1`` indicates if module was 3307db96d56Sopenharmony_ci successfully loaded. 3317db96d56Sopenharmony_ci 3327db96d56Sopenharmony_ci .. versionadded:: 3.7 3337db96d56Sopenharmony_ci 3347db96d56Sopenharmony_ci 3357db96d56Sopenharmony_ci.. object:: audit(str event, void *tuple) 3367db96d56Sopenharmony_ci 3377db96d56Sopenharmony_ci Fires when :func:`sys.audit` or :c:func:`PySys_Audit` is called. 3387db96d56Sopenharmony_ci ``arg0`` is the event name as C string, ``arg1`` is a :c:type:`PyObject` 3397db96d56Sopenharmony_ci pointer to a tuple object. 3407db96d56Sopenharmony_ci 3417db96d56Sopenharmony_ci .. versionadded:: 3.8 3427db96d56Sopenharmony_ci 3437db96d56Sopenharmony_ci 3447db96d56Sopenharmony_ciSystemTap Tapsets 3457db96d56Sopenharmony_ci----------------- 3467db96d56Sopenharmony_ci 3477db96d56Sopenharmony_ciThe higher-level way to use the SystemTap integration is to use a "tapset": 3487db96d56Sopenharmony_ciSystemTap's equivalent of a library, which hides some of the lower-level 3497db96d56Sopenharmony_cidetails of the static markers. 3507db96d56Sopenharmony_ci 3517db96d56Sopenharmony_ciHere is a tapset file, based on a non-shared build of CPython: 3527db96d56Sopenharmony_ci 3537db96d56Sopenharmony_ci.. code-block:: none 3547db96d56Sopenharmony_ci 3557db96d56Sopenharmony_ci /* 3567db96d56Sopenharmony_ci Provide a higher-level wrapping around the function__entry and 3577db96d56Sopenharmony_ci function__return markers: 3587db96d56Sopenharmony_ci \*/ 3597db96d56Sopenharmony_ci probe python.function.entry = process("python").mark("function__entry") 3607db96d56Sopenharmony_ci { 3617db96d56Sopenharmony_ci filename = user_string($arg1); 3627db96d56Sopenharmony_ci funcname = user_string($arg2); 3637db96d56Sopenharmony_ci lineno = $arg3; 3647db96d56Sopenharmony_ci frameptr = $arg4 3657db96d56Sopenharmony_ci } 3667db96d56Sopenharmony_ci probe python.function.return = process("python").mark("function__return") 3677db96d56Sopenharmony_ci { 3687db96d56Sopenharmony_ci filename = user_string($arg1); 3697db96d56Sopenharmony_ci funcname = user_string($arg2); 3707db96d56Sopenharmony_ci lineno = $arg3; 3717db96d56Sopenharmony_ci frameptr = $arg4 3727db96d56Sopenharmony_ci } 3737db96d56Sopenharmony_ci 3747db96d56Sopenharmony_ciIf this file is installed in SystemTap's tapset directory (e.g. 3757db96d56Sopenharmony_ci``/usr/share/systemtap/tapset``), then these additional probepoints become 3767db96d56Sopenharmony_ciavailable: 3777db96d56Sopenharmony_ci 3787db96d56Sopenharmony_ci.. object:: python.function.entry(str filename, str funcname, int lineno, frameptr) 3797db96d56Sopenharmony_ci 3807db96d56Sopenharmony_ci This probe point indicates that execution of a Python function has begun. 3817db96d56Sopenharmony_ci It is only triggered for pure-Python (bytecode) functions. 3827db96d56Sopenharmony_ci 3837db96d56Sopenharmony_ci.. object:: python.function.return(str filename, str funcname, int lineno, frameptr) 3847db96d56Sopenharmony_ci 3857db96d56Sopenharmony_ci This probe point is the converse of ``python.function.return``, and 3867db96d56Sopenharmony_ci indicates that execution of a Python function has ended (either via 3877db96d56Sopenharmony_ci ``return``, or via an exception). It is only triggered for pure-Python 3887db96d56Sopenharmony_ci (bytecode) functions. 3897db96d56Sopenharmony_ci 3907db96d56Sopenharmony_ci 3917db96d56Sopenharmony_ciExamples 3927db96d56Sopenharmony_ci-------- 3937db96d56Sopenharmony_ciThis SystemTap script uses the tapset above to more cleanly implement the 3947db96d56Sopenharmony_ciexample given above of tracing the Python function-call hierarchy, without 3957db96d56Sopenharmony_cineeding to directly name the static markers: 3967db96d56Sopenharmony_ci 3977db96d56Sopenharmony_ci.. code-block:: none 3987db96d56Sopenharmony_ci 3997db96d56Sopenharmony_ci probe python.function.entry 4007db96d56Sopenharmony_ci { 4017db96d56Sopenharmony_ci printf("%s => %s in %s:%d\n", 4027db96d56Sopenharmony_ci thread_indent(1), funcname, filename, lineno); 4037db96d56Sopenharmony_ci } 4047db96d56Sopenharmony_ci 4057db96d56Sopenharmony_ci probe python.function.return 4067db96d56Sopenharmony_ci { 4077db96d56Sopenharmony_ci printf("%s <= %s in %s:%d\n", 4087db96d56Sopenharmony_ci thread_indent(-1), funcname, filename, lineno); 4097db96d56Sopenharmony_ci } 4107db96d56Sopenharmony_ci 4117db96d56Sopenharmony_ci 4127db96d56Sopenharmony_ciThe following script uses the tapset above to provide a top-like view of all 4137db96d56Sopenharmony_cirunning CPython code, showing the top 20 most frequently entered bytecode 4147db96d56Sopenharmony_ciframes, each second, across the whole system: 4157db96d56Sopenharmony_ci 4167db96d56Sopenharmony_ci.. code-block:: none 4177db96d56Sopenharmony_ci 4187db96d56Sopenharmony_ci global fn_calls; 4197db96d56Sopenharmony_ci 4207db96d56Sopenharmony_ci probe python.function.entry 4217db96d56Sopenharmony_ci { 4227db96d56Sopenharmony_ci fn_calls[pid(), filename, funcname, lineno] += 1; 4237db96d56Sopenharmony_ci } 4247db96d56Sopenharmony_ci 4257db96d56Sopenharmony_ci probe timer.ms(1000) { 4267db96d56Sopenharmony_ci printf("\033[2J\033[1;1H") /* clear screen \*/ 4277db96d56Sopenharmony_ci printf("%6s %80s %6s %30s %6s\n", 4287db96d56Sopenharmony_ci "PID", "FILENAME", "LINE", "FUNCTION", "CALLS") 4297db96d56Sopenharmony_ci foreach ([pid, filename, funcname, lineno] in fn_calls- limit 20) { 4307db96d56Sopenharmony_ci printf("%6d %80s %6d %30s %6d\n", 4317db96d56Sopenharmony_ci pid, filename, lineno, funcname, 4327db96d56Sopenharmony_ci fn_calls[pid, filename, funcname, lineno]); 4337db96d56Sopenharmony_ci } 4347db96d56Sopenharmony_ci delete fn_calls; 4357db96d56Sopenharmony_ci } 4367db96d56Sopenharmony_ci 437