Usando PHP y DTrace

PHP puede ser configurado con sondas estáticas DTrace en plataformas que soportan Rastreo Dinámico DTrace.

Configurando PHP para Sondas Estáticas DTrace

Refierase a la documentación externa específica par su plataforma para habilitar el soporte para rastreo DTrace en el sistema operativo. Por ejemplo, en Oracle Linux arranque con un kernel UEK3 y haga:

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

En lugar de utilizar chmod, usted podria utilizar una regla de paquete ACL para limitar acceso a los dispositivos a ciertos usuarios.

Compile PHP con el parámetro de configuración --enable-dtrace:

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

Esto habilita las sondas estáticas en el núcleo de PHP. Cualquiera de las extensiones que ofrezcan sus propios sondeos deberán ser compiladas de forma separada como extensiones compartidas.

Sondeos Estáticos DTrace en el núcleo de PHP

Los siguientes sondeos estáticos están disponibles en PHP
Nombre del Sondeo Descripción del Sondeo Argumentos del Sondeo
request-startup Se dispara cuando comienza una petición. char *file, char *request_uri, char *request_method
request-shutdown Se dispara cuando se termina una petición. char *file, char *request_uri, char *request_method
compile-file-entry Se dispara cuando la compilación de un script comienza. char *compile_file, char *compile_file_translated
compile-file-return Se dispara cuando la compilación de un script termina. char *compile_file, char *compile_file_translated
execute-entry Se dispara cuando un código de operación array está por ser ejecutado. Por ejemplo, se dispara en llamadas a funciones, includes, y continuaciones de resumes. char *request_file, int lineno
execute-return Se dispara después de la ejecución de un código de operación array. char *request_file, int lineno
function-entry Se dispara cuando el motor de PHP entra a la llamada de una función o método. char *function_name, char *request_file, int lineno, char *classname, char *scope
function-return Se dispara cuando el motor de PHP regresa de la llamada a una función o método. char *function_name, char *request_file, int lineno, char *classname, char *scope
exception-thrown Se dispara cuando una excepción es lanzada. char *classname
exception-caught Se dispara cuando una excepción es capturada. char *classname
error Se dispara cuando ocurre un error, sin importar el nivel de error_reporting. char *errormsg, char *request_file, int lineno

Otras extensiones PHP pueden también tener otras sondas estáticas adicionales.

Listando Sondas Estáticas DTrace en PHP

Para listar todas las sondas disponibles, inicie un proceso PHP y ejecute:

# dtrace -l

La salida será similar a:

   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

La columna Proveedor consiste en php y el id del proceso del proceso PHP que está ejecutandose.

Si el servidor web Apache está corriendo, el nombre del módulo será, por ejemplo, libphp5.so, y habría múltiples bloques de listado, uno por cada proceso Apache ejecutandose.

La columna Función se refiere los nombres internos de función de su implementación en C, donde cada proveedor está ubicado.

Si un proceso PHP no está ejecutandose, entonces ningún sondeo será mostrado.

DTrace con un ejemplo PHP

Este ejemplo muestra los conceptos básicos del lenguaje de scripting DTrace D.

Ejemplo #1 all_probes.d para monitorizar todos los Śondeos Estáticos en PHP con 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));
}

Este script utiliza la opción -Z en dtrace, permitiendo que se ejecute aún cuando no hay procesos PHP ejecutandose. Si esta opción se hubiese omitido el script hubiese terminado inmediatamente porque no sabría que los sondeos a ser monitorizados realmente son válidos.

Este script rastrea todas las sondas estáticas del núcleo de PHP y puntos de muestreo a lo largo de la duración de un script PHP que esté corriendo:

# ./all_probes.d

Ejecuta un script o aplicación PHP. El script D de monitorización mostrará los argumentos de cada sondeo según vayan sucediendo.

Cuando la monitorización está completada, el script D puede ser terminado con ^C.

En máquinas con múltiples-CPU el orden de los sondeos podría no aparecer secuencialmente. Esto depende de en que CPU fue procesado, y como los hilos se mueven a través de las CPUs. Mostrar la fecha y hora del sondeo ayudará a reducir la confusión, por ejemplo:

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