Використання PHP та DTrace

PHP може бути налаштований зі статичними зондами DTrace на платформах, що підтримують динамічне трасування DTrace.

Конфігурування PHP із статичними зондами DTrace

Зверніться до документації вашої платформи, щоб увімкнути підтримку DTrace у вашій операційній системі. Наприклад, в Oracle Linux необхідно завантажити ядро ​​UEK3 і зробити таке:

Loading...

Замість chmod, Ви можете використовувати пакет правил ACL для обмеження доступу для конкретного користувача.

Складання PHP з ключем --enable-dtrace :

Loading...

Це включає статичні зонди в ядрі PHP. Будь-який модуль PHP, що надає власні зонди, повинен бути зібраний окремо як модуль, що розділяється.

Статичні зонди DTrace у ядрі PHP

Наступні статичні зонди доступні в PHP

Имя зондаОпис зондаАргументы зонда
request-startupСпрацьовує на початку запиту.char *file, char *request_uri, char *request_method
request-shutdownСпрацьовує після закінчення запиту.char *file, char *request_uri, char *request_method
compile-file-entryСпрацьовує, коли розпочинається компіляція скрипту.char *compile_file, char *compile_file_translated
compile-file-returnСпрацьовує, коли закінчується компіляція скрипту.char *compile_file, char *compile_file_translated
execute-entryСпрацьовує, коли запускається масив байт-коду. Наприклад, коли викликаються функції, відновлюється робота генератора чи відбувається include.char *request_file, int lineno
execute-returnСпрацьовує після відпрацювання масиву байт-коду.char *request_file, int lineno
function-entryСпрацьовує, коли PHP починає запуск функції або методу.char *function_name, char *request_file, int lineno, char *classname, char *scope
function-returnСпрацьовує, коли PHP повертається з функції або методу.char *function_name, char *request_file, int lineno, char *classname, char *scope
exception-thrownСпрацьовує, коли викинуто виняток.char *classname
exception-caughtСпрацьовує, коли виняток спійманий.char *classname
errorСпрацьовує, якщо сталася помилка, незалежно від рівня error_reportingchar *errormsg, char *request_file, int lineno

Модулі PHP можуть мати додаткові зонди.

Список статичних зондів DTrace у PHP

Щоб отримати список зондів, запустіть процес PHP і виконайте:

# dtrace -l

Висновок буде приблизно такий:

ID   PROVIDER            MODULE                          FUNCTION NAME
   [ . . . ]
    4   php15271               php               dtrace_compile_file compile-file-entry
    5   php15271               php               dtrace_compile_file compile-file-return
    6   php15271               php                        zend_error error
    7   php15271               php  ZEND_CATCH_SPEC_CONST_CV_HANDLER exception-caught
    8   php15271               php     zend_throw_exception_internal exception-thrown
    9   php15271               php                 dtrace_execute_ex execute-entry
   10   php15271               php           dtrace_execute_internal execute-entry
   11   php15271               php                 dtrace_execute_ex execute-return
   12   php15271               php           dtrace_execute_internal execute-return
   13   php15271               php                 dtrace_execute_ex function-entry
   14   php15271               php                 dtrace_execute_ex function-return
   15   php15271               php              php_request_shutdown request-shutdown
   16   php15271               php               php_request_startup request-startup

Колонка Provider містить напис php та pid поточного запущеного процесу PHP.

Якщо запущено веб-сервер Apache, ім'я модуля може бути, наприклад, libphp5.so, і може бути безліч блоків списку по одному на кожен процес Apache.

Колонка Function посилається на ім'я внутрішньої функції PHP, що реалізує відповідний зонд.

Якщо PHP не запущено, то пов'язаних з ним зондів у списку не буде.

Приклади використання DTrace із PHP

Цей приклад показує основні можливості скриптової мови DTrace D.

Приклад #1 all_probes.d - трасування всіх статичних зондів PHP за допомогою DTrace

#!/usr/sbin/dtrace -Zs

#pragma D option quiet

php*:::compile-file-entry
{
    printf("PHP compile-file-entry\n");
    printf("  compile_file              %s\n", copyinstr(arg0));
    printf("  compile_file_translated   %s\n", copyinstr(arg1));
}

php*:::compile-file-return
{
    printf("PHP compile-file-return\n");
    printf("  compile_file              %s\n", copyinstr(arg0));
    printf("  compile_file_translated   %s\n", copyinstr(arg1));
}

php*:::error
{
    printf("PHP error\n");
    printf("  errormsg                  %s\n", copyinstr(arg0));
    printf("  request_file              %s\n", copyinstr(arg1));
    printf("  lineno                    %d\n", (int)arg2);
}

php*:::exception-caught
{
    printf("PHP exception-caught\n");
    printf("  classname                 %s\n", copyinstr(arg0));
}

php*:::exception-thrown
{
    printf("PHP exception-thrown\n");
    printf("  classname                 %s\n", copyinstr(arg0));
}

php*:::execute-entry
{
    printf("PHP execute-entry\n");
    printf("  request_file              %s\n", copyinstr(arg0));
    printf("  lineno                    %d\n", (int)arg1);
}

php*:::execute-return
{
    printf("PHP execute-return\n");
    printf("  request_file              %s\n", copyinstr(arg0));
    printf("  lineno                    %d\n", (int)arg1);
}

php*:::function-entry
{
    printf("PHP function-entry\n");
    printf("  function_name             %s\n", copyinstr(arg0));
    printf("  request_file              %s\n", copyinstr(arg1));
    printf("  lineno                    %d\n", (int)arg2);
    printf("  classname                 %s\n", copyinstr(arg3));
    printf("  scope                     %s\n", copyinstr(arg4));
}

php*:::function-return
{
    printf("PHP function-return\n");
    printf("  function_name             %s\n", copyinstr(arg0));
    printf("  request_file              %s\n", copyinstr(arg1));
    printf("  lineno                    %d\n", (int)arg2);
    printf("  classname                 %s\n", copyinstr(arg3));
    printf("  scope                     %s\n", copyinstr(arg4));
}

php*:::request-shutdown
{
    printf("PHP request-shutdown\n");
    printf("  file                      %s\n", copyinstr(arg0));
    printf("  request_uri               %s\n", copyinstr(arg1));
    printf("  request_method            %s\n", copyinstr(arg2));
}

php*:::request-startup
{
    printf("PHP request-startup\n");
    printf("  file                      %s\n", copyinstr(arg0));
    printf("  request_uri               %s\n", copyinstr(arg1));
    printf("  request_method            %s\n", copyinstr(arg2));
}

Цей скрипт використовує опцію -Z для dtrace, дозволяючи йому працювати навіть якщо жодного процесу PHP не запущено. Якщо не використовувати цю опцію, то скрипт відразу завершить виконання, оскільки не побачить жодного зонда, який йому треба відстежувати.

Скрипт відстежує всі статичні зонди PHP протягом усього роботи PHP-скрипту. Запускаємо D-скрипт:

# ./all_probes.d

Запустіть скрипт або програму PHP. Відстежуючий D-скрипт виводитиме аргументи всіх зондів, що спрацювали.

Коли ви побачили все, що хотіли, можна перервати роботу скрипта комбінацією CTRL+C.

На багатопроцесорних машинах порядок зондів може бути не послідовним, залежно від того, на яких процесорах працюють зонди і як мігрують потоки між процесорами. Відображення тимчасових міток дозволить уникнути конфузів. Наприклад:

php*:::function-entry
{
      printf("%lld: PHP function-entry ", walltimestamp);
      [ . . .]
}

Дивіться також