Tracing/USDT: различия между версиями

Материал из ALT Linux Wiki
Строка 50: Строка 50:
   puts
   puts


* Пример использование через ''perf_event'':
Использование через ''perf_event'':
* В пакете <code>perf</code> одноименная утилита, пример:
   # perf buildid-cache --add /usr/lib64/libtcl8.6.so
   # perf buildid-cache --add /usr/lib64/libtcl8.6.so
   # perf list | grep sdt_ | grep proc__entry
   # perf list | grep sdt_ | grep proc__entry

Версия от 13:28, 14 октября 2022

Userland Statically Defined Tracing

Некоторый софт позволяет добавлять статические точки трассировки (трейспоинты) для удобства его отладки в сложных местах где трудно сделать другие виды трассировки, улучшая т.н. observability системы.

Например, такая поддержка есть у некоторых языков (java, perl, php, python, ruby, tcl, nodejs, dotnet), приложений (mariadb, postgresql, couchdb, systemd-udev, sssd, ceph), библиотек (grpc, glibc, glib, zlib). У нас эти пакеты пока собраны без такой поддержки и требуют её включения.

Исторически эти трейспоинты восходят к Solaris Dtrace, а в Линукс впервые попали через SystemTap. Нужно отметить, что данная реализация USDT использует только хедер sys/sdt.h предоставляемый SystemTap, но не использует прочий SystemTap функционал или инфраструктуру.

Сборка пакета с поддержкой usdt

Маинтайнеру зачастую достаточно сделать два изменения spec'а: 1) добавить

 BuildRequires: systemtap-sdt-devel

который приносит необходимый Си хедер, и 2) добавить соответствующую опцию configure, например (её название может отличаться):

 %configure --enable-dtrace

Другие варианты: --with-dtrace, --enable-systemtap, --with-systemtap.

В результате — в коде в точке трассировке добавляется один nop не влияющий на производительность при отключенной трассировке, а в ELF бинарник в секцию .note.stapsdt записывается описание каждого трейспоинта и его аргументов. Проверить их наличие можно командой eu-readelf --notes=.note.stapsdt путь-к-бинарнику. Пример для трейспоинта с именем example:test (имеющим один аргумент) и находящимся в бинарнике ./example:

 $ eu-readelf --notes=.note.stapsdt ./example
 
 Note section [30] '.note.stapsdt' of 68 bytes at offset 0x3174:
   Owner          Data size  Type
   stapsdt               45  Version: 3
     PC: 0x1153, Base: 0x2004, Semaphore: 0
     Provider: example, Name: test, Args: '8@%rax'

Использование

Есть три варианта использования этих трейспоинтов -- через eBPF, perf_event и ftrace -- все они потребуют рутовых привилегий и трассировка (по умолчанию) происходит для всей системы вцелом (или для указанного процесса).

Использование через BPF:

  • В пакете bcc-tools предоставляются следующие утилиты:
    • tplist покажет список трейспоинтов:
 # tplist -l /usr/lib64/libtcl8.6.so | grep entry
 /usr/lib64/libtcl8.6.so tcl:cmd__entry
 /usr/lib64/libtcl8.6.so tcl:proc__entry
  • bcc trace трассировщик. Пример использования:
 шелл-А# bcc trace 'u:/usr/lib64/libtcl8.6.so:cmd__entry "%s", arg1' 
 PID     TID     COMM            FUNC             -
 шелл-Б$ tclsh
 шелл-Б% puts test
 шелл-А:
 23036   23036   tclsh           cmd__entry       b'puts'
 шелл-А# bpftrace -e 'usdt:/usr/lib64/libtcl8.6.so:cmd__entry { printf("%s\n", str(arg0)); }'
 Attaching 1 probe...
 шелл-Б$ tclsh
 шелл-Б% puts test
 шелл-А:
 puts

Использование через perf_event:

  • В пакете perf одноименная утилита, пример:
 # perf buildid-cache --add /usr/lib64/libtcl8.6.so
 # perf list | grep sdt_ | grep proc__entry
   sdt_tcl:proc__entry                                [SDT event]
 # perf probe sdt_tcl:proc__entry
 Added new events:
   sdt_tcl:proc__entry  (on %proc__entry in /usr/lib64/libtcl8.6.so)
 # perf record -e sdt_tcl:proc__entry -a -- tclsh
 % echo 'hello world'
 'hello world'
 % ^D
 # perf script | head -1
          tclsh 22814 [015] 686801.201230: sdt_tcl:proc__entry: (7f9950fdf04e) arg1=94274876797648 arg2=0 arg3=94274876480632

Доп. материалы