# Blockschema Logging mit Log4J



## Ben Letzel (24. August 2011)

Guten Tag liebe Kollegen,

ich habe folgendes Problem:
Ich habe mich vor einigen Tagen durch die API des Apache Frameworks *Log4J* durchgeschlagen und habe auch einige Sachen ausprobiert um ein Logging in eine Art Blockschema darzustellen.
Das Logging bezieht sich auf ein Transfer einer Datei zum Finanzamt, wobei ich für jede zu transferierende XML-Datei einen eindeutigen "Log-Datensatz" haben möchte um diesen später in der GUI darstellen zu können. Dazu habe ich eine Klasse implementiert, die die einzelnen Pattern der Log aufnimmt. 
Um das etwas genauer auf den Punkt zu bringen werde ich mal zeigen wie ich es realisiert haben möchte
Im Log soll es folgendermaßen aussehen:



> [Transfer=fref.xml]
> (15 08 2011 13:37:43) ELSTER_ERROR - fehlercode - Fehlermeldung
> (15 08 2011 13:40:30) ELSTER_ERROR - fehlercode - Fehlermeldung
> (15 08 2011 13:41:01) ELSTER_ERROR - fehlercode - Fehlermeldung
> ...



Dabei ist zu beachten, dass eine XML-Datei mehrmals im Log stehen kann z.B. wenn der Transfer beim ersten mal Fehlgeschlagen ist ein erneuter Transfer versucht wird und ggf. dieser erfolgreich war.

In der GUI soll dies später so aussehen, dass es für jeden geloggten Transfer ein Klapp-Menü gibt, wo schließlich die detaillierten Fehlermeldungen der Datei angezeigt werden.

Ich hoffe ihr könnt mir bei dem Thema weiterhelfen.

Lg Ben.


----------



## Fabio Hellmann (24. August 2011)

Hi und herzlich Willkommen bei Tutorials ,
was mich jetzt noch interessieren würde, wäre deine konkrete Frage und ob der Transferprozess ein Programmlauf ist, oder eben nur ein Teilprozess?

Gruß

Fabio


----------



## Ben Letzel (24. August 2011)

Ich würde sagen ein Programmlauf, da mehrere Methoden aufgerufen werden und die Rückgabewerte zurückgeliefert werden bzw. die Fehlermeldungen wenn eine Exception geworfen wird. Dann rufe ich eine Methode meiner Logger Klasse auf die sagt addLog(). Diese soll dann anschließend die Rückgabewerte und so weiter, wie oben dargestellt, in die Datei Loggen und in eine Liste packen um diese dann an die GUI zu pushen.


----------



## Fabio Hellmann (24. August 2011)

Mh, nein, du hast meine Frage glaub ich mal falsch verstanden.
Also meine Frage war, ob der Programmablauf so aussieht...
1. Programmstart
2. Transfer der XML-Datei
3. Logeintrag
4. Programmende
... oder eben anders.

Es wäre auch nicht schlecht, wenn du deinen Code posten könntest, damit wir dir dann besser weiterhelfen können.


----------



## Ben Letzel (24. August 2011)

Achso. Sorry. Haha. Dann entscheide ich mich für Teilprozess.


----------



## Fabio Hellmann (24. August 2011)

Ok, gut zu wissen. Aber drotzdem ohne Code und konkrete Frage können wir dir nicht weiterhelfen.


----------



## Ben Letzel (24. August 2011)

Eigentlich hat das weniger mit dem Code zutun. 
Meine eigentliche frage ist: Gibt es eine Möglichkeit eine strukturierte Darstellung in einer Log mit Hilfe dieses Frameworks zu erstellen? Wichtig ist für mich die Eindeutigkeit der einzelnen Blöcke im oben beschriebenen Schema auch wenn ein Transfer einer Datei mehrmals vor kommt.


----------



## Fabio Hellmann (24. August 2011)

Kla ist das möglich. Du kannst, wenn du in deine Logeinträge machst, doch einen String übergeben. Dann schreibst du in den String rein:
log.info("Transfer XML-File:"+file.getPath);
...
log.error("Transfer failed - "+errorcode+" - "+exception);
...
log.info("Transfer exit");


----------



## Ben Letzel (24. August 2011)

Achsoooooooo. Natürlich. Das habe ich anscheinend in der API übersehen ... 
Nein mal ehrlich, das war mir schon vorher bewusst. Anscheinend wurde mein erster Beitrag nicht verstanden.
Ich möchte ein EINDEUTIGES Blockschema



> [TRANSFER "xml.xml" - Datum(Begin des Transfers)]
> ...
> Datum - LoggingTyp (z.B. Error usw.) - ErrorCode - Errormsg
> ...
> [ENDE]



Die Log-Datei soll nicht nur einfach ausgelesen werden und runtergerattert im Debug-Modus in der GUI angezeigt werden. 
Ich denke meine Oma würde das nicht verstehen bzw. Hätte keine Lust das alles durchzulesen.
In der GUI soll später jeder Transfer damit gekennzeichnet werden ob er Erfolgreich war oder nicht. Wenn erfolgreich, ein grünes Häckchen keine Fehlermeldungen. Wenn fehlgeschlagen rotes Kreuzchen, Liste von lesbaren und verständlichen Fehlermeldungen für den Ottonormalverbraucher. 
Deshalb dieses Blockschema um eine Eindeutigkeit festzulegen.
Wenn nämlich die Log folgendermaßen aussehen würde:



> ...
> Datei - Datum - LoggingTyp (z.B. Error usw.) - ErrorCode - Errormsg
> Datei - Datum - LoggingTyp (z.B. Error usw.) - ErrorCode - Errormsg
> Datei - Datum - LoggingTyp (z.B. Error usw.) - ErrorCode - Errormsg
> ...


Gäbe es keine Eindeutigkeit.


----------



## SE (24. August 2011)

Ich hab mal so ne andere blöde Frage : warum lässt du erst alles loggen und machst dir dann die Mühe dieses Log wieder so aus ein ander zu nehmen ?
Mach das doch einfacher :
Objekte erstellen die das XML spezifizieren , eine globale Statusvariable : noch zu senden / gesendet / senden fehlgeschlagen und einen Vector / List / sonst was um aufgetretene Fehlermeldungen darin zu speichern. Das würde auf jeden Fall das verarbeiten in der GUI deutlich vereinfachen als wenn du dir dann noch n Log-Parser zusammenbaust , damit auch Probleme hast und dann für eine eigentlich so einfache Lösung einen so riesen Umweg baust.

Oder kurz : Konzeptionsfehler


----------



## Fabio Hellmann (24. August 2011)

Willst du das LogFile denn in die GUI laden, sprich einlesen und anzeigen?


----------



## Ben Letzel (24. August 2011)

> Ich hab mal so ne andere blöde Frage : warum lässt du erst alles loggen und machst dir dann die Mühe dieses Log wieder so aus ein ander zu nehmen ?


Das ist so nicht richtig. Komplett auseinander nehmen hatte ich auch nicht vor. Aber mir bleibt nichts anderes übrig auf die Datei zuzugreifen, aufgrund des Datums, das ich später in die Klasse "LogValues" übergebe. In der Klasse gibt es die Parameter Dateiname, Datum, LoggingTyp, Fehlercode, Fehlermeldung. Die Klasse "TransferLog" besitzt eine Methode addLog(dateiname, LoggingTyp, Fehlercode, Fehlermeldung). Diese fasst die Parameter zusammen und übergibt sie dem Appender der Logger-Klasse aus dem Apache Framework Log4J. Danach wird mit der Methode log(Priority priority, Object message) der Logger-KLasse des Log4J Frameworks geloggt. Danach muss ich den Eintrag aus der Datei lesen und das Datum heraus zu bekommen. Erst dann kann ich die Parameter in einer Instanz der Klasse "LogValues" übergeben um diese zu cachen, das heißt in eine Liste zusammenzufassen. Der Rückgabewert der Methode addLog(dateiname, LoggingTyp, Fehlercode, Fehlermeldung) aus der Klasse "TransferLog" ist eine Instanz von LogValues damit die GUI diese verarbeiten kann. 
ich hoffe es lässt sich jetzt klarer verstehen, wie weibliche Vornamen...


----------



## Ben Letzel (24. August 2011)

> Willst du das LogFile denn in die GUI laden, sprich einlesen und anzeigen?


Bitte nächstes mal den Beitrag lesen. Danke.


----------



## Fabio Hellmann (24. August 2011)

Also ich kann dir sagen, das was du vorhast geht *nicht*!
Du kannst aber eine "Art" Start- und End-Tag bei deinen Logeinträgen setzen. Dann kannst du beim Parsen einfach vom Start- bis zum jeweiligen End-Tag lesen, diese in dein Object verfrachten und anschließend die nächsten lesen...


----------



## Ben Letzel (24. August 2011)

Fabio Hellmann hat gesagt.:


> Also ich kann dir sagen, das was du vorhast geht *nicht*!


Bitte ?!! Wenn ja. Was *nicht* konkret, bitte... -.-*
Du hast den ersten Satz deiner Signatur bestätigt!


----------



## SE (24. August 2011)

Also wenn ich das richtig verstanden habe willst du erst alles loggen nnur um es danach wieder einzulesen und dann anzuzeigen ? Schwachsinn ...
Erst cachen , dann anzeigen ... UND DANN erst ins log speichern.


----------



## Ben Letzel (24. August 2011)

SPiKEe hat gesagt.:


> Also wenn ich das richtig verstanden habe willst du erst alles loggen nnur um es danach wieder einzulesen und dann anzuzeigen ? Schwachsinn ...
> Erst cachen , dann anzeigen ... UND DANN erst ins log speichern.



Hier muss man echt alles fünf mal erklären, oder?
Ich bin daran GEZWUNGEN erst zu loggen, dann zu cachen und anschließend anzuzeigen. 

Um auf dein letzten Satz nochmal zu sprechen zu kommen. Seit wann loggt man nachdem man angezeigt hat? Ist kein Zeitunterschied oder? Normalerweise in dieser Reihenfolge: cachen, loggen, anzeigen.


----------



## SE (24. August 2011)

Lol ... wer oder was zwingt dich bitte dazu erst ein Log-File zu schreiben , dieses dann auszulesen und daraus die Anzeige zu konstruieren ? Verbietet es dir denn jemand in dem Moment wo du etwas loggst dies auch als Objekt im RAM zu tun ? Wenn nicht : arbeite damit um die Anzeige aus dem RAM zu erzeugen *geht auch einfacher da OOP*.

Letzter Satz : whoops ... ja ok ... da hast du recht ... hatte da n Drehwurm.


----------



## Ben Letzel (24. August 2011)

SPiKEe hat gesagt.:


> Lol ... wer oder was zwingt dich bitte dazu erst ein Log-File zu schreiben , dieses dann auszulesen und daraus die Anzeige zu konstruieren ?



Das Datum.


----------



## SE (24. August 2011)

Ähm ... OOP ? Einfach in einem Objekt mitspeichern. Mein Gott ... bist du denn wirklich so prozedual orientiert das du auf sowas nicht kommst ? Und wenn jetzt kommt : wie bekommst du den Timestamp aus Log4J -> Apache-Forum ...
Alternativ : System.currentTimeMillis()


----------



## Ben Letzel (24. August 2011)

Was habe ich in Beitrag #12 denn gesagt? Dass ich es nicht in eine Klasse namens "LogValues" erfasse?
Und leider bekommt man den Timestamp nicht bevor der log in die Datei geschrieben wird.  
Und wenn ich stattdessen, wie die sagtest, System.currentTime() verwende besteht wieder ein Zeitunterschied.


----------



## SE (24. August 2011)

Ähm .. ja ... ok ... ich enthalte mich dann mal meiner weiteren Meinung. Wenn du es echt so umständlich machen willst und die Ratschläge nicht annimst welche dir OOP nahe legen ... und es scheinbar SO genau sein muss *ich glaube kaum das du einen Unterschied von mehr als 200ms haben wirst zwischen System.currentTimeMillis() und dem Aufruf im Logger* dann musst du halt damit leben das du mehr Leistung für deinen Umweg verbrauchst als du mit einem sauberen OOP sparen würdest.


----------



## Ben Letzel (25. August 2011)

Okay. Vielleicht war ich etwas zu übermütig in meiner Aussage. 
Habe nochmal darüber nachgedacht, dass man ein LoggingEvent abfangen kann und somit den Timestamp abfängt. Das heißt man müsste die append()-Methode einer Appender-Klasse überschreiben.
Das Problem wäre dann schonmal gelöst.
Bleibt nur noch die Eindeutigkeit.


----------

