Empirius Tech Blog


SAP Java LogViewer Standalone - warum einfach, wenn's auch kompliziert geht...

Ein alternativer Weg, die SAP Java-Tracefiles auch ohne SAP Java LogViewer Standalone Installation zu lesen bzw. weiterzuverarbeiten.


 

SAP Java Logviewer Standalone

Warum einfach, wenn's auch kompliziert geht...

 

In der SAP-Welt wird gern mit Kanonen auf Spatzen geschossen. Gelegentlich auch mit Haubitzen auf Fruchtfliegen. Gemeint sind die häufig kompliziert angelegten Wege, die SAP einschlägt, um einfache Dinge zu erledigen.

 

Einfach "mal schnell" ein Tracefile von einem Kollegen oder einem Kunden anschauen ... nicht so einfach. Bisher.

 

Zwar gibt es den SAP Java Logviewer, der die Tracefiles menschenlesbar aufbereitet. Der braucht aber schon gleich mal ein X-Display. Und nicht immer hat man das Tracefile dort, wo auch der LogViewer ist. Dafür gibt es dann den SAP Java Logviewe Standalone. Aber den muss man im (seit Herbst '14 wiedermal umstrukturierten) SAPnet Download-Center auch erstmal finden und dann installieren. Wo war die Installationsanleitung nochmal? Mist. Wieder suchen.

 

Ist das geschafft, kann man die Server-Komponente starten, dann die Client-Komponente.

 

Jetzt nur noch Logfile hochladen, Logfile registrieren, ... Und all das nur, um ein Tracefile anzuschauen, das man z.B. per Mail bekommen hat?!

 

Muss das alles wirklich sooo schwierig sein?

 

Sinnvoll lesbar?

 

Was heißt eigentlich "sinnvoll lesbar"? In besagten Logfiles sind zwar durchaus (mehr oder minder) im Klartext die Fehlermeldungen enthalten. Nur: wann ist hier was passiert? Wo fängt ein Eintrag an und wo hört er auf?

Nach Anwendung der Methode des "scharfen Hinschauens" und ein wenig GSV hat man das Gröbste erschlossen.

 

Perl "to the rescue"

 

Abhilfe naht in Form eines auf der Kommandozeile ausführbaren Perl-Einzeilers. Naja, sofern man knapp die Länge eines Tweets - also ca. 140 Zeichen - als Einzeiler durchgehen läßt. Der "Zauberspruch" lautet wie folgt (alles eine Zeile):

 

Auf Windows:

perl -E"undef$/;$_=<>;@m=split/#$/m;for my$m(@m){$m=~s/\n//g;$m=~s/#(1|3)#/#/g;@f=split('#',$m);say localtime(substr($f[3],0,10)).' - '.join(' ',@f[20..25])}" < tracefile.trc

 

Auf Unix:

perl -E'undef$/;$_=<>;@m=split/#$/m;for my$m(@m){$m=~s/\n//g;$m=~s/#(1|3)#/#/g;@f=split("#",$m);say localtime(substr($f[3],0,10))." - ".join(" ",@f[20..25])}' < tracefile.trc

 

Huh?! Ich gebe zu, der zuvor bemühte Ausdruck "sinnvoll lesbar" trifft auf das Perl-Konstrukt nicht unbedingt zu. Dafür liefert er für jeden Eintrag im Tracefile eine Zeile beginnend mit einem lesbaren Zeitstempel und den interessantesten Angaben.

 

Unter der Haube

 

An sich ist der Ablauf recht einfach. Der Algorithmus ist richtig formatiert auch schon einfacher zu durchschauen. Das eigentliche Perl-Programm  steht in den doppelten(Windows)/einfachen(Unix) Anführungszeichen hinter -e:

#!/usr/bin/perl
use 5.12.0;

# einlesen von STDIN:
undef $/;
 $_ = <>;
# record split an am Zeilenende befindlichen #'s:
my @m = split /#$/m;
for my $m (@m) {
  $m =~ s/\n//g; # Zeilenenden entfernen
  $m =~ s/#(1|3)#/#/g; # multiple #'s vereinzeln
  my @f = split('#',$m); # auftrennen in Felder

  # Ausgabe Zeitstempel (Feld 4, epoch->lesbar)
  # + Felder (21-26)
  say localtime(substr($f[3],0,10)).' - '.join(' ',@f[20..25]);
}

Die ersten zwei Zeilen lesen die Standardeingabe, also unser reingepipetes Tracefile, ein. Danach wird an am Zeilenende stehenden #'s in Einträge aka Records zerlegt. Nun wird nur noch über die einzelnen Records iteriert und diese für die Ausgabe aufbereitet und die jeweile Zeile für den Record ausgegeben.

 

Besonderheiten sind lediglich das Lesbarmachen des vierten Feldes (Zeitstempel im Unix-Epoch-Format), das Herausfischen einiger wohl der Formatierung dienenden '#1#' bzw. '#3#'er-Vorkommen und der Array-Slice am Ende, welche die letzten 6 Felder zusammenfaßt.

 

Aber ich hätte gern noch...

 

Für weitere Informationen können natürlich beliebige weitere Felder ausgewertet und ausgegeben werden, wie Eintragstyp, betreffende Java-Klasse, usw. . Dafür müßten lediglich andere Felder ($f[<Index>]) ebenfalls ausgegeben werden. Eine Variante dieses Schnipsels mit deutlich mehr Optionen und Aufbereitungsmöglichkeiten ist bereits in Arbeit und wird sich bald hier wiederfinden.

 

Update (13.April 2015)

 

Mein Kollege wies mich heute darauf hin, daß für einige Logfiles mein "Skriptchen" nicht funktionieren würde - recht hat er! Hier hat sich das Log-Format geändert (wahrscheinlich mit Sap 7.40?). Nun ist der Zeitstempel prima menschenlesbar und damit auch mit simpelsten mitteln schon ein brauchbarer Auszug aus den Logfiles erhältlich... Jetzt reicht z.B. aus, einen Record-Trenner "2\.0." zu nutzen und nur den Zeitstempel und die interessierenden Felder auszugeben:

 

perl -e"$l=$/;undef$/;$_=<>;@m=split/#2\.0.#/m;$/=$l;for my$m(@m){$m=~s/\n//g;$m=~s/#(1|3)#/#/g;@f=split('#',$m);print $f[0].' - '.$f[-1].$/}"

 

Die Langform:

 

$l=$/; undef $/; $_ = <>; $/=$l;
@m = split /#2\.0.#/m;
for my $m (@m) {
  $m =~ s/\n//g;
  $m =~ s/#(1|3)#/#/g;
  @f = split('#',$m);
  print $f[0].' - '.$f[-1].$/;
}

 

Wieder gilt: Obiges funktioniert auf Windows, für Unix (aufgrund des Shell-Quotings) bitte doppelte und einfache Anführungszeichen austauschen. Geändert haben sich nur der Record-Trenner und die Ausgabe-Zeile. Und ich habe auf das say-Feature verzichtet, da auf betreffendem Rechner ein Perl < 5.12 im Einsatz war.

 

 

 


Tech Blog <- Zurück


Kommentare (1)

  1. Stefan:
    Apr 13, 2015 at 04:52 PM

    Und für die Freunde der Write-Only-Konstrukte das Ganze mal in "völlig unverständlich":

    perl -F# -ape'if($F[1]=~/2\.0./){$_=$c.$/;$c=$F[2]." - ".$F[-2]}else{$_="";$c.=$F[-2]}' < blubb.log

    (Unix-Verwendung). Alles klar?


Kommentar hinzufügen:





Erlaubte Tags: <b><i><br>Kommentar hinzufügen: