## PHP и DTrace

PHP конфигурируется со статическими зондами DTrace на платформах, которые поддерживают динамическую трассировку DTrace.

### Конфигурирование PHP со статическими зондами DTrace

Обратитесь к документации платформы, чтобы включить поддержку DTrace в операционной системе. Например, в Oracle Linux требуется загрузить ядро UEK3 и сделать следующее:

    # modprobe fasttrap
    # chmod 666 /dev/dtrace/helper

Вместо `chmod` доступен пакет правил ACL для ограничения доступа для конкретного пользователя.

Сборка PHP с ключом `--enable-dtrace`:

    # ./configure --enable-dtrace ...
    # make
    # make install

Сборка PHP с ключом `--enable-dtrace` сделает статические зонды доступными в ядре PHP. Каждый PHP-модуль, который предоставляет свои зонды, потребуется собрать отдельно как разделяемый модуль.

Установите переменную среды USE_ZEND_DTRACE=1 для целевых 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_reporting. | char *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, если 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));
    }

Для команды dtrace скрипт указывает опцию `-Z` и разрешает работу, даже если ни один PHP-процесс не запущен. Без опции скрипт сразу же завершит выполнение, поскольку не увидит ни одного зонда для отслеживания.

Скрипт отслеживает каждый статический PHP-зонд на всём протяжении работы PHP-скрипта. Запускаем D-скрипт:

    # ./all_probes.d

Запустите скрипт или PHP-приложение. Отслеживающий D-скрипт будет выводить аргументы каждого сработавшего зонда.

После получения информации работу скрипта прерывают комбинацией ``CTRL`+`C``.

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

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

### Смотрите также

- OCI8 и динамическая трассировка DTrace

`↑` and `↓` to navigate • `Enter` to select • `Esc` to close • `/` to open