Proxy Sniffer

Werbung
Ingenieurbüro David Fischer AG | A Company of the Apica Group
http://www.proxy-sniffer.com
"Lasttest Plug-In" Entwicklungshandbuch
Version 4.6
Deutsche Ausgabe
© 2008, 2009, 2010, 2011, 2012
Alle Rechte vorbehalten.
Proxy Sniffer V 4.6
Plug-In Entwicklungshandbuch
Inhaltsverzeichnis
1
Übersicht ...........................................................................................................................3
1.1
Inhalt dieses Dokuments ............................................................................................3
1.2
Einführung ..................................................................................................................3
1.3
Neue Funktionalitäten ab Proxy Sniffer Version 4.5....................................................3
1.4
Neue Funktionalitäten ab Proxy Sniffer Version 4.6....................................................3
2 Eigenschaften, Laufzeitverhalten und Konfiguration ..........................................................4
2.1
Laufzeitumgebung ......................................................................................................4
2.2
Lebenszyklus von Plug-Ins während der Testausführung ...........................................5
2.3
Konfiguration von Plug-Ins mittels des GUIs ..............................................................6
2.4
Lebenszyklus von Plug-Ins nach der Konfiguration ....................................................8
3 Entwicklung eigener Plug-Ins ............................................................................................9
3.1
Java API Dokumentation ............................................................................................9
3.2
Verwenden von mehreren Klassen und von externen Class-Libraries ........................9
3.3
Erstellen des Programm-Skeletts mit dem GUI-Assistenten ..................................... 11
3.4
Programmierung der Plug-In Funktionalität .............................................................. 14
3.4.1
Klasse LoadtestPluginContext ........................................................................... 16
3.4.2
Klasse HttpLoadTest ......................................................................................... 17
3.4.3
Spezielle Hinweise zur Laufzeitumgebung ........................................................ 18
3.4.3.1
Debug-Output während der Plug-In Ausführung ......................................... 18
3.4.3.2
Initialisierung eines Plug-Ins mittels importierten GUI-Variablen................. 18
3.4.3.3
Extrahieren von Daten aus der HTTP-Response von URL-Calls ................ 19
3.4.3.4
Ausführen von Plug-Ins am Ende eines Loops ........................................... 20
3.4.3.5
Plug-Ins bei Cluster-Jobs ........................................................................... 20
3.4.3.6
Integrieren von zusätzlichen (externen) Messdaten ................................... 21
3.4.3.7
Versenden von E-Mails mittels SMTP ........................................................ 26
3.4.3.8
Umgang mit Zeitzonen und Datums-Berechnungen ................................... 26
3.4.3.9
Erzeugen von Plug-In spezifischen Fehler-Arten ........................................ 27
3.4.4
Performante Plug-In Programmierung ............................................................... 29
3.4.4.1
Vorberechnen von Ergebnissen ................................................................. 29
3.4.4.2
Disk und Netzwerk I/O-Operationen ........................................................... 30
3.5
Plug-In Programm-Beispiele..................................................................................... 31
4 Hersteller ......................................................................................................................... 32
© 2008, 2009, 2010, 2011, 2012 Ingenieurbüro David Fischer AG
Alle Rechte vorbehalten
Seite 2 / 32
Proxy Sniffer V 4.6
Plug-In Entwicklungshandbuch
1 Übersicht
1.1 Inhalt dieses Dokuments
Dieses Handbuch gibt in einem ersten Teil einen Überblick über die Eigenschaften, das
Laufzeitverhalten und die Konfiguration von Proxy Sniffer Lasttest Plug-Ins. In einem zweiten
Teil wird auf die Entwicklung eigener Plug-Ins eingegangen.
1.2 Einführung
Proxy Sniffer Lasttest Plug-Ins sind Erweiterungs-Module zum Proxy Sniffer Produkt, welche
über das GUI konfiguriert werden und während der Durchführung eines Lasttests zur
Ausführung kommen.
Nebst bereits vorgefertigten Plug-Ins, welche mit dem Produkt zusammen ausgeliefert
werden, lassen sich auch eigene Plug-Ins erstellen, wodurch zusätzliche Funktionalitäten
nach eigenem Bedarf dem Produkt hinzugefügt werden können.
Plug-Ins habe unter anderem die Eigenschaft, dass diese wieder verwendbar sind. Ist ein
neues Plug-In einmal erstellt, so kann dieses in jedem Lasttest-Programm verwendet werden.
Zur Erstellung eines neuen Plug-Ins sind Java Programmier-Kenntnisse notwendig, wobei zur
Erleichterung der Programmierung das Programm-Skelett eines Plug-Ins mittels eines GUIAssistenten automatisch erstellt werden kann.
Die Einbindung eines bereits erstellten Plug-Ins in ein Lasttest-Programm benötigt hingegen
keine Programmier-Kenntnisse, da dies über das GUI mittels weniger Maus-Klicks erfolgt.
Die Ausführung eines Plug-Ins geschieht auf demselben Exec-Agent Rechner, auf welchem
auch das Lasttest-Programm ausgeführt wird. Beim Starten eines Lasttests wird das
entsprechende Plug-In automatisch zusammen mit dem Lasttest-Programm an den Exec
Agenten übertragen, so dass auf diesem keine vorhergehende Installation des Plug-Ins
notwendig ist.
1.3 Neue Funktionalitäten ab Proxy Sniffer Version 4.5
Ab Proxy Sniffer Version 4.5 können Plug-Ins zusätzlich:
Break- oder Continue-Sprünge bei "Inner Loops" auslösen.
Dem Lasttest-Resultat beliebige XY-Diagramme hinzufügen, deren Daten innerhalb eines
Plug-Ins selbst gemessen wurden (Vor V4.5 war die X-Achse eines hinzugefügten
Diagramms immer auf die aktuelle Zeit während der Lasttest-Ausführung beschränkt).
1.4 Neue Funktionalitäten ab Proxy Sniffer Version 4.6
Ab Proxy Sniffer Version 4.6 können Plug-Ins zusätzlich:
XY-Diagrammen auch auf Cluster-Ebene erzeugen, wobei die Diagramm-Daten der
einzelnen Lastgeneratoren entweder mittels Addition oder durch die Bildung eines
"künstlichen Mittelwertes" automatisch von Proxy Sniffer vereinigt werden.
Eigene Typen von kundenspezifischen Fehlermeldungen erzeugen welche in den
"normalen" Detail-Diagrammen und -Daten der Lasttest-Resultate dargestellt werden.
© 2008, 2009, 2010, 2011, 2012 Ingenieurbüro David Fischer AG
Alle Rechte vorbehalten
Seite 3 / 32
Proxy Sniffer V 4.6
Plug-In Entwicklungshandbuch
2 Eigenschaften, Laufzeitverhalten und Konfiguration
Alle „Lasttest Plug-Ins“ werden im GUI mittels des Variablen-Handlers in das LasttestProgramm eingebunden. Solche Plug-Ins können:
1. GUI-Variablen importieren
2. Eigenen Programm-Code ausführen
3. GUI-Variablen exportieren, sowie das Lasttest-Programm vorzeitig abbrechen, oder
auch weitere Messdaten dem Lasttest-Resultat hinzufügen.
Beispiel 1: ein Plug-In errechnet ein Datum (MM.DD.YYYY), welches vom aktuellen Datum
aus gesehen immer drei Tage in der Zukunft liegt. Das Datum wird als GUI-Variable exportiert.
Diese Variable wird danach bei einem HTML-Formular als Input-Parameter zum dynamischen
Setzen eines Buchungsdatums verwendet.
Beispiel 2: bei einem Bestell-Vorgang wird mittels des Variablen-Handlers die BestellNummer zuerst als GUI-Variable aus einem URL-Call extrahiert und danach als Input-Variable
einem Plug-In übergeben. Das Plug-In schreibt alle so gesammelten Bestell-Nummern aller
simulierten Benutzer in ein File, welche nach der Ausführung des Lasttests zur Verfügung
steht. Aufgrund dieses Files können später die Bestellungen storniert werden.
Beispiel 3: ein Plug-In überwacht dauernd den Fortschritt des Lasttest und stoppt diesen,
wenn innerhalb eins Zeitfensters von 5 Minuten mehr als 90% aller Loops fehlschlagen –
gezählt über alle virtuellen Benutzer. Dadurch wird bei einem Dauertest über mehrere
Stunden ein vorzeitiger Abbruch des Tests erzwungen, wenn der Web-Server kollabiert und
sich nicht mehr von selbst „erholt“.
2.1 Laufzeitumgebung
Plug-Ins sind stark mit dem Laufzeit-Daten eines Lasttests integriert und können Zugriff
nehmen auf:
-
alle GUI-Variablen welche bereits im Variablen-Handler definiert wurden (Import wie auch
Export von GUI-Variablen).
-
auf die aktuellen (real-time) Messdaten eines laufenden Lasttest-Programms.
-
Auf die Daten von bestimmten oder auch von allen ausgeführten URL-Calls eines
laufenden Lasttest-Programms, inkl. der Möglichkeit diese vor der Ausführung abzuändern
oder zu ergänzen, sowie der Möglichkeit, deren Ergebnisse nach der Ausführung weiter zu
verarbeiten.
-
Auf das Betriebssystem des Exec Agenten sofern dessen Schnittstellen über Java
zugänglich sind (z.B. auf Netzwerkverbindungen, Disk-Files etc.).
-
Auf weitere Daten der Laufzeitumgebung eines Lasttests wie z.B. die aktuelle Nummer
eines virtuellen Benutzers, die aktuellen Nummer des Lasttest-ausführenden ClusterMembers (bei Cluster-Jobs) oder auch auf den Cookie-Speicher eines virtuellen
Benutzers.
Einschränkend gilt jedoch, dass ein Plug-In die Struktur des Programm-Ablaufs eines LasttestProgramms in der Regel nicht beeinflussen kann. So kann ein Plug-In z.B. die Reihenfolge der
ausgeführten URL-Calls nicht beeinflussen. Ebenso wenig kann ein Plug-In bei einem
aufgetretenen (gemessenen) Fehler eines URL-Calls dessen Ergebnis nachträglich
„korrigieren“. Umgekehrt ist es jedoch einem Plug-In möglich, einen erfolgreichen URL-Call in
einen Fehler zu verwandeln.
© 2008, 2009, 2010, 2011, 2012 Ingenieurbüro David Fischer AG
Alle Rechte vorbehalten
Seite 4 / 32
Proxy Sniffer V 4.6
Plug-In Entwicklungshandbuch
2.2 Lebenszyklus von Plug-Ins während der Testausführung
Ein Plug-In wird zuerst initialisiert, danach ein- oder mehrmals ausgeführt, und schlussendlich
de-initialisiert.
Oft erfolgen währen der Initialisierung und De-Initialisierung keine speziellen Aktionen, d.h.
dass diese Schritte oftmals „leer“ sind. Anderseits könnte ein Plug-In z.B. während eines
Lasttests auch eine Verbindung zu einer externen Datenbank aufnehmen. In einem solchen
Fall würde die Verbindung zur Datenbank während der Initialisierung des Plug-Ins aufgebaut,
die Plug-In Daten während der Ausführung des Plug-Ins von der Datenbank gelesen, bzw. in
diese geschrieben, und bei der De-Initialisierung des Plug-Ins die Verbindung zur Datenbank
geschlossen.
Der Zeitpunkt der der Initialisierung + De-Initialisierung, sowie der weitere Zeitpunkt der PlugIn Ausführung lässt sich getrennt d.h. unterschiedlich festlegen. Diese Zeitpunkte sind eng
mit den Daten verbunden, auf welche das Plug-In zugreifen kann und werden darum auch als
Scope bezeichnet.
Folgende Scopes sind möglich:
global: unmittelbar vor oder nach der Ausführung des Lasttest-Programms
user: beim Erzeugen oder beim Beenden eines virtuellen Benutzers
loop: am Anfang oder am Ende jedes ausgeführten Loops
URL: vor oder nach dem Aufruf eines bestimmten oder auch aller URL-Calls
Der gebräuchlichste Scope bei der Initialisierung + De-Initialisierung eines Plug-Ins ist global.
Bei der Ausführung eines Plug-Ins ist der gebräuchlichste Scope jedoch loop oder URL.
Liste der möglichen Initialisierungs-Scopes eines Plug-Ins:
Initialisierungs-Scope
global
user
loop
URL
Plug-In Initialisierung
unmittelbar nach dem Start
des Lasttest-Programms
Vor dem Erzeugen eines jeden
virtuellen Benutzers, bevor
dessen erster Loop ausgeführt
wird.
Vor der Ausführung eins jeden
Loops.
Plug-In De-Initialisierung
unmittelbar vor dem Ende des
Lasttest-Programms
Nach dem Beenden eines jeden
virtuellen Benutzers, nachdem
dessen letzter Loop ausgeführt
wurde.
Nach der Ausführung eines
jeden Loops.
Die De-Initialisierung wird auch
ausgeführt wenn der Loop
fehlschlägt.
Dieser Scope kann nicht zur Initialisierung bzw. De-Initialisierung
von Plug-Ins verwendet werden.
© 2008, 2009, 2010, 2011, 2012 Ingenieurbüro David Fischer AG
Alle Rechte vorbehalten
Seite 5 / 32
Proxy Sniffer V 4.6
Plug-In Entwicklungshandbuch
Liste der möglichen Ausführungs-Scopes eines Plug-Ins:
Ausführungs-Scope
global
Vorher / Nachher
before
global
after
user
before
user
after
loop
before
loop
after
URL
before
URL
after
Plug-In Ausführung
unmittelbar beim Start des LasttestProgramms, jedoch nach der Initialisierung
des Plug-Ins
unmittelbar vor dem Ende des LasttestProgramms, jedoch noch vor der DeInitialisierung des Plug-Ins
Vor dem Erzeugen eines jeden virtuellen
Benutzers, bevor dessen erster Loop
ausgeführt wird
Nach dem Beenden eines jeden virtuellen
Benutzers, nachdem dessen letzter Loop
ausgeführt wurde
Vor der Ausführung eins jeden Loops, eines
jeden Benutzers
Nach der Ausführung eines jeden Loops,
eines jeden Benutzers ¹
Vor der Ausführung eines bestimmten oder
vor jedem URL-Call
Nach der Ausführung eines bestimmten oder
nach jedem URL-Call ²
¹ das Plug-In wird nicht ausgeführt, wenn der entsprechende Loop fehlschlägt. Die DeInitialisierung des Plug-Ins wird jedoch immer durchgeführt.
² das Plug-In wird immer ausgeführt, auch dann wenn beim URL-Call ein Fehler auftritt.
Hinweis: der Import und der Export von GUI-Variablen erfolgt unmittelbar vor bzw. nach der
Ausführung des Plug-Ins.
2.3 Konfiguration von Plug-Ins mittels des GUIs
Sämtliche bereits vorhandenen Plug-Ins befinden sich unter MyTests im Sub-Directory
Plugins. Bei der Konfiguration eines Plug-Ins im GUI (d.h. im Variablen Handler) schaut Proxy
Sniffer in diesem Directory nach, worauf aus einer Liste das entsprechende Plug-In
ausgewählt werden kann. Falls Sie ein neues, bereits vorgefertigtes Plug-In z.B. per E-Mail
erhalten, so müssen Sie dieses zuerst in das Plugins Sub-Directory unter MyTests kopieren,
bevor Sie dieses im GUI verwenden können.
Die Konfiguration eines Plug-Ins, d.h. das Hinzufügen zu einem Lasttest-Programm, geschieht
im GUI über den Variablen-Handler – analog der Definition eines Input-Files oder eines „User
Input Fields“ – mittels des „Add Plug-in …“ Buttons.
Nachdem Sie im GUI das Plug-In ausgewählt haben, müssen sie gegebenenfalls noch die
GUI-Variablen festlegen, welche vom Plug-In importiert oder exportiert werden, sowie den
Initialisierungs- sowie Ausführungs-Scope des Plug-Ins. Bei den meisten Plug-Ins wurden die
Scopes jedoch bereits bei Entwicklung festgelegt und „fest verdrahtet“, so dass diese im GUI
nicht mehr frei gewählt werden können. Eine weitere Eigenschaft eines Plug-Ins, welches
bereits bei der Entwicklung festgelegt wird, ist ob dieses nur ein Mal oder mehrmals
demselben Lasttest-Programm hinzugefügt werden kann. Kann ein Plug-In nur ein Mal
demselben Lasttest-Programm hinzugefügt werden, so sperrte das GUI weitere Versuche das
Plug-In mehrmals zu Konfigurieren.
© 2008, 2009, 2010, 2011, 2012 Ingenieurbüro David Fischer AG
Alle Rechte vorbehalten
Seite 6 / 32
Proxy Sniffer V 4.6
Plug-In Entwicklungshandbuch
Bild: hinzufügen eines Plug-Ins zum Lasttest-Programm:
Bild: festlegen der importierten GUI-Variablen eines Plug-Ins (Beispiel):
© 2008, 2009, 2010, 2011, 2012 Ingenieurbüro David Fischer AG
Alle Rechte vorbehalten
Seite 7 / 32
Proxy Sniffer V 4.6
Plug-In Entwicklungshandbuch
2.4 Lebenszyklus von Plug-Ins nach der Konfiguration
Wurde ein Plug-In über das GUI konfiguriert, so wird dessen kompilierter Java-Code beim
Speichern der Web-Session zusammen mit der Web-Session gemeinsam im selben File
abgespeichert (*.prxdat File der Web-Session). Wird das entsprechende *.prxdat File auf
einen anderen Computer übertragen, so „fliesst“ das Plug-In mit und steht dann auch dort zur
Verfügung.
Bei der Erzeugung eines Lasttests-Programms wird das Plug-In automatisch wieder aus der
Web-Session herauskopiert, wobei eine Kopie des Plug-Ins in demselben Projekt-Navigator
Directory abgelegt wird, indem sich auch das Lasttest-Programm erzeugt wird. Vor der TestAusführung wird dann das Plug-In zusammen mit dem kompilierten Lasttest-Programm
(*.class) gezippt. Danach kann das ZIP-Archiv selbst als Lasttest-Programm ausgeführt
werden, wobei das Plug-In zusammen mit dem Lasttest-Programm an den Exec Agenten
übertragen wird.
Während der Entwicklung eines Plug-Ins kann es vorkommen, dass eine neue Version des
Plug-Ins im Plugins Directory unter MyTests erstellt wird. Das GUI überwacht solche
Vorgänge und „merkt“, wenn eine Web-Session eine veraltete Version eines kompilierten
Plug-Ins enthält. Als Reaktion erscheint im GUI ein Dialog, welche den Benutzer auffordert,
die neue Plug-In Version in die Web-Session zu importieren. Allerdings kann eine neue
Version eines Plug-Ins nur dann erfolgreich importiert werden, wenn dessen Anzahl GUIInput- und GUI-Output-Variablen noch gleich geblieben ist, und diese auch noch die gleiche
Bedeutung haben. Ist dies nicht der Fall, so muss das Plug-In zuerst manuell in der WebSession über den Var Handler gelöscht werden, und danach der Web-Session erneut
hinzugefügt werden.
Nebst der Web-Session überwacht das GUI auch die kompilierten Kopien des Plug-Ins in den
Directories der Lasttest-Programme. Bei einem „refresh“ des Projekt Navigators werden die
Icons von veralteten Plug-Ins mit einem gelben Ausrufezeichen versehen. Durch einen Klick
auf das entsprechende Icon im Projekt Navigator kann dann die aktuelle Version des Plug-Ins
vom Plugins Directory unter MyTests in das Directory des Lasttest-Programms übertragen
werden. Sind die Anzahl GUI-Input- und GUI-Output-Variablen des Plug-Ins sowie deren
Bedeutung noch gleich geblieben, so kann das Lasttest-Programm nun direkt mit dem
überarbeiteten (neuen) Plug-In gestartet werden, ohne dass der Java-Code des LasttestProgramms neu erstellt oder kompiliert werden muss.
Der interne Vergleich, ob ein Plug-In veraltet ist oder nicht, erfolgt nicht über das File-Datum
sondern über die Berechnung einer Prüfsumme über den kompilierten Code des Plug-Ins. Bei
unterschiedlichen Prüfsummen gilt immer diejenige Version als „neu“, welche sich im Plugins
Directory unter MyTests befindet.
Beispiel: veraltete Kopie des Plug-Ins im Lasttest-Programm Directory – Icon enthält gelbes
Ausrufezeichen
© 2008, 2009, 2010, 2011, 2012 Ingenieurbüro David Fischer AG
Alle Rechte vorbehalten
Seite 8 / 32
Proxy Sniffer V 4.6
Plug-In Entwicklungshandbuch
3 Entwicklung eigener Plug-Ins
Bei der Entwicklung eigener Plug-Ins sollte in einem ersten Schritt die Anbindung an die
Laufzeit-Umgebung von Proxy Sniffer vorgenommen werden. Dies geschieht mittels eines
GUI-Assistenten, welcher das Programm-Skelett des Plug-Ins automatisch erzeugt. Danach
ist das Plug-In bereits kompilations-fähig, enthält jedoch noch keine innere Logik welche dem
Kern der Plug-In Funktionalität ausmacht.
In einem zweiten Schritt wird innere Logik dem Plug-In hinzugefügt, wobei dies von Hand
programmiert werden muss. Danach kann das Plug-In im GUI über den Variablen-Handler
einer aufgezeichneten Web-Session hinzugefügt werden.
3.1 Java API Dokumentation
Bei der Programmierung eines Plug-Ins stehen Ihnen die Class-Libraries des Java SDK 5.0
sowie weitere Klassen welche sich im Package dfischer.utils befinden bereits zur Verfügung.
Bei Windows-Systemen können Sie die entsprechende API-Dokumentation von dfischer.utils
über Start  Programme  ProxySniffer  Proxy Sniffer Java API Documentation
einsehen.
Bei Mac OS X Systemen ist die API-Dokumentation von dfischer.utils im folgenden Directory
abgelegt: /Applications/ProxySniffer/doc/javadoc (index.hrml)
Bei der Installation des Proxy Sniffer auf anderen Unix-ähnlichen Betriebssystemen (Solaris,
Linux, …) wird die API-Dokumentation nicht automatisch installiert. Sie können diese jedoch
von folgender URL herunterladen:
http://www.proxy-sniffer.com/download/ProxySnifferJavaDoc.zip
3.2 Verwenden von mehreren Klassen und von externen ClassLibraries
Oft besteht ein Plug-In nur aus einer einzigen Klasse und verwendet selbst keine
externen Libraries. In diesem Fall ist nichts spezielles zu beachten und Sie können
dieses Unterkapitel überspringen.
Benötigen Sie jedoch zur Entwicklung eines Plug-Ins weitere Class-Libraries, wie z.B. ein
Datenbank-Treiber, oder soll das Plug-In aus mehreren Klassen bestehen, so müssen diese
bereits als *.jar Files vorliegen, bevor Sie mit der Entwicklung des Hauptklasse des Plug-Ins
beginnen. Beachten Sie in diesem Zusammenhang auch, dass die Hauptklasse eines Plug-Ins
niemals selbst Bestandteil eines Java-Packages sein darf, und sich selbst auch nicht in einem
jar-Archiv befinden darf.
Sind weitere *.jar Files notwendig, so müssen Sie diese zuerst in das Plugins Subdirectory
unter MyTests kopieren. Danach müssen Sie noch den CLASSPATH des Web Admin GUIs
anpassen. Dies geschieht an folgenden Stellen:
Wählen Sie im Project Navigator Fenster oben rechts das „Setup“ Icon (Menü „Project
Navigator - Java™ Setup and Report Branding“) und ergänzen Sie den CLASSPATH des
Java Compilers sowie des Java Interpreters mit dem Pfaden zu den weiteren *.jar Files.
Bei Windows-Systemen müssen Sie zusätzlich das Flle „Proxy Sniffer Console.lax“ und
gegebenenfalls dessen Varianten „Proxy Sniffer Console (1024 MB).lax“ und „Proxy
Sniffer Console (without local Exec Agent).lax“ von Hand editieren und die Zuweisung an
lax.class.path ergänzen. Danach müssen Sie Proxy Sniffer stoppen und dann wieder neu
starten.
© 2008, 2009, 2010, 2011, 2012 Ingenieurbüro David Fischer AG
Alle Rechte vorbehalten
Seite 9 / 32
Proxy Sniffer V 4.6
Plug-In Entwicklungshandbuch
Bei Unix-ähnlichen Systemen müssen Sie zusätzlich Proxy Sniffer stoppen, danach die
externen *.jar Files dem CLASSPATH des Startup-Scripts hinzufügen, und danach Proxy
Sniffer erneut starten.
Danach können Sie mit der Entwicklung der Haupt-Klasse des Plug-Ins fortfahren.
Bei der (späteren) Ausführung eines Lasttests Plug-Ins auf remote Exec Agenten stehen
Ihnen zwei verschiedene Alternativen zur Verfügung:
a) Entweder zippen Sie das den *.class Code des Plug-Ins mit der kompilierten *.class Code
des Lasttest-Programms und allen weiteren externen *.jar Files zu einem ZIP-Archiv
zusammen und führen das ZIP-Archiv selbst als Lasttest aus. In diesem (empfohlene) Fall
müssen die externen *.jar Files nicht von Hand auf den Exec Agenten installiert werden.
Allerdings müssen Sie die externen *.jar Files zusätzlich auch noch in das Directory des
Lasttest-Programms kopieren, damit Sie das ZIP-Archiv im GUI erstellen können, was
nicht immer ganz praktisch ist.
b) Oder Sie installieren die externen *.jar Files von Hand auf den Exec Agenten, wobei Sie
auf den Exec Agenten zusätzlich auch im File javaSetup.dat den Wert von javaClasspath
ergänzen. Danach müssen Sie die Exec Agenten stoppen und wieder neu starten. In
diesem Fall müssen Sie nur das Plug-In mit der kompilierten Klasse des LasttestProgramms zusammen zippen, jedoch nicht die externen *.jar Files. Auch hier führen Sie
danach das ZIP-Archiv als Lasttest aus. Diese einfachere Variante ist nur dann empfohlen,
wenn die Entwicklung der externen *.jar Files abgeschlossen ist.
© 2008, 2009, 2010, 2011, 2012 Ingenieurbüro David Fischer AG
Alle Rechte vorbehalten
Seite 10 / 32
Proxy Sniffer V 4.6
Plug-In Entwicklungshandbuch
3.3 Erstellen des Programm-Skeletts mit dem GUI-Assistenten
Der GUI-Assistent ist im Project Navigator Plugins Subdirectory unter MyTests zugänglich.
Starten Sie diesen indem Sie im Project Navigator auf dessen Icon klicken:
Hinweis: falls Sie das Proxy Sniffer GUI auf einem Unix-ähnlichen Betriebssystem verwenden,
so müssen Sie gegeben falls das Directory Plugins von Hand erzeugen bevor Sie den GUIAssistenten aufrufen können.
In der Box oben links müssen Sie folgendes eingeben:
Plug-In Class Name: frei wählbarer Name der Java-Klasse des Plug-Ins (ohne *.class
oder *.java Datei-Erweiterung).
Allow Multiple Usage: hier können Sie festlegen, ob das Plug-In im selben LasttestProgramm (bzw. in derselben Web-Session) mehrmals oder nur ein Mal konfiguriert
werden darf.
© 2008, 2009, 2010, 2011, 2012 Ingenieurbüro David Fischer AG
Alle Rechte vorbehalten
Seite 11 / 32
Proxy Sniffer V 4.6
Plug-In Entwicklungshandbuch
Plug-In GUI Label: dies ist die Bezeichnung des Plug-Ins im GUI. Geben Sie hier nur ein
oder zwei Stichwörter ein.
Plug-In Description: dies ist die ausführliche Beschreibung des Plug-Ins welche im GUI
angezeigt wird. Sie können hier auch mehrere Sätze eingeben. Eine HTML-Formatierung
wird jedoch nicht unterstützt. Das einzige Formatierungs-Sequenz welches unterstützt wird
ist „\n“ was einen Zeilenumbruch im dargestellten Text bewirkt.
In der Box oben in der Mitte, welche mit „Plug-In Initialization“ beschriftet ist, können Sie den
Initialisierungs-Scope des Plug-Ins festlegen (siehe auch Kapitel 2.2). Dabei bedeutet
„arbitrary / assigned by GUI“, dass dem Plug-In kein fester Initialisierungs-Scope
vorgegeben wird; d.h. dass dieser später bei der Konfiguration des Plug-Ins im GUI frei
gewählt werden kann. Es wird jedoch empfohlen, diese Option nicht zu verwenden, sondern
sofern möglich immer einen festen Initialisierungs-Scope vorzugeben.
In der Box oben rechts, welche mit „Plug-In Execution“ beschriftet ist, können Sie den
Ausführungs-Scope des Plug-Ins festlegen (siehe auch Kapitel 2.2). Wiederum ist zusätzlich
auch „arbitrary / assigned by GUI“ möglich. Auch hier wird empfohlen einen festen Scope
vorzugeben.
Danach, etwas weiter unten in der Mitte des Fensters, erfolgt die Definition der Plug-in Input
Parameter. Es können bis zu sechs Parameter festgelegt werden, wobei mittels des DropDown Felds „Optional Parameter“ bestimmt werden kann, wie viele Parameter als „PflichtGUI-Variablen“ importiert werden müssen und wie viele Parameter als „optionale GUIVariablen“ importiert werden können. Beachten Sie, dass die Reihenfolge immer so definiert
ist, dass die Definition der „Pflicht-Variablen“ vor der Definition der nachfolgenden „optionale
Variablen“ erfolgen muss. Die Eingabefelder der Plug-In Input-Parameter haben folgende
Bedeutung:
GUI Label: dies ist die Bezeichnung des Parameters im GUI. Geben Sie hier nur ein oder
zwei Stichwörter ein.
local var: dies ist der Name der lokalen Plug-In Variable im automatisch erzeugten Java
Programm-Code des Plug-Ins. Die später konfigurierte GUI-Variable übergibt ihren Wert
an diese lokale Plug-In Variable.
convert to: bestimmt den Datentyp der lokalen Plug-In Variable. Beachten Sie, dass alle
GUI-Variablen des Variablen-Handlers als String dem Plug-In übergeben werden.
„Convert To“ = „int“ bedeutet z:B. in diesem Zusammenhang, dass die importierte GUIVariable in den (lokalen) „int“ Datentyp konvertiert wird.
User Input Field: wird diese Checkbox aktiviert, so wird bei der Konfiguration des Plug-Ins
im GUI gleichzeitig auch noch ein neues „User Input Field“ erzeugt, wobei dessen
Eingabewert (dessen neue GUI-Variable) der lokalen Plug-In Variable zugewiesen wird. Ist
diese Checkbox nicht aktiviert, so muss die GUI-Variable des Input-Parameters bei der
Konfiguration im GUI manuell ausgewählt werden.
default value: hier kann der Default-Wert der lokalen Variable im Java Programm-Code
des Plug-Ins gesetzt werden. Wird kein Default-Wert gesetzt so wird die lokale Variable
wie folgt initialisiert:
Datentyp
String
int
long
float
double
boolean
Initialisierungs-Wert
““ (Leerstring)
-1 (minus eins)
-1 (minus eins)
-1 (minus eins)
-1 (minus eins)
false
© 2008, 2009, 2010, 2011, 2012 Ingenieurbüro David Fischer AG
Alle Rechte vorbehalten
Seite 12 / 32
Proxy Sniffer V 4.6
Plug-In Entwicklungshandbuch
Hinweis: beim Import einer boolean Variablen wird für den Wert true auf das Vorhandensein
des Strings „1“ oder „true“ geprüft.
Im unteren Teil des Fensters erfolgt die Definition der Plug-in Output Parameter. Es können
bis zu vier Output-Parameter gesetzt werden, wobei auch hier einige oder alle optional sein
können. Die Eingabefelder der Output-Parameter haben folgende Bedeutung:
GUI Label: dies ist die Bezeichnung des Parameters im GUI. Geben Sie hier nur ein oder
zwei Stichwörter ein.
local var: dies ist der Name der lokalen Plug-In Variable welche (später) der
entsprechende konfigurierten GUI-Variable zugewiesen wird.
convert from: bestimmt den Datentyp der lokalen Variable im Programm-Code. Beachten
Sie bitte, dass alle lokalen Variablen nach der Ausführung des Plug-Ins als String an die
GUI-Variablen exportiert werden.
default value: hier kann der Default-Wert der lokalen Plug-In Variable gesetzt werden.
Wird kein Default-Wert gesetzt so gelten dieselben Regeln wie bei den Input-Parametern.
Nachdem Sie alle Eingaben vorgenommen haben können Sie unten links im Fenster des GUIAssistenten auf den Knopf „Save Template and Continue“ klicken und danach im neuen
Inhalt desselben Fensters auf den Knopf „Generate Plug-In Code“ klicken.
Dabei wird der Programm-Code des Plug-Ins automatisch – zuerst nur im Memory – erzeugt.
Durch einen Klick auf den Knopf „Save Plug-In Code“ unten links im Fenster wird der Plug-In
Code auf Disk in das Plugins Directory geschrieben. Danach können Sie den Plug-In Code
im Project Navigator ein erstes Mal kompilieren. Um das Plug-In später erneut zu kompilieren
können Sie im Project Navigator das graue Zahnrad-Icon mit dem „j“ verwenden welche rechts
neben dem *.java File-Namen des Plug-Ins angeordnet ist.
Bild: erzeugen des Programm-Skeletts
(*.java Code)
Bild: erneutes
kompilieren des Plug-Ins
© 2008, 2009, 2010, 2011, 2012 Ingenieurbüro David Fischer AG
Alle Rechte vorbehalten
Seite 13 / 32
Proxy Sniffer V 4.6
Plug-In Entwicklungshandbuch
3.4 Programmierung der Plug-In Funktionalität
Vom GUI-Assistenten werden u.a. die Methoden für die Plug-In Initialisierung public void
construct(Object context), für die Plug-In Ausführung public void execute(Object
context) sowie für die Plug-In De-Initialisierung public void deconstruct(Object context)
erzeugt, wobei Sie in der Regel anschliessend nur den Inhalt der Methode execute mit
eigenem Programm-Code ergänzen müssen.
public void construct(Object context)
{
// LoadtestPluginContext pluginContext = (LoadtestPluginContext) context;
}
public void execute(Object context)
{
logVector = new LogVector();
LoadtestPluginContext pluginContext = (LoadtestPluginContext) context;
}
public void deconstruct(Object context)
{
// LoadtestPluginContext pluginContext = (LoadtestPluginContext) context;
}
Je nach Ausführungs-Scope wird die Methode execute vom GUI-Assistenten noch mit
unterschiedlichem Beispiel-Code versehen welcher durch die Marker // vvv --- sample code
--- vvv und // ^^^ --- sample code --- ^^^ umfasst wird. Sie sollten darum bei der
Programmierung diesen Beispiel-Code entfernen.
Der Zugriff aus einem Plug-In auf die Laufzeitumgebung eines Lasttest-Programms erfolgt
mittels der Klasse LoadtestPluginContext, deren aktuelle Instanz allen vorgenannten Plug-In
Methoden übergeben wird. Eine ausführliche Beschreibung der Klasse
LoadtestPluginContext ist in der Proxy Sniffer Java API Documentation enthalten.
© 2008, 2009, 2010, 2011, 2012 Ingenieurbüro David Fischer AG
Alle Rechte vorbehalten
Seite 14 / 32
Proxy Sniffer V 4.6
Plug-In Entwicklungshandbuch
Wichtiger Hinweis: Beachten Sie, dass die einzelnen Methoden der Klasse
LoadtestPluginContext innerhalb eines Plug-Ins unter Umständen keinen gültigen ReturnWert liefern, je nachdem wie der Initialisierungs-Scope und der Ausführungs-Scope des PlugIns gewählt wurde (CONTEXT_SCOPE_GLOBAL, CONTEXT_SCOPE_USER, CONTEXT_SCOPE_LOOP oder
CONTEXT_SCOPE_URL). In der Proxy Sniffer Java API Dokumentation ist darum bei der
Beschreibung der einzelnen Methoden der Klasse LoadtestPluginContext unter „See Also:“
genau festgehalten, für welchen Scope eine Methode gültige Werte während der ProgrammAusführung des Plug-Ins liefert.
Beispiel: die Methode getCookieHandler() liefern nur einen gültigen Return-Wert, wenn der
Scope CONTEXT_SCOPE_LOOP oder CONTEXT_SCOPE_URL ist.
Weitere Hintergrund-Informationen zum Scope sind in diesem Dokument in Kapitel 2.2
enthalten.
Falls der Initialisierungs-Scope oder der Ausführungs-Scope nicht mittels des GUI-Assistenten
festgelegt wurde (Wert „arbitrary / assigned by GUI“ gewählt), so müssen Sie diesen
während derr Laufzeit des Plug-Ins bestimmen. Dazu steht die Methode getContextScope()
zur Verfügung.
© 2008, 2009, 2010, 2011, 2012 Ingenieurbüro David Fischer AG
Alle Rechte vorbehalten
Seite 15 / 32
Proxy Sniffer V 4.6
Plug-In Entwicklungshandbuch
3.4.1 Klasse LoadtestPluginContext
Dieses Unterkapitel enthält nur die Beschreibung einiger ausgewählter Methoden der Klasse
LoadtestPluginContext. Die vollständige Dokumentation dieser Klasse ist in der „Proxy
Sniffer Java API Documentation“ enthalten.
Methode
getContextScope()
getPerformanceData()
getHttpLoadTest()
getHttpTestURL()
getThreadStep()
Beschreibung
Bestimmt den aktuellen Scope zur
Laufzeit. Wird nur dann benötigt wenn
dieser nicht mittels des GUIAssistenten festgelegt wurde.
Erlaubt den Zugriff auf die aktuellen
Messdaten.
Beispiel: mittels
PerformanceData.getPassedLoops()
kann bestimmt werden, wie viele
Loops – gemessen über alle virtuellen
Benutzer – bereits erfolgreich
ausgeführt wurden.
Erlaubt den Zugriff auf weitere Daten
der Laufzeitumgebung – siehe
folgendes Unterkapitel.
Erlaubt Zugriff auf die Daten des
aktuell ausgeführten URL-Calls.
Beispiel: mittels HttpTestURL.
getRequestHeaderObject().appendHe
aderField() kann z.B. dem URL Call
vor dessen Ausführung ein
zusätzliches HTTP Request Header
Field hinzugefügt werden.
Gibt den Index des aktuell
ausgeführten URL-Calls aus.
zulässige Scopes
alle Scopes
alle Scopes
alle Scopes
CONTEXT_SCOPE_URL
CONTEXT_SCOPE_URL
Beispiel 1: der Index kann als InputParameter bei der Methode
PerformanceData.
getPerformanceDataRecord()
verwendet werden, um auf weitere,
detaillierte statistische Messdaten des
URLs zuzugreifen.
setContinueInnerLoopFlag()
setBreakInnerLoopFlag()
markUrlAsFailed(<Text>)
Beispiel 2: der Index kann als InputParameter von PerformanceData.
getPageInfoTextOfUrl() verwendet
werden, um den Text des zum URL
gehörenden Page Breaks zu ermitteln.
Erzwingt innerhalb eines "Inner Loops"
den direkten Sprung zurück an den
Anfang des "Inner Loops".
Erzwingt innerhalb eines "Inner Loops"
dass dieser sofort verlassen wird.
Verwandelt einen erfolgreich
durchgeführten URL-Call in einen
schweren (roten) Fehler.
© 2008, 2009, 2010, 2011, 2012 Ingenieurbüro David Fischer AG
Alle Rechte vorbehalten
CONTEXT_SCOPE_URL
CONTEXT_SCOPE_URL
CONTEXT_SCOPE_URL
Seite 16 / 32
Proxy Sniffer V 4.6
Plug-In Entwicklungshandbuch
3.4.2 Klasse HttpLoadTest
Dieses Unterkapitel enthält nur die Beschreibung einiger ausgewählter Methoden der Klasse
HttpLoadTest. Die vollständige Dokumentation dieser Klasse ist in der „Proxy Sniffer Java
API Documentation“ enthalten.
Methode
contentToDiskFile()
getClusterMemberLocalId()
triggerAbort()
Beschreibung
Schreibt den Inhalt eines ausgeführten URL Calls (HTTP
response content) als File auf Disk.
Gibt bei einem Cluster-Job die Nummer des entsprechenden
Cluster-Members (Exec Agenten) aus. Der erste Cluster
Member hat die Nummer=0, der zweite die Nummer=1 usw.
Da bei einem Cluster-Job dasselbe Plug-In parallel auf
sämtlichen Cluster-Member abläuft kann es unter Umständen
sinnvoll sein, gewisse Aktionen des Plug-Ins nur an einen
bestimmten Cluster Member zu binden (z.B. an Member
Nummer 0).
Führt den vorzeitigen Abbruch des Lasttest-Programms
herbei, wobei die bereits gesammelten statistischen Daten
nicht verloren gehen (das *.prxdat File wird erzeugt).
© 2008, 2009, 2010, 2011, 2012 Ingenieurbüro David Fischer AG
Alle Rechte vorbehalten
Seite 17 / 32
Proxy Sniffer V 4.6
Plug-In Entwicklungshandbuch
3.4.3 Spezielle Hinweise zur Laufzeitumgebung
3.4.3.1 Debug-Output während der Plug-In Ausführung
Innerhalb der Plug-In Methode execute sollte der Debug-Output niemals mit
System.out.println() geschrieben werden, da sonst im Log-File des Lasttest-Jobs ein
verwürfelter Mix des Outputs von verschiedenen Loops der virtuellen Benutzern entsteht.
Verwenden Sie darum in dieser Methode anstelle dessen immer logVector.log().
Bei den Methoden construct und deconstruct ist dies nicht möglich. Hier können Sie nur
System.out.println() verwenden.
Um einen vollständigen Debug-Output des Lasttest-Programms inkl. des Debug-Outputs des
Plug-Ins zu erhalten müssen Sie beim Starten des Lasttests im GUI Menu „Project Navigator Execute Load Test“ das Feld „Debug Options“ auf „debug loops (including var handler)“
setzen. Bei der späteren Ausführung eines realen Lasttests sollten sie diese Option dann
wieder auf „none – recommended“ setzen. Der Debug-Output wird in das *.out File des
entsprechenden Lasttest-Jobs geschrieben. Erfolgt ein Programm-Absturz während eines
Lasttests aufgrund einer fehlerhaften Plug-In Programmierung, so wird dessen Output in das
*.err File des entsprechenden Lasttest-Jobs geschrieben.
3.4.3.2 Initialisierung eines Plug-Ins mittels importierten GUI-Variablen
Die importierten GUI-Variablen eines Plug-Ins werden unmittelbar (jedes Mal) vor dessen
Ausführung dem Plug-In übergeben – d.h. unmittelbar bevor die Methode execute im Plug-In
aufgerufen wird. Nun kann es aber sein, dass dem Plug-In eigentlich schon eine GUI-Variable
übergeben werden sollte wenn dieses Initialisiert wird, d.h. beim Aufruf der Methode
construct. Das wird jedoch nicht unterstützt.
Als Workaround muss in diesem Fall die Initialisierung des Plug-Ins nach dem „Lazy-Prinzip“
erfolgen. D.h. die Methode construct führt keine Initialisierung durch. Anstelle dessen wird bei
jedem Aufruf der Methode execute zuerst geprüft, ob das Plug-In bereits initialisiert wurde.
Beim ersten Aufruf ist dies noch nicht der Fall und die Initialisierung des Plug-Ins wird mittels
der GUI-Variable(n) ausgeführt. Bei allen nachfolgenden Aufrufen von execute wird dann die
Initialisierung übersprungen. Das folgende Code-Fragment illustriert dies:
[...]
/**
* Load test add-on module.
*/
public class TestPlugin implements LoadtestPluginInterface
{
private String vInitialParameter = ""; // input parameter #1
private int vNormalInputParameter = -1; // input parameter #2
private boolean pluginInitialized = false;
private String vOutputParam = "";
// output parameter #1
private LogVector logVector = null;
// internal log vector
[...]
public void construct(Object context)
{
}
[...]
public void execute(Object context)
{
logVector = new LogVector();
LoadtestPluginContext pluginContext = (LoadtestPluginContext) context;
© 2008, 2009, 2010, 2011, 2012 Ingenieurbüro David Fischer AG
Alle Rechte vorbehalten
Seite 18 / 32
Proxy Sniffer V 4.6
Plug-In Entwicklungshandbuch
if (!pluginInitialized)
{
// initialize plug-in by using parameter #1
doInitialize(vInitialParameter);
pluginInitialized = true;
}
[...]
}
[...]
3.4.3.3 Extrahieren von Daten aus der HTTP-Response von URL-Calls
Falls Sie Daten aus dem HTTP Response Header oder aus dem HTTP Response Content
eines URL-Calls extrahieren möchten, so hat das Plug-In den Ausführungs-Scope URL /
after. Dabei müssen Sie jedoch bei der Programmierung von execute beachten, dass ein
solches Plug-In auch ausgeführt wird, wenn der URL-Call fehlschlägt. Zum Beispiel dann,
wenn ein Timeout auftritt und darum gar keine Response-Daten empfangen wurden, oder
auch z.B. dann, wenn anstelle eines 200 (OK) HTTP Response Codes ein 500 (Internal
Server Error) Response Code vom Web-Server zurückgegeben wird.
Damit der Program-Code des Plug-Ins in einem solchen Fall nicht „abstürzt“ und das ganze
Lasttest-Programm „mit nach unten reisst“ müssen Sie darum zuerst prüfen, ob überhaupt
eine gültige Server-Antwort vorliegt – bevor Daten aus der HTTP-Response extrahiert werden.
Um dies zu tun steht in der Klasse LoadtestPluginContext die Methode urlPassed() zur
Verfügung. Diese liefert nur den Wert true zurück, wenn während eines Lasttests bei diesem
URL-Call kein Fehler aufgetreten ist – entsprechend der Konfiguration des GUI-Menüs „HTTP
Response Verification“. „Kein Fehler“ bedeutet:
Es wurde beim URL-Call der korrekte HTTP Response Code empfangen
Die Antwort enthält den korrekten MIME-Type (z.B. TEXT/HTML)
Die Überprüfung des empfangenen Daten-Inhalts aufgrund dessen Grösse oder
aufgrund eines gefunden Text-Fragments verlief ebenfalls erfolgreich
Das nachfolgende Programm-Fragment illustriert den sicheren Zugriff auf den empfangenen
Dateninhalt eines URL-Calls:
public void execute(Object context)
{
LoadtestPluginContext pluginContext = (LoadtestPluginContext) context;
if (pluginContext.urlPassed())
{
HttpTestURL httpTestURL = pluginContext.getHttpTestURL();
String content = httpTestURL.getContentString();
[...] // Weiterverarbeitung des empfangenen Daten-Inhalts
}
[...]
}
© 2008, 2009, 2010, 2011, 2012 Ingenieurbüro David Fischer AG
Alle Rechte vorbehalten
Seite 19 / 32
Proxy Sniffer V 4.6
Plug-In Entwicklungshandbuch
3.4.3.4 Ausführen von Plug-Ins am Ende eines Loops
Beachten Sie, dass ein Plug-In am Ende eines Loops nicht ausgeführt wird, wenn bei einem
URL-Call innerhalb eines Loops ein Fehler auftritt, und dadurch der ganze Loop fehlschlägt.
D.h. wenn ein Fehler auftritt und das Plug-In den Ausführungs-Scope loop / after hat, so wird
die Plug-In Methode execute nicht ausgeführt.
Falls das Plug-In jedoch (auch / zusätzlich) den Initialisierungs-Scope loop hat, so wird in
jedem Fall die Plug-In Methode deconstruct aufgerufen. Dies geschieht bei diesem
Initialisierungs-Scope immer am Ende eines jeden Loops - unabhängig davon, ob ein Fehler
im entsprechenden Loop auftrat oder nicht.
Dabei wird der Methode deconstruct des Plug-Ins immer eine aktuelle Instanz der Klasse
LoadtestPluginContext übergeben. Mittels der Methode loopPassed() können Sie nun
innerhalb von deconstruct feststellen, ob ein Loop fehlschlug oder nicht. Weiterhin erhalten
Sie – nur bei einem fehlgeschlagenen Loop – mittels der Methode getHttpTestURL() Zugriff
auf denjenigen URL-Call, welcher den Fehler ausgelöst hat.
3.4.3.5 Plug-Ins bei Cluster-Jobs
Bei Cluster-Jobs wird ein Plug-In parallel in allen entsprechenden Exec Agenten des Clusters
ausgeführt.
Falls Sie besondere Aktionen durchführen möchten – welche nur ein Mal über den ganzen
Cluster-Job gesehen ausgeführt werden sollen, so müssen Sie das Plug-In an genau einen
Exec Agenten des Clusters binden. Dazu können Sie im Plug-In die ID (Nummer) des Exec
Agenten mittels HttpLoadTest. getClusterMemberLocalId() abfragen.
Diese Methode liefert für den ersten Cluster Member den Wert 0 zurück, für den zweiten
Cluster Member den Wert 1, … usw.
Da ein Cluster theoretisch auch nur aus einem einzigen Exec Agenten bestehen kann, sollte
das Plug-In an den ersten Cluster-Member (ID = 0) gebunden werden, damit dieses auch
immer ausgeführt wird. Bei normalen Exec Agent Jobs, d.h. wenn der Lasttest nicht von einem
Cluster ausgeführt wird, liefert getClusterMemberLocalId() den Wert -1 (minus Eins) zurück.
Das nachfolgende Programm-Fragment zeigt, wie eine Aktion pro Job immer nur von einem
Exec Agenten ausgeführt wird, egal ob es sich um einen gewöhnlichen Exec Agent Job oder
um einen Cluster Job handelt:
public void execute(Object context)
{
LoadtestPluginContext pluginContext = (LoadtestPluginContext) context;
HttpLoadTest httpLoadTest = pluginContext.getHttpLoadTest();
int clusterMemberLocalId = httpLoadTest.getClusterMemberLocalId();
if ((clusterMemberLocalId == -1) || (clusterMemberLocalId == 0))
{
// Aktion wird nur auf einem Exec Agenten ausgeführt
[...]
}
}
© 2008, 2009, 2010, 2011, 2012 Ingenieurbüro David Fischer AG
Alle Rechte vorbehalten
Seite 20 / 32
Proxy Sniffer V 4.6
Plug-In Entwicklungshandbuch
3.4.3.6 Integrieren von zusätzlichen (externen) Messdaten
Mittels Plug-Ins ist es auch möglich, während eines Lasttests zusätzlich Messdaten zu
sammeln und diese später als XY-Diagramme im GUI anzuzeigen (im Menü „Load Test Result
Detail - Statistics and Diagrams“).
Dabei spielt es keine Rolle, ob die Messdaten von internen Datenquellen – z.B. extrahiert aus
URL-Antworten des Lasttest-Programms – oder von externen Datenquellen stammen. Die
einzige Bedingung ist, dass solche zusätzliche Messdaten während der Ausführungsdauer
des Lasttest-Programms zur Verfügung stehen. Es lassen sich so – eine geeignete
Programmierung vorausgesetzt – auch Messdaten von externen Systemen im LasttestResultat (*.prxres File) integrieren.
Der spätest mögliche Zeitpunkt zur Integration von zusätzlichen Messdaten ist kurz vor dem
Programm-Ende des Lasttest-Programms, d.h. dann wenn alle virtuellen Benutzer ihren
letzten Loop abgeschlossen haben. Der entsprechende Plug-In Initialisierungs-Scope ist dabei
global, und das Hinzufügen der Messdaten erfolgt in der Plug-In Methode deconstruct.
Das Sammeln von zusätzlichen Messdaten kann jederzeit während des Lasttests erfolgen,
wobei pro Messgrösse bzw. pro Messreihe zuerst eine Instanz der Klasse
dfischer.utils.DataCollectionSequence erzeugt werden muss. Im Konstruktor dieser Klasse
erfolgen die Angaben zur Beschriftung des entsprechenden Mess-Diagramms im GUI. Die
Konstruktor-Parameter sind:
- sequenceId: frei wählbare, eindeutige Nummer der Datensequenz
- diagramTitle: Titel des Diagramms im GUI
- diagramSubTitle: Sub-Titel des Diagramms im GUI
- yAxisLabel: Beschriftung der Y-Achse im Diagramm
- sequenceContext: hat hier keine Bedeutung, als Wert sollte null übergeben werden
Nachdem die Instanz von DataCollectionSequence erzeugt wurde, können die einzelnen
Messwerte der Messgrösse mittels wiederholten Aufrufen der Methode
addItem(DataCollectionFloatItem floatItem) hinzugefügt werden. Dazu muss pro
hinzugefügtem Messwert zuvor eine Instanz der Klasse DataCollectionFloatItem erzeugt
werden, bevor addItem aufgerufen werden kann. Der Konstruktor von
DataCollectionFloatItem enthält zwei Parameter:
- timeStamp: Zeitpunkt des Messwerts (verstrichene Millisekunden seit 1970). Soll der
augenblickliche Zeitpunkt verwendet werden so kann System.currentTimeMillis()
verwendet werden.
- floatValue: Grösse des Messwerts.
Hinweis: beachten Sie, dass Messwerte welchen einen Zeitpunkt (timeStamp) vor dem Start
des Lasttest-Programms enthalten im GUI-Diagramm nicht dargestellt werden. Falls Daten
von einem externen System inklusive dessen externen timeStamps importiert werden, so
sollte im Plug-In zuerst die Differenz der System-Zeit zwischen dem lokalen System und dem
externen System ermittelt werden. Diese Zeit-Differenz kann danach als Korrekturwert für den
timeStamp dienen.
Nachdem alle Daten gesammelt wurden, müssen diese noch dem Lasttest-Resultat
hinzugefügt werden. Dies geschieht mittels der Methode
PerformanceData .addDataCollectionSequence(DataCollectionSequence), wobei diese
Methode pro Messgrösse, d.h. pro Instanz von DataCollectionSequence, wiederholt
aufgerufen wird. Den Zugriff auf die aktuelle Instanz von PerformanceData erhalten Sie über
den Plug-In Context (Instanz der Klasse LoadtestPluginContext welche dem Plug-In in den
Methoden construct, execute und deconstruct übergeben wird).
© 2008, 2009, 2010, 2011, 2012 Ingenieurbüro David Fischer AG
Alle Rechte vorbehalten
Seite 21 / 32
Proxy Sniffer V 4.6
Plug-In Entwicklungshandbuch
Beispiel 1: Das nachfolgende, einfache Beispiel zeigt, wie die "Zeit bis zum Empfang des
ersten Bytes eines HTTP-Response-Headers eines URL-Aufrufs" von einem Plug-In extrahiert
und als zusätzliches Diagramm dem Lasttest-Resultat hinzugefügt wird.
[...]
import dfischer.utils.DataCollectionSequence;
import dfischer.utils.DataCollectionFloatItem;
/**
* Load test add-on module.
*/
public class AdditionalDataExample implements LoadtestPluginInterface
{
private LogVector logVector = null;
private DataCollectionSequence simpleSequence = new DataCollectionSequence(1,
"Wait Time for Receiving the first Byte of Response", "", "Milliseconds", null);
[...]
/**
* Execute plug-in after URL call.
*
* Intrinsic plug-in implementation.
*/
public void execute(Object context)
{
logVector = new LogVector();
LoadtestPluginContext pluginContext = (LoadtestPluginContext) context;
HttpTestURL httpTestURL = pluginContext.getHttpTestURL();
if (pluginContext.urlPassed())
{
DataCollectionFloatItem waitTimeForFirstByteItem = new
DataCollectionFloatItem(System.currentTimeMillis(),
httpTestURL.getResponseHeaderWaitTime());
simpleSequence.addItem(waitTimeForFirstByteItem);
}
}
[...]
/**
* Finalize plug-in at end of load test.
*/
public void deconstruct(Object context)
{
LoadtestPluginContext pluginContext = (LoadtestPluginContext) context;
simpleSequence.addClusterOption(DataCollectionSequence.
CLUSTER_OPTION_MERGE_FLOAT_ITEMS_TO_SUM, "Merged Cluster Data");
pluginContext.getPerformanceData().addDataCollectionSequence(simpleSequence);
}
[...]
}
// end of class
Das nachfolgende Bild zeigt, wie die zusätzlichen Messdaten im GUI dargestellt werden.
Wurden mehr als eine Messgrösse dem Lasttest-Resultat hinzugefügt, so erfolgt die Auswahl
© 2008, 2009, 2010, 2011, 2012 Ingenieurbüro David Fischer AG
Alle Rechte vorbehalten
Seite 22 / 32
Proxy Sniffer V 4.6
Plug-In Entwicklungshandbuch
der entsprechenden Messgrösse mittels der Dropdown-Liste oberhalb des Diagramms. Alle
Diagramme der zusätzlichen Messdaten werden auch in den PDF-Report übernommen.
Hinweis:
Falls Sie die X-Achse eines Diagramms auch frei wählen möchten, so müssen Sie die
gemessenen Daten mittels eines DataCollectionYZFloatItem (anstelle eines
DataCollectionFloatItem) der DataCollectionSequence hinzufügen. Bei einem
DataCollectionYZFloatItem hat jeder Messwert drei Dimensionen: 1. Der Zeitstempel (XDimension, vorgegeben), 2. Der erste Wert (Y-Dimension), 3. Der zweite Wert (Z-Dimension).
Infolgedessen können im GUI für eine solche DataCollectionSequence drei verschiedene
Diagramme angezeigt werden: XY-Diagramm, XZ- Diagramm und YZ- Diagramm, wobei hier
hauptsächlich die Ansicht des YZ-Diagramms von Bedeutung ist, da nur dieses beide Werte
gleichzeitig anzeigt.
Über den dazu geeigneten Konstruktor von DataCollectionSequence können Sie die beiden
freien Achsen des Diagramms beschriften, und auch festlegen, ob im GUI alle drei
Diagramme angezeigt werden sollen, oder nur das YZ- Diagramm.
© 2008, 2009, 2010, 2011, 2012 Ingenieurbüro David Fischer AG
Alle Rechte vorbehalten
Seite 23 / 32
Proxy Sniffer V 4.6
Plug-In Entwicklungshandbuch
Beispiel 2: Das nachfolgende, etwas komplexere Beispiel zeigt, wie mittels eines lokalen
Threads im Plug-In externe Messdaten integriert werden. Das Plug-In hat den InitialisierungsScope global. Der lokale Thread wird beim Starten des Lasttest-Programms in der Plug-In
Methode construct gestartet und am Ende des Lasttest-Programms in der Plug-In Methode
deconstruct wieder gestoppt. Innerhalb der Thread-Methode run() erfolgt das Sammeln der
Messdaten. Nachdem der lokale Thread (wahrscheinlich) gestoppt wurde, werden gleich
danach die Messdaten dem Lasttest-Resultat hinzugefügt. Innerhalb von deconstruct wird
nur maximal 10 Sekunden das Ende des Threads gewartet, damit das Programm-Ende des
Lasttest-Programms nicht zu stark verzögert wird. Falls der lokale Thread dennoch
weiterlaufen würde, so ist dies kein Problem, da danach das Lasttest-Programm sich selbst
beendet – ausserhalb des Plug-Ins mit System.Exit() – was zu einem Exit der Java Virtual
Maschine des Lasttest-Jobs führt.
[...]
import dfischer.utils.DataCollectionSequence;
import dfischer.utils.DataCollectionFloatItem;
/**
* Load test add-on module.
*/
public class ExternalMeasuringData extends Thread implements LoadtestPluginInterface
{
private LogVector logVector = null;
private PerformanceData performanceData = null;
// load test result
private Thread dataCollectThread = null;
// data collecting thread
private DataCollectionSequence dataCollectionSequence = null; // external data
[...]
/**
* Initialize plug-in at start of load test.
*/
public void construct(Object context)
{
LoadtestPluginContext pluginContext = (LoadtestPluginContext) context;
performanceData = pluginContext.getPerformanceData();
// start data collecting thread
dataCollectThread = new Thread(this);
dataCollectThread.start();
}
/**
* Thread - used to collect external measuring data
*/
public void run()
{
// create data structure for external data and define GUI diagram settings
dataCollectionSequence = new DataCollectionSequence(1, "Database Calls", "",
"Calls per Second", null);
// collect external measuring data in a loop
while (!isInterrupted())
{
// get external data snapshot
float externalValue = 10.0f; // <<< actual value of external data
// [ add your own code here to
//
accumulate external data ]
// add external data snapshot to data collection
DataCollectionFloatItem dataItem =
new DataCollectionFloatItem(System.currentTimeMillis(), externalValue);
dataCollectionSequence.addItem(dataItem);
© 2008, 2009, 2010, 2011, 2012 Ingenieurbüro David Fischer AG
Alle Rechte vorbehalten
Seite 24 / 32
Proxy Sniffer V 4.6
Plug-In Entwicklungshandbuch
// sleep for one sampling interval. The sampling interval is
// arbitrary configurable on the GUI when starting the load test
try
{
sleep(performanceData.getSamplingInterval() * 1000);
}
catch (InterruptedException e)
{
interrupt();
}
}
}
/**
* Execute plug-in at start of load test.
*
* Intrinsic plug-in implementation.
*/
public void execute(Object context)
// no action in this method
{
}
/**
* Finalize plug-in at end of load test.
*/
public void deconstruct(Object context)
{
// stop data collecting thread
dataCollectThread.interrupt();
try
{
dataCollectThread.join(10000);
}
catch (InterruptedException e) {}
// add external measuring data to load test result
performanceData.addDataCollectionSequence(dataCollectionSequence);
}
[...]
}
// end of class
Hinweis: falls die zusätzlich Messdaten nur aus URL-Antworten gewonnen werden, oder wenn
zusätzlich Messdaten nur aufgrund von bereits vorhandenen Proxy Sniffer Messwerte
berechnet werden, so ist kein lokaler Thread notwendig.
© 2008, 2009, 2010, 2011, 2012 Ingenieurbüro David Fischer AG
Alle Rechte vorbehalten
Seite 25 / 32
Proxy Sniffer V 4.6
Plug-In Entwicklungshandbuch
3.4.3.7 Versenden von E-Mails mittels SMTP
Mittels der Klasse dfischer.utils.SmtpMessage können Sie E-Mails aus Plug-Ins versenden.
Dies bedingt jedoch, dass Sie über einen SMTP E-Mail Server verfügen, welcher das
Einspeisen von E-Mails erlaubt. Da wegen Sicherheits-Auflagen E-Mail Server oft so
konfiguriert sind, dass diese eine Einspeisung von E-Mails von anonymen Benützern nicht
zulassen, können Sie zur Authentisierung gegenüber dem E-Mail auch einen Benutzernamen
und ein Passwort verwenden.
Das nachfolgende Programm-Fragment zeigt ein Beispiel wie ein E-Mail im HTML-Format an
einem SMTP-Relay-Server gesendet werden kann:
String htmlMessage = "<body><html><ul><li>first</li><li>second</li></ul>
<font color=\"blue\">blue sea</font></body></html>";
SmtpMessage smtpMessage = new SmtpMessage(smtpHost);
smtpMessage.setSmtpAuthentication(authUsername, authPassword);
smtpMessage.markHtmlMessage();
smtpMessage.setDebug();
smtpMessage.send(from, to, subject, htmlMessage);
System.out.println("--- waiting for completion ---");
smtpMessage.waitForSendCompletion();
// debug message transfer
String[] debugOutput = smtpMessage.getDebugOutput();
for (int x = 0; x < debugOutput.length; x++)
System.out.println(debugOutput[x]);
3.4.3.8 Umgang mit Zeitzonen und Datums-Berechnungen
Um Datums-Berechnungen in Plug-Ins durchzuführen kann wie bei Java üblich die Klasse
java.util.GregorianCalendar verwendet werden. Diese sollte jedoch mit der in Proxy Sniffer
konfigurierten Zeitzone initialisiert werden, damit die späteren Berechnungen korrekt
verlaufen. Verwenden Sie darum die Klasse
dfischer.utils.ZoneTime.getGregorianCalendar() um das aktuelle Datum in der
konfigurierten Proxy Sniffer Zeitzone zu erhalten.
Beispiel:
[...]
import java.util.Calendar;
import java.util.GregorianCalendar;
import dfischer.utils.ZoneTime;
[...]
// get current date and time in configured Proxy Sniffer time zone
GregorianCalendar cal = ZoneTime.getGregorianCalendar();
// add 3 days to current date
cal.add(Calendar.DAY_OF_YEAR, 3);
// get future date
int futureDay = cal.get(Calendar.DAY_OF_MONTH);
int futureMonth = cal.get(Calendar.MONTH);
int futureYear = cal.get(Calendar.YEAR);
© 2008, 2009, 2010, 2011, 2012 Ingenieurbüro David Fischer AG
// value range 1..31
// value range 0..11, 0 = January
Alle Rechte vorbehalten
Seite 26 / 32
Proxy Sniffer V 4.6
Plug-In Entwicklungshandbuch
3.4.3.9 Erzeugen von Plug-In spezifischen Fehler-Arten
Plug-Ins, welche an ein oder an alle URLs gebunden sind, können nach einem URL-Aufruf
einen an sich erfolgreichen Aufruf des URLs auch in einen "roten" Fehler überführen, wobei
der aktuelle Loop des simulieren Benutzers abgebrochen wird, und der simulierte Benutzer
nun mit dem nächsten Loop fortfährt.
Beispiel:
/**
* Execute plug-in after URL call.
*
* Intrinsic plug-in implementation.
*/
public void execute(Object context)
{
logVector = new LogVector();
LoadtestPluginContext pluginContext = (LoadtestPluginContext) context;
if (firstCall)
{
// Definition von Plug-In spezifischen Fehler-Arten
pluginContext.getPerformanceData().setErrorStatusTypeTranslation(HttpTestURL
.STATUS_TYPE_PLUGIN_ERROR_CODE_1, "No Connection to External Service");
pluginContext.getPerformanceData().setErrorStatusTypeTranslation(HttpTestURL
.STATUS_TYPE_PLUGIN_ERROR_CODE_7, "Internal Plug-In Error");
firstCall = false;
}
if (...)
{
// Auslösen eines Fehlers
// report plug-in specific "red" error and terminate current loop of
// simulated user -> continue with next loop of simulated user
pluginContext.markUrlAsFailed(HttpTestURL.STATUS_TYPE_PLUGIN_ERROR_CODE_1,
"Plug-In Error Message Text A");
}
if (...)
{
// Auslösen eines Fehlers
// report plug-in specific "red" error and terminate current loop of
// simulated user -> continue with next loop of simulated user
pluginContext.markUrlAsFailed(HttpTestURL.STATUS_TYPE_PLUGIN_ERROR_CODE_7,
"Plug-In Error Message Text B");
}
}
Insgesamt können bis zu 10 verschiedene Plug-In spezifischen Fehler-Arten definiert werden
(STATUS_TYPE_PLUGIN_ERROR_CODE_0 - STATUS_TYPE_PLUGIN_ERROR_CODE_9)
und beim Auslösen jedes Fehlers kann zusätzlich noch eine eigene Fehlermeldung
angegeben werden.
© 2008, 2009, 2010, 2011, 2012 Ingenieurbüro David Fischer AG
Alle Rechte vorbehalten
Seite 27 / 32
Proxy Sniffer V 4.6
Plug-In Entwicklungshandbuch
Die vom Plug-Ins ausgelösten Fehler werden in den "normalen" Detail-Diagrammen und Daten der Lasttest-Resultate dargestellt (zusammen mit allen anderen gemessenen Fehlern):
© 2008, 2009, 2010, 2011, 2012 Ingenieurbüro David Fischer AG
Alle Rechte vorbehalten
Seite 28 / 32
Proxy Sniffer V 4.6
Plug-In Entwicklungshandbuch
3.4.4 Performante Plug-In Programmierung
Die Ausführungs-Zeitdauer eines Plug-Ins selbst beeinflusst die gemessenen Antwortzeiten
nicht. Dennoch benötigt ein Plug-In lokale CPU-Zeit zur Ausführung, was dazu führen kann,
dass weniger virtuelle Benutzer vom Exec Agenten simuliert werden können – da dessen CPU
früher überlastet wird (siehe auch „Leitfaden zum erfolgreichen Durchführen von Lasttests“,
Kapitel 4 – Punkt 4).
3.4.4.1 Vorberechnen von Ergebnissen
Um den Programm-Code eines Plug-Ins möglichst „CPU-schonend“ zu gestalten sollten vor
allem repetitiv ausgeführte Programm-Abschnitte – welche jeweils bei wiederholten Aufrufen
von execute zum gleichen Ergebnis führen – so modifiziert werden, dass deren Ergebnis nur
beim ersten Mal berechnet wird und dabei dieses zusätzlich lokal im Plug-In abgespeichert
wird. Bei allen weiteren Aufrufen desselben Programm-Abschnitts kann nun direkt auf das
Ergebnis zugegriffen werden, ohne dass die Berechnung von neuem erfolgen muss.
Um eine solche Optimierung ohne grossen Aufwand zu realisieren sollte bevorzugt auf die
Klasse java.util.HashMap zurückgegriffen werden. Dabei stellt die fehlende interne
Synchronisierung dieser Klasse kein Hindernis dar, da die Ausführung von Plug-In-Instanzen
bereits durch Proxy Sniffer synchronisiert wird.
Beispiel:
Bei einem jedem URL-Aufruf soll zusätzlich die Web-Page (d.h. der Text des Page-Breaks)
bestimmt werden.
Der nicht-optimierte Code sieht zuerst so aus:
public void execute(Object context)
{
LoadtestPluginContext pluginContext = (LoadtestPluginContext) context;
PerformanceData performanceData = pluginContext.getPerformanceData();
int threadStep = pluginContext.getThreadStep();
String pageName = performanceData.getPageInfoTextOfUrl(threadStep);
[...]
D.h. dass jedes Mal aufgrund des aktuellen URL-Indexes (threadStep) der Text des PageBreaks neu bestimmt wird. Dies ist insofern von Bedeutung, da bei Proxy Sniffer nur das
Schreiben bzw. das Sammeln von Messdaten bereits CPU-optimiert ist, jedoch nicht das
Auslesen von Messergebnissen.
Um dies nun zu Optimieren wird das Ergebnis nur ein Mal berechnet und in einer HashMap
abgelegt. Der optimierte Code sieht nun so aus:
import java.util.HashMap;
public class TestPlugin implements LoadtestPluginInterface
{
HashMap pageInfoMap = new HashMap();
[...]
public void execute(Object context)
{
LoadtestPluginContext pluginContext = (LoadtestPluginContext) context;
PerformanceData performanceData = pluginContext.getPerformanceData();
int threadStep = pluginContext.getThreadStep();
String pageName;
Object o = pageInfoMap.get(new Integer(threadStep));
If (o != null)
© 2008, 2009, 2010, 2011, 2012 Ingenieurbüro David Fischer AG
Alle Rechte vorbehalten
Seite 29 / 32
Proxy Sniffer V 4.6
Plug-In Entwicklungshandbuch
pageName = (String) o;
// Zugriff auf vorberechnetes Ergebnis
else
{
// Ergebnis ein erstes Mal berechnen und abspeichern
pageName = performanceData.getPageInfoTextOfUrl(threadStep);
pageInfoMap.put(new Integer(threadStep), pageName);
}
[...]
Bedenken Sie, dass die nur ein Beispiel ist. Grundsätzlich können Sie diese Vorgehensweise
bei jeder Programm-Aufgabe anwenden, bei der sich Ergebnisse von repetitiv ausgeführten
Programm-Abschnitten vorberechnen lassen. Es lohnt sich oft etwas darüber nachzudenken
was vorberechnet werden kann und was nicht.
3.4.4.2 Disk und Netzwerk I/O-Operationen
I/O-Operationen benötigen in der Regel nicht so viel CPU, doch erfolgen diese Vorgänge
Betriebssystem-intern mittels asynchron verarbeiteten Events, was je nach Volumen der I/OOperationen dazu führen kann, dass das gesamte Betriebssystem langsamer wird und bei
(fast) allen Aufgaben mehr Durchlaufszeit zu Ausführung einzelner System-Routinen benötigt.
Um dies zu optimieren sollten I/O-Verbindungen innerhalb der Methode execute nicht immer
wieder geöffnet und gleich wieder geschlossen werden. Vielmehr sollten diese nur beim
ersten Aufruf von execute – oder alternativ in der Methode construct – geöffnet werden.
Danach sollte die Verbindung zum weiteren Datenaustausch dauernd offen bleiben. Das
Schliessen der Verbindung kann dann später in der Methode deconstruct erfolgen.
Bei Disk I/O-Operationen welche ein File während eines Lasttests erzeugen kann es auch
sinnvoll sein, die File-Daten zuerst nur im Speicher zu sammeln (z.B. mittels
java.util.ArrayList oder mittels java.io.PrintWriter(java.io.ByteArrayOutputStream)), und
erst in der Methode deconstruct „in einem Rutsch“ auf Disk zu schreiben. Dies geht jedoch
nur, falls die Daten nicht zu gross werden. Als Faustregel gilt, dass ein Plug-In insgesamt nicht
mehr als 50 MB lokale Daten im Speicher halten soll.
© 2008, 2009, 2010, 2011, 2012 Ingenieurbüro David Fischer AG
Alle Rechte vorbehalten
Seite 30 / 32
Proxy Sniffer V 4.6
Plug-In Entwicklungshandbuch
3.5 Plug-In Programm-Beispiele
Bei Windows sowie bei Ubuntu (Linux) und Mac OS X Installationen von Proxy Sniffer finden
Sie mehrere Programm-Beispiele (*.java Quellcode) von vorgefertigten Plug-Ins im Project
Navigator Directory „MyTests \ Plugins“.
Bei der Installation des Proxy Sniffer GUIs bei anderen Unix-ähnlichen Betriebssystemen
(Solaris, …) wird das „MyTests / Plugins“ Directory im Project Navigator nicht automatisch
erzeugt. Sie müssen dieses Directory darum von Hand selbst erstellen. Danach können Sie
die vorgefertigten Plug-Ins und deren Quellcode von
http://www.proxy-sniffer.com/download/ProxySnifferPlugins.zip
herunterladen und danach den Inhalt dieses ZIP-Archivs in das Project Navigator Directory
„MyTests / Plugins“ extrahieren.
Hinweis: Beachten Sie, dass bei einer weiteren Installation von Proxy Sniffer die vorgefertigten
Plug-Ins überschrieben werden. Falls Sie den Quellcode eines Plug-Ins abändern, so sollten
Sie die entsprechende *.java Datei unter einem anderen Namen in „MyTests / Plugins“
abspeichern – und auch den Namen der Plug-In Klasse im Quellcode entsprechend
anpassen.
© 2008, 2009, 2010, 2011, 2012 Ingenieurbüro David Fischer AG
Alle Rechte vorbehalten
Seite 31 / 32
Proxy Sniffer V 4.6
Plug-In Entwicklungshandbuch
4 Hersteller
Ingenieurbüro David Fischer AG, Schweiz | A company of the Apica Group
Product Web Site:
http://www.proxy-sniffer.com
Alle Rechte vorbehalten.
© 2008, 2009, 2010, 2011, 2012 Ingenieurbüro David Fischer AG
Alle Rechte vorbehalten
Seite 32 / 32
Herunterladen