Π Π°Π±ΠΎΡ‚Π° трассировщика bpftrace со статичСскими Π·ΠΎΠ½Π΄Π°ΠΌΠΈ PHP DTrace

Π’ дистрибутивах Linux, Π² ΠΊΠΎΡ‚ΠΎΡ€Ρ‹Ρ… ядро ΠΏΠΎΠ΄Π΄Π΅Ρ€ΠΆΠΈΠ²Π°Π΅Ρ‚ Ρ‚Π΅Ρ…Π½ΠΎΠ»ΠΎΠ³ΠΈΡŽ eBPF, трассировщик bpftrace ΡƒΠΌΠ΅Π΅Ρ‚ ΠΏΠΎΠ΄ΠΊΠ»ΡŽΡ‡Π°Ρ‚ΡŒΡΡ ΠΊ Π·ΠΎΠ½Π΄Π°ΠΌ PHP DTrace USDT Π±Π΅Π· посрСдничСства инструмСнта SystemTap.

Установка bpftrace

УстановитС bpftrace Ρ‡Π΅Ρ€Π΅Π· ΠΌΠ΅Π½Π΅Π΄ΠΆΠ΅Ρ€ ΠΏΠ°ΠΊΠ΅Ρ‚ΠΎΠ² дистрибутива. НапримСр, Π² Oracle Linux, RHEL ΠΈΠ»ΠΈ Fedora:

# dnf install bpftrace
Или в Debian либо Ubuntu:
# apt install bpftrace

Π‘Π»Π΅Π΄ΡƒΡŽΡ‰ΠΈΠ΅ ΠΏΡ€ΠΈΠΌΠ΅Ρ€Ρ‹ ΠΏΡ€Π΅Π΄ΠΏΠΎΠ»Π°Π³Π°ΡŽΡ‚, Ρ‡Ρ‚ΠΎ Ρ†Π΅Π»Π΅Π²ΠΎΠΉ исполняСмый Ρ„Π°ΠΉΠ» PHP установлСн ΠΏΠΎ ΠΏΡƒΡ‚ΠΈ /usr/bin/php.

Π’Π΅ ΠΆΠ΅ Π·ΠΎΠ½Π΄Ρ‹ USDT ΠΏΡ€Π΅Π΄ΠΎΡΡ‚Π°Π²Π»ΡΡŽΡ‚ ΠΈ Π΄Ρ€ΡƒΠ³ΠΈΠ΅ SAPI, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹Π΅ собрали ΠΈΠ· Ρ‚ΠΎΠ³ΠΎ ΠΆΠ΅ Π΄Π΅Ρ€Π΅Π²Π° исходного ΠΊΠΎΠ΄Π°, поэтому Ρ†Π΅Π»ΡŒΡŽ Π·ΠΎΠ½Π΄ΠΎΠ² вмСсто этого выступаСт Π»ΠΈΠ±ΠΎ ΠΌΠΎΠ΄ΡƒΠ»ΡŒ Apache (libphp.so), Π»ΠΈΠ±ΠΎ исполняСмый Ρ„Π°ΠΉΠ» диспСтчСра процСссов FastCGI (php-fpm); ΠΏΠΎΠ΄ΡΡ‚Π°Π²ΡŒΡ‚Π΅ ΠΏΡ€Π°Π²ΠΈΠ»ΡŒΠ½Ρ‹ΠΉ ΠΏΡƒΡ‚ΡŒ ΠΈΠ»ΠΈ ΠΏΠΎΠ΄ΠΊΠ»ΡŽΡ‡ΠΈΡ‚Π΅ΡΡŒ ΠΏΠΎ PID-ΠΈΠ΄Π΅Π½Ρ‚ΠΈΡ„ΠΈΠΊΠ°Ρ‚ΠΎΡ€Ρƒ Ρ‡Π΅Ρ€Π΅Π· ΠΊΠ»ΡŽΡ‡ -p ΠΏΡ€ΠΈ нСобходимости.

Π£Π±Π΅Π΄ΠΈΡ‚Π΅ΡΡŒ, Ρ‡Ρ‚ΠΎ собрали Ρ†Π΅Π»Π΅Π²ΠΎΠΉ исполняСмый Ρ„Π°ΠΉΠ» с ΠΏΠΎΠ΄Π΄Π΅Ρ€ΠΆΠΊΠΎΠΉ Ρ„Ρ€Π΅ΠΉΠΌΠ²ΠΎΡ€ΠΊΠ° DTrace ΠΈ Ρ‡Ρ‚ΠΎ ΠΏΡ€Π°Π²ΠΈΠ»ΡŒΠ½ΠΎ настроили ΠΏΠ΅Ρ€Π΅ΠΌΠ΅Π½Π½Ρ‹Π΅ окруТСния. ΠŸΠΎΠ΄Ρ€ΠΎΠ±Π½ΠΎΡΡ‚ΠΈ описываСт Ρ€Π°Π·Π΄Π΅Π» ΠšΠΎΠ½Ρ„ΠΈΠ³ΡƒΡ€ΠΈΡ€ΠΎΠ²Π°Π½ΠΈΠ΅ PHP со статичСскими Π·ΠΎΠ½Π΄Π°ΠΌΠΈ DTrace.

БтатичСскиС Π·ΠΎΠ½Π΄Ρ‹ PHP Π²Ρ‹Π²ΠΎΠ΄ΠΈΡ‚ ΠΊΠΎΠΌΠ°Π½Π΄Π° bpftrace:

# bpftrace -l 'usdt:/usr/bin/php:php:*'

Команда Π²Ρ‹Π²ΠΎΠ΄ΠΈΡ‚:

usdt:/usr/bin/php:php:compile__file__entry
usdt:/usr/bin/php:php:compile__file__return
usdt:/usr/bin/php:php:error
usdt:/usr/bin/php:php:exception__caught
usdt:/usr/bin/php:php:exception__thrown
usdt:/usr/bin/php:php:execute__entry
usdt:/usr/bin/php:php:execute__return
usdt:/usr/bin/php:php:function__entry
usdt:/usr/bin/php:php:function__return
usdt:/usr/bin/php:php:request__shutdown
usdt:/usr/bin/php:php:request__startup

ΠŸΡ€ΠΈΠΌΠ΅Ρ€ #1 Π‘ΠΊΡ€ΠΈΠΏΡ‚ all_probes.bt β€” трассировка всСх статичСских PHP-Π·ΠΎΠ½Π΄ΠΎΠ² Ρ‡Π΅Ρ€Π΅Π· bpftrace

#!/usr/bin/env bpftrace

usdt:/usr/bin/php:php:compile__file__entry
{
    printf("Probe compile__file__entry\n");
    printf("  compile_file %s\n", str(arg0));
    printf("  compile_file_translated %s\n", str(arg1));
}
usdt:/usr/bin/php:php:compile__file__return
{
    printf("Probe compile__file__return\n");
    printf("  compile_file %s\n", str(arg0));
    printf("  compile_file_translated %s\n", str(arg1));
}
usdt:/usr/bin/php:php:error
{
    printf("Probe error\n");
    printf("  errormsg %s\n", str(arg0));
    printf("  request_file %s\n", str(arg1));
    printf("  lineno %d\n", (int32)arg2);
}
usdt:/usr/bin/php:php:exception__caught
{
    printf("Probe exception__caught\n");
    printf("  classname %s\n", str(arg0));
}
usdt:/usr/bin/php:php:exception__thrown
{
    printf("Probe exception__thrown\n");
    printf("  classname %s\n", str(arg0));
}
usdt:/usr/bin/php:php:execute__entry
{
    printf("Probe execute__entry\n");
    printf("  request_file %s\n", str(arg0));
    printf("  lineno %d\n", (int32)arg1);
}
usdt:/usr/bin/php:php:execute__return
{
    printf("Probe execute__return\n");
    printf("  request_file %s\n", str(arg0));
    printf("  lineno %d\n", (int32)arg1);
}
usdt:/usr/bin/php:php:function__entry
{
    printf("Probe function__entry\n");
    printf("  function_name %s\n", str(arg0));
    printf("  request_file %s\n", str(arg1));
    printf("  lineno %d\n", (int32)arg2);
    printf("  classname %s\n", str(arg3));
    printf("  scope %s\n", str(arg4));
}
usdt:/usr/bin/php:php:function__return
{
    printf("Probe function__return\n");
    printf("  function_name %s\n", str(arg0));
    printf("  request_file %s\n", str(arg1));
    printf("  lineno %d\n", (int32)arg2);
    printf("  classname %s\n", str(arg3));
    printf("  scope %s\n", str(arg4));
}
usdt:/usr/bin/php:php:request__shutdown
{
    printf("Probe request__shutdown\n");
    printf("  file %s\n", str(arg0));
    printf("  request_uri %s\n", str(arg1));
    printf("  request_method %s\n", str(arg2));
}
usdt:/usr/bin/php:php:request__startup
{
    printf("Probe request__startup\n");
    printf("  file %s\n", str(arg0));
    printf("  request_uri %s\n", str(arg1));
    printf("  request_method %s\n", str(arg2));
}

ΠŸΡ€ΠΈΠ²Π΅Π΄Ρ‘Π½Π½Ρ‹ΠΉ скрипт трассируСт всС статичСскиС Π·ΠΎΠ½Π΄Ρ‹ ядра PHP Π½Π° всём протяТСнии Ρ€Π°Π±ΠΎΡ‚Ρ‹ PHP-скрипта. Врассировщику bpftrace Ρ‚Ρ€Π΅Π±ΡƒΡŽΡ‚ΡΡ ΠΏΡ€ΠΈΠ²ΠΈΠ»Π΅Π³ΠΈΠΈ ΡΡƒΠΏΠ΅Ρ€ΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚Π΅Π»Ρ:

# USE_ZEND_DTRACE=1 bpftrace -c '/usr/bin/php test.php' all_probes.bt

Для трассировки ΡƒΠΆΠ΅ Π·Π°ΠΏΡƒΡ‰Π΅Π½Π½ΠΎΠ³ΠΎ PHP-процСсса, Π½Π°ΠΏΡ€ΠΈΠΌΠ΅Ρ€, Ρ€Π°Π±ΠΎΡ‡Π΅Π³ΠΎ процСсса php-fpm ΠΈΠ»ΠΈ процСсса Apache, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹ΠΉ Π·Π°Π³Ρ€ΡƒΠ·ΠΈΠ» Π±ΠΈΠ±Π»ΠΈΠΎΡ‚Π΅ΠΊΡƒ libphp.so, ΠΏΠΎΠ΄ΠΊΠ»ΡŽΡ‡ΠΈΡ‚Π΅ΡΡŒ ΠΏΠΎ PID:

# bpftrace -p $PID all_probes.bt
Π’Π½ΡƒΡ‚Ρ€ΠΈ скрипта послС usdt: потрСбуСтся ΡƒΠΊΠ°Π·Π°Ρ‚ΡŒ Ρ†Π΅Π»ΡŒ β€” ΠΏΡƒΡ‚ΡŒ Π΄ΠΎ исполняСмого Ρ„Π°ΠΉΠ»Π° Π·Π°ΠΏΡƒΡ‰Π΅Π½Π½ΠΎΠ³ΠΎ процСсса: usdt:/usr/bin/php; Π·Π°ΠΌΠ΅Π½ΠΈΡ‚Π΅ ΠΏΡƒΡ‚ΡŒ Π² строкС спСцификации Π·ΠΎΠ½Π΄Π° Π½Π° ΠΏΡƒΡ‚ΡŒ Π΄ΠΎ исполняСмого Ρ„Π°ΠΉΠ»Π° php-fpm ΠΈΠ»ΠΈ Π±ΠΈΠ±Π»ΠΈΠΎΡ‚Π΅ΠΊΠΈ libphp.so, Ссли потрСбуСтся.
οΌ‹Π”ΠΎΠ±Π°Π²ΠΈΡ‚ΡŒ

ΠŸΡ€ΠΈΠΌΠ΅Ρ‡Π°Π½ΠΈΡ ΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚Π΅Π»Π΅ΠΉ

ΠŸΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚Π΅Π»ΠΈ Π΅Ρ‰Ρ‘ Π½Π΅ добавляли примСчания для страницы