CakeFest 2024: The Official CakePHP Conference

PHP mit DTrace verwenden

PHP kann auf Plattformen, die DTrace Dynamic Tracing unterstützen, mit statischen DTrace-Sonden konfiguriert werden.

PHP für statische DTrace-Sonden konfigurieren

Um die DTrace-Unterstützung des Betriebssystems zu aktivieren, siehe die externe plattformspezifische Dokumentation. Unter Oracle Linux muss zum Beispiel ein UEK3-Kernel gebootet und anschließend Folgendes ausgeführt werden:

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

Anstatt chmod zu verwenden, kann stattdessen eine ACL-Paketregel verwendet werden, um den Gerätezugriff auf einen bestimmten Benutzer zu beschränken.

PHP mit dem Konfigurationsparameter --enable-dtrace kompilieren:

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

Dies aktiviert die statischen Sonden im Kern von PHP. Alle PHP-Erweiterungen, die ihre eigenen Sonden bereitstellen, müssen separat als dynamische Erweiterungen gebaut werden.

Statische DTrace-Sonden im Kern von PHP

Die folgenden statischen Sonden stehen in PHP zur Verfügung
Name der Probe Beschreibung der Probe Parameter der Probe
request-startup Wird ausgelöst, wenn eine Anfrage beginnt. char *file, char *request_uri, char *request_method
request-shutdown Wird ausgelöst, wenn eine Anfrage endet. char *file, char *request_uri, char *request_method
compile-file-entry Wird ausgelöst, wenn die Kompilierung eines Skripts beginnt. char *compile_file, char *compile_file_translated
compile-file-return Wird ausgelöst, wenn die Kompilierung eines Skripts endet. char *compile_file, char *compile_file_translated
execute-entry Wird ausgelöst, wenn ein OpCode-Array ausgeführt wird, z. B. bei Funktionsaufrufen, Includes und wenn ein Generator fortfährt. char *request_file, int lineno
execute-return Wird nach der Ausführung eines OpCode-Arrays ausgelöst. char *request_file, int lineno
function-entry Wird ausgelöst, wenn die PHP-Engine in eine PHP-Funktion oder -Methode gelangt. char *function_name, char *request_file, int lineno, char *classname, char *scope
function-return Wird ausgelöst, wenn die PHP-Engine aus einer PHP-Funktion oder -Methode zurückkehrt. char *function_name, char *request_file, int lineno, char *classname, char *scope
exception-thrown Wird ausgelöst, wenn eine Exception ausgelöst wird. char *classname
exception-caught Wird ausgelöst, wenn eine Exception abgefangen wird. char *classname
error Wird ausgelöst, wenn ein Fehler auftritt, unabhängig von der error_reporting-Stufe. char *errormsg, char *request_file, int lineno

PHP-Erweiterungen verfügen möglicherweise über zusätzliche statische Sonden.

Liste statischer DTrace-Sonden in PHP

Um die verfügbaren Sonden aufzulisten, ist es nötig, einen PHP-Prozess zu starten und dann Folgendes auszuführen:

# dtrace -l

Die Ausgabe wird ungefähr so aussehen:

   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

Die Werte der Spalte PROVIDER setzen sich aus php und der Prozess-ID des aktuell laufenden PHP-Prozesses zusammen.

Wenn der Apache-Webserver läuft, könnte der Modulname zum Beispiel libphp5.so sein, und es gäbe pro laufendem Apache-Prozess einen Auflistungs-Block.

Die Spalte FUNCTION verweist auf den Funktionsnamen der PHP-internen C-Implementierung, in der sich der jeweilige Provider befindet.

Wenn kein PHP-Prozess läuft, werden auch keine PHP-Sonden angezeigt.

DTrace-Beispiel für PHP

Dieses Beispiel zeigt die grundlegenden Möglichkeiten der DTrace-Skriptsprache D.

Beispiel #1 all_probes.d für die Verfolgung aller statischen PHP-Sonden mit 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));
}

Dieses Skript verwendet dtrace mit der Option -Z, damit es auch dann ausgeführt werden kann, wenn gerade kein PHP-Prozess läuft. Ohne diese Option würde das Skript sofort beendet, weil es erkennt, dass keine der zu überwachenden Sonden vorhanden ist.

Das Skript verfolgt während der gesamten Zeit, in der ein PHP-Skript läuft, alle statischen Sondenpunkte des PHP-Kerns.

# ./all_probes.d

Sobald nun ein PHP-Skript oder eine Anwendung ausgeführt wird, beginnt das überwachende D-Skript, alle Parameter der ausgelösten Sonden auszugeben.

Um die Überwachung abzuschließen, kann das D-Skript mittels CTRL+C beendet werden.

Auf Rechnern mit mehreren CPUs ist die Reihenfolge der Tests möglicherweise nicht sequentiell. Dies hängt davon ab, welche CPU die Sonden verarbeitet hat und wie die Threads zwischen den CPUs wechseln. Die Anzeige der Zeitstempel der Sonden hilft, Verwechslungen zu vermeiden, zum Beispiel:

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

add a note

User Contributed Notes

There are no user contributed notes for this page.
To Top