On Linux distributions with a kernel that supports eBPF, the bpftrace utility can attach to PHP's DTrace USDT probes directly, without requiring SystemTap.
Install bpftrace using the distribution's package manager. For example, on Oracle Linux, RHEL, or Fedora:
# dnf install bpftrace
# apt install bpftrace
The examples below assume the target PHP binary is installed at /usr/bin/php.
The same USDT probes are also exposed by other SAPIs built from the same source tree, so the
probe target may instead be the Apache module
(libphp.so) or the FastCGI Process Manager
binary (php-fpm); substitute the appropriate
path or attach by PID with -p as needed.
Make sure the target binary is built with DTrace and the environment variable is configured properly. See Configuring PHP for DTrace Static Probes for details.
The static probes in PHP can be listed using bpftrace:
# bpftrace -l 'usdt:/usr/bin/php:php:*'
This outputs:
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
Example #1 all_probes.bt for tracing all PHP Static Probes with 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));
}
The above script will trace all core PHP static probe points throughout the duration of a running PHP script. bpftrace requires root privileges:
# USE_ZEND_DTRACE=1 bpftrace -c '/usr/bin/php test.php' all_probes.bt
To trace an already-running PHP process (for instance, a php-fpm worker or an Apache process loading libphp.so), attach by PID:
# bpftrace -p $PID all_probes.bt
usdt: target path in the script must match the binary of
the running process; adjust usdt:/usr/bin/php to the
php-fpm binary or libphp.so as appropriate.