Usando PHP e DTrace

O PHP pode ser configuracom com sensores estáticos do DTrace em plataformas que suportam a Instrumentação Dinâmica do DTrace.

Configurando o PHP para Sensores Estáticos DTrace

Refira-se à documentação externa específica da plataforma para habilitar o suporte do DTrace no sistema operacional. Por exemplo, no Oracle Linux inicialize um kernel UEK3 e rode os seguintes comandos:

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

Ao invés de usar chmod, pode-se alternativamente usar uma regra de pacote ACL para limitar o acesso a um dispositivo para um usuário específico.

Construa o PHP com o parâmetro de configuração --enable-dtrace:

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

Isto habilita sensores estáticos no núcleo do PHP. Quaisquer extensões PHP que fornecem seus próprios sensores devem ser construídas separadamente como extensões compartilhadas.

Sensores Estáticos DTrace no Núcleo do PHP

Os sensores estáticos a seguir estão disponíveis no PHP
Nome do SensorDescrição do SensorArgumentos do Sensor
request-startupDispara quando uma requisição inicia.char *file, char *request_uri, char *request_method
request-shutdownDispara quando uma requisição termina.char *file, char *request_uri, char *request_method
compile-file-entryDispara quando a compilação de um script inicia.char *compile_file, char *compile_file_translated
compile-file-returnDispara quando a compilação de um script termina.char *compile_file, char *compile_file_translated
execute-entryDispara quando um array de opcode está para ser executado. Por exemplo, ele dispara em chamadas de função, de includes e em continuação de geradores.char *request_file, int lineno
execute-returnDispara depois da execução de um array de opcode.char *request_file, int lineno
function-entryDispara quando o motor do PHP entra em uma chamada de função ou método.char *function_name, char *request_file, int lineno, char *classname, char *scope
function-returnDispara quando o motor do PHP retorna de uma chamada de função ou método.char *function_name, char *request_file, int lineno, char *classname, char *scope
exception-thrownDispara quando uma exceção é disparada.char *classname
exception-caughtDispara quando uma exceção é capturada.char *classname
errorDispara quando um erro ocorre, independente do nível de error_reporting.char *errormsg, char *request_file, int lineno

Extensões de PHP podem também conter sensores estáticos adicionais.

Listando os Sensores Estáticos DTrace no PHP

Para listar os sensores disponíveis, inicie um processo PHP e então execute:

 # dtrace -l 

A saída 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 

Os valores da coluna Provider consistem de php mais o id do processo PHP sendo executado.

Se o servidor web Apache estiver rodando, o módulo poderia ser, por exemplo, libphp5.so, e haveria múltiplos blocos de listagens, um para cada processo Apache em execução.

A coluna Function refere-se aos nomes das funções da implementação interna do PHP, em C, onde cada fornecedor está localizado.

Se um processo PHP não estiver em execução, então nenhum sensor PHP será mostrado.

Exemplo de DTrace com PHP

Este exemplo mostra o básico da linguagem D de scripts DTrace.

Exemplo #1 Arquivo all_probes.d para instrumentar todos os Sensores Estáticos PHP com 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 usa a opção -Z para a aplicação dtrace, permitindo que ela seja executada quando não há processo PHP em execução. Se esta opção fosse omitida, o script iria terminar imediatamente porque ele saberia que nenhum dos sensores a serem monitorados existiriam.

O script instrumenta todos os pontos de sensores estáticos do núcleo do PHP durante toda a duração de um script PHP em execução. Execute o script D:

 # ./all_probes.d 

Executa um script PHP ou aplicação. O script D de monitoramento terá como saída os argumentos de cada um dos sensores quando for disparado.

Quando o monitoramento estiver completo, o script D pode ser terminado com CTRL+C.

Em máquinas com múltiplas CPUs, pode parecer que os sensor estão em ordem não sequencial. Isto depende de qual CPU está processando os sensores, e como as threads migram atráves dos CPUs. Mostrar os timestamps dos sensores irá ajudar a reduzir a confusão, por exemplo:

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