Devel::CallTrace, Devel::CallStack, Devel::RemoteTrace,
Devel::Trace, Devel::TraceMore, Devel::TraceVars,
Devel::TraceSubs – es gibt viele Module
die die Ausführung eines Perl Programms verfolgen helfen.
Was noch kann man wollen?
Doch haben wir in unserem Team vor einige Jahre noch ein Modul entwickelt.
Das Modul heißt Devel::YCallTrace und ist auf GitHub erreichbar.
Ich möchte die vorhandene Werkzeuge kurz beschreiben
und ihre Vorteile und Nachteile angeben.
Dann zeige ich, wie man unser Modul benutzen kann
und welche Aufgabe sind möglich damit zu lösen.
Wer bin ich
Ich heiße Lena, ich komme aus Moskau, Russland.
Es freut mich hier mit euch zu sein, und ich möchte ich mich entschuldigen für Akzent und Fehlern ;)
Der Vortrag war mein erster großer Vortrag auf Deutsch, und das ist der größte Text, den ich auf Deutsch geschrieben habe.
Ich arbeite bei Yandex.
Yandex ist die größte suchmaschine in Russland, wir haben dort etwa 60% des Suchmarkts.
Und Yandex ist jetzt die 4. größte Suchmaschine der Welt an der Zahl der Suchanfragen,
nur noch hinter den Suchmaschinen Google, Baidu und Yahoo.
Naturlich, die Suchmaschine selbst ist nicht in Perl geschrieben, aber Yandex hat auch viele
andere Teile und Dienste, die verschidene Programmesprache nutzen, and Perl auch.
Darum eigentlich arbeite ich bei Yandex.
Heute möchte ich über ein Werkzeug erzählen, die wir in unser Team für Diagnostizieren gebrauchen.
Problemstellung
Erstens, was ist das Problem?
Du hast ein Programm geschrieben, und es sieht gut aus, aber funkzioniert nicht richtig.
Wie kann man die Fehlern finden?
Na, es gibt viele Möglichkeiten.
Zum Beispiel, kann man das Programm aufmerksam lesen.
Oder Unittests schreiben und damit die Fehler etwa lokalisieren.
Oder das Programm im debugger öffnen und Einzelschritt-Verarbeitung machen.
Debugger ist ein gutes Werkzeug.
Aber was ist wenn das Programm ziemlich gross ist und komplizierte Logik hat?
Wenn du keine Idee hast, in welchem Teil des Programs das Fehler sein kann,
dann kann Einzelschritt-Verarbeitung zu langweilich sein.
Dazu kann das Programm ein Teil von einem Webdienst sein und unter mod_perl laufen, oder so was.
Dann kann es schwierig sein, einen gewönlichen Debugger zu nutzen.
Es wäre gut einen “automatischer Debugger” zu haben:
das Programm auszuführen und dann einer Logdatei bekommen mit alle interesanten Sachen:
welche Operationen ausgeführt wurden, mit welchem Resultat und so weiter.
Was bietet CPAN?
Gut, gucken wir was es auf CPAN gibt.
Hier sind einige Beispiele.
Devel::RemoteTrace
Druckt jede Zeile die ausführt wird.
Verlangsamung: sehr bedeutend
Bericht:
Devel::TraceSubs
Druckt die Namen der Funktionen die ausführt werden, und ihre Parametern.
Verlangsamung: ~20x
warnings:
defined(%hash) is deprecated
Modification of non-creatable array value attempted
Initialisierung
Bericht:
Bericht 2:
Devel::CallTrace
Hier sind auch die Namen der Funktionen, doch ohne Parametern.
Gebraucht den Debugger
Verlangsmanung: ~1.5x
perl -d:CallTrace script.pl
Bericht
Devel::CallStack
druckt wieviel Mal man jeden Zustand den Stapelspeicher sah.
Verlangsamung: 2-10x
Gesamtbericht über den Stapelspeicher
perl -d:CallStack script.pl
less callstack.out
Bericht:
Devel::Trace
Wieder jede Zeile (wie sh -x)
perl -d:Trace script.pl
Bericht:
Devel::TraceVars
Noch einmal alle Zeilen die ausführt wurden. Jetzt mit Variablenwerte.
Bericht:
Ist alles schon gut? Leider nicht
Also, mit Devel::CallTrace und Devel::CallStack bekommt man zu wenig Information:
nur die Namen der Funktionen (die aufgeruft wurden).
Mit Devel::RemoteTrace, Devel::Trace, Devel::TraceVars bekommt man sehr große Logdateien.
Zum Beispiel, ich möchte Devel::Trace für ein kleines Programm benutzen.
Das program war nur 300 Zeile groß und lief für 2 Sekunden ohne Debugger.
Ich bekam 300 Megabyte Logdatei.
Es ist unbequem, einen solchen großen File zu bearbeiten.
Und für ein größes Program würde es vielleicht uberhaupt unmöglich.
Und doch fehlt da einige interresante Informationen: Werte der Variablen,
Rückgabewerte der Funktionen unn so weiter.
Mir gefällt am liebsten Devel::TraceSubs.
Aber riesiges File ist sowieso unbequem zu untersuchen.
Devel::YCallTrace
So, hier kommt unser Modul.
Er heißt Devel::YCallTrace,
und mit ihm wir versuchen den goldenen Mittelweg zu finden.
Gespeichert werden die Aufrufen der Funktionen, Paremetern und Rückgabewerte.
Die Logdatei wird in einer Datenbank gespeichert.
Um eienen Bericht zu lesen, kann man einen specialen Html-Schnittstelle benutzen.
Demo
Hier is ein kleines Programm für Fibonacci-Zahlen Rechnung.
Führen wir das Programm aus und starten wir den Webdienst um den Bericht zu sehen.
Hier ist die Liste, alle Logdateien:
Hier sind Parametern und Rückgabewerte:
Und jetzt zwei speciäle Fällen: wenn ein Funktion exit() oder die aufruft.
Dass ist die Fibonacci-Function, die in zufälligen Moment stirbt.
Und hier ist die Logdatei:
Hier ist eine änliche Programme mit exit statt die.
Und hier ist die Logdatei:
Das alle waren Beispielen mit Initialisirung im Quelltext.
Das kann nicht immer passen.
Dann können wir YCallTrace als ein Debugger gebrauchen.
Zum Beispiel, ich suche etwas mit dem Programm ack, und will wissen, was das Programm dabei tut.
So, hier ist die Logdatei.
Devel::YCallTrace: Nutzung
Also, es gibt 3 Varianten wie man dieses Modul gebrauchen kann.
Prozedurale Schnittstelle. Die Logdatei wird im END block gespeihert.
Objektorientirte Schnitstelle mit “Guard object”. perl
Der Logdatei wird gespeihert wenn der Objekt zerstört wird.
Als einen Debugger
Irgendwie im Quelltext einer Webdienst
Was unser Team anbetrifft, wir etwieckeln einen Webdienst und haben im Quelltext etwa so:
Wenn es keine Protuktivumgebung ist und es bei request ein speciales Cookie gibt,
dann speichern den Logdatei.
Es ist ziemlich bequem: wenn beim einigem Request etwas merkwürdig passiert,
kann man dieses Cookie erzeugen, einen Request machen und dann den Bericht prüfen.
Oft ist alles ziemlich schnell clar. Mir gefällt das.