PHP 및 DTrace 사용

PHP는 DTrace 동적 추적을 지원하는 플랫폼에서 DTrace 정적 프로브로 구성할 수 있습니다.


DTrace 정적 프로브를 위한 PHP 구성

운영 체제 DTrace 지원을 활성화하려면 외부 플랫폼별 설명서를 참조하십시오. 예를 들어 Oracle Linux에서 UEK3 커널을 부팅하고 다음을 수행합니다.

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

chmod를 사용하는 대신 ACL 패키지 규칙을 사용하여 특정 사용자에 대한 장치 액세스를 제한할 수 있습니다.

--enable-dtrace 구성 매개변수를 사용하여 PHP를 빌드합니다.

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

이것은 핵심 PHP에서 정적 프로브를 활성화합니다. 자체 프로브를 제공하는 모든 PHP 확장은 공유 확장으로 별도로 빌드해야 합니다.


코어 PHP의 DTrace 정적 프로브

다음 정적 프로브는 PHP에서 사용할 수 있습니다.

Probe Name Probe Description Probe Arguments
request-startup Fires when a request starts. char *file, char *request_uri, char *request_method
request-shutdown Fires when a request shutdown. char *file, char *request_uri, char *request_method
compile-file-entry Fires when the compilation of a script starts. char *compile_file, char *compile_file_translated
compile-file-return Fires when the compilation of a script finishes. char *compile_file, char *compile_file_translated
execute-entry Fires when an opcode array is to be executed. For example, it fires on function calls, includes, and generator resumes. char *request_file, int lineno
execute-return Fires after execution of an opcode array. char *request_file, int lineno
function-entry Fires when the PHP engine enters a PHP function or method call. char *function_name, char *request_file, int lineno, char *classname, char *scope
function-return Fires when the PHP engine returns from a PHP function or method call. char *function_name, char *request_file, int lineno, char *classname, char *scope
exception-thrown Fires when an exception is thrown. char *classname
exception-caught Fires when an exception is caught. char *classname
error Fires when an error occurs, regardless of the error_reporting level. char *errormsg, char *request_file, int lineno

PHP 확장에는 추가 정적 프로브가 있을 수도 있습니다.


PHP에서 DTrace 정적 프로브 나열

사용 가능한 프로브를 나열하려면 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 웹 서버가 실행 중인 경우 모듈 이름은 예를 들어 libphp5.so일 수 있으며 실행 중인 Apache 프로세스당 하나씩 여러 블록의 목록이 있을 수 있습니다.

함수 열은 각 공급자가 위치한 PHP의 내부 C 구현 함수 이름을 나타냅니다.

PHP 프로세스가 실행되고 있지 않으면 PHP 프로브가 표시되지 않습니다.


PHP 예제를 사용한 DTrace

이 예는 DTrace D 스크립팅 언어의 기본 사항을 보여줍니다.

예제 #1 DTrace로 모든 PHP 정적 프로브를 추적하기 위한 all_probes.d

#!/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));
}
                

이 스크립트는 dtrace-Z 옵션을 사용하여 PHP 프로세스가 실행되고 있지 않을 때 실행할 수 있습니다. 이 옵션을 생략하면 모니터링할 프로브가 존재하지 않는다는 것을 알기 때문에 스크립트가 즉시 종료됩니다.

스크립트는 PHP 스크립트를 실행하는 동안 모든 핵심 PHP 정적 프로브 지점을 추적합니다. D 스크립트를 실행합니다.

# ./all_probes.d
                

PHP 스크립트 또는 애플리케이션을 실행합니다. 모니터링 D 스크립트는 실행될 때 각 프로브의 인수를 출력합니다.

모니터링이 완료되면 ^C로 D 스크립트를 종료할 수 있습니다.

다중 CPU 시스템에서 프로브 순서는 순차적으로 나타나지 않을 수 있습니다. 이는 어떤 CPU가 프로브를 처리하고 있었고 스레드가 CPU 간에 마이그레이션되는 방식에 따라 다릅니다. 프로브 타임스탬프를 표시하면 다음과 같이 혼동을 줄이는 데 도움이 됩니다.

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

기타