PHP 可以使用 DTrace 静态探针配置,适用于支持 DTrace 动态跟踪的平台。
请参考外部平台特定文档以了解如何启用操作系统 DTrace 支持。例如,在 Oracle Linux 上,启动一个 UEK3 内核并执行以下操作
# modprobe fasttrap
# chmod 666 /dev/dtrace/helper
您可以使用 ACL 包规则来限制特定用户的设备访问权限,而不是使用 chmod
。
使用 --enable-dtrace
配置参数构建 PHP
# ./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 |
执行操作码数组时触发。例如,它在函数调用、包含和生成器恢复时触发。 | char *request_file, int lineno |
execute-return |
执行操作码数组后触发。 | char *request_file, int lineno |
function-entry |
PHP 引擎进入 PHP 函数或方法调用时触发。 | char *function_name, char *request_file, int lineno, char *classname, char *scope |
function-return |
PHP 引擎从 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
和当前正在运行的 PHP 进程的进程 ID。
如果 Apache Web 服务器正在运行,模块名称可能是 libphp5.so,并且会有多个列表块,每个正在运行的 Apache 进程一个。
Function 列指的是 PHP 内部 C 实现函数名称,每个提供者都位于其中。
如果 PHP 进程未运行,则不会显示任何 PHP 探针。
此示例演示了 DTrace D 脚本语言的基础知识。
示例 #1 all_probes.d 用于使用 DTrace 跟踪所有 PHP 静态探针
#!/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 终止 D 脚本。
在多 CPU 机器上,探针顺序可能看起来不连续。这取决于哪个 CPU 正在处理探针,以及线程如何在 CPU 之间迁移。显示探针时间戳将有助于减少混淆,例如
php*:::function-entry { printf("%lld: PHP function-entry ", walltimestamp); [ . . .] }