PHP может быть сконфигурирован со статическими зондами DTrace на платформах поддерживающих динамическую трассировку DTrace.
Обратитесь к документации вашей платформы, чтобы включить поддержку DTrace в вашей операционной системе. К примеру, в Oracle Linux необходимо загрузить ядро UEK3 и сделать следующее:
# modprobe fasttrap
# chmod 666 /dev/dtrace/helper
Вместо chmod
, вы можете использовать
пакет правил ACL для ограничения доступа для конкретного
пользователя.
Сборка PHP с ключом --enable-dtrace
:
# ./configure --enable-dtrace ...
# make
# make install
Это включит статические зонды в ядре 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 могут содержать дополнительные зонды.
Для получения списка зондов, запустите процесс 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 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); [ . . .] }