Sur les distributions Linux dont le noyau supporte eBPF, l'utilitaire bpftrace peut s'attacher directement aux sondes USDT DTrace de PHP, sans nécessiter SystemTap.
Il faut installer bpftrace avec le gestionnaire de paquets de la distribution. Par exemple, sur Oracle Linux, RHEL ou Fedora :
# dnf install bpftrace
# apt install bpftrace
Les exemples ci-dessous supposent que le binaire PHP cible est installé dans /usr/bin/php.
Les mêmes sondes USDT sont également exposées par les autres SAPI compilées à partir du même
arbre de sources, donc la cible de la sonde peut aussi être le module Apache
(libphp.so) ou le binaire du gestionnaire de processus FastCGI
(php-fpm) ; il faut substituer le chemin approprié ou s'attacher
par PID avec -p si nécessaire.
Il faut s'assurer que le binaire cible est compilé avec DTrace et que l'environnement est correctement configuré. Voir Configurer PHP pour les sondes statiques DTrace pour les détails.
Les sondes statiques de PHP peuvent être listées en utilisant bpftrace :
# bpftrace -l 'usdt:/usr/bin/php:php:*'
Ce qui affiche :
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
Exemple #1 all_probes.bt pour tracer toutes les sondes statiques de PHP avec 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));
}
Le script ci-dessus tracera tous les points de sonde statiques du cœur de PHP pendant toute la durée d'exécution d'un script PHP. bpftrace nécessite les privilèges root :
# USE_ZEND_DTRACE=1 bpftrace -c '/usr/bin/php test.php' all_probes.bt
Pour tracer un processus PHP déjà en cours d'exécution (par exemple, un worker php-fpm ou un processus Apache chargeant libphp.so), il faut s'attacher par PID :
# bpftrace -p $PID all_probes.bt
usdt: dans le script doit correspondre au binaire
du processus en cours ; il faut ajuster usdt:/usr/bin/php au
binaire php-fpm ou à libphp.so selon le cas.