Inhalt

• Anlass Was mich denn umtrieb ...
• Entwurf Was kann man machen?
• Einsatz Wie mache ich es?
• Einblick Wie sieht die Benutzer­schnittstelle aus?
• Quell­code Der Ada-Quellcode als GPS-Projekt


Anlass

Was mich denn umtrieb ...

Ich suchte ein einfach einzusetzendes Hilfsmittel, mit dem ich in echt­zeit­na­hen Pro­gram­men etwa bei der Feh­ler­su­che Daten sammenln kann, um die­se dann (oft) fix mit Ex­cel auszuwerten.

So brachte ein Kollege einmal CentOS ins Haus - als Kan­di­dat für den Er­satz eines pro­prie­tä­ren Be­triebs­sys­tems. Ich wollte wissen, wie stabil eine 10ms-Schleife über Nacht denn unter CentOS läuft.

Ein Einsatzfall für mein Logs_To_Ram. Ich pro­to­kol­lier­te über Nacht die Aus­rei­ßer und hat­te am Morgen das Ergebnis - ein Ausreißer um 21 Uhr, ein fa­mo­ses Er­geb­nis. Ein normales Suse-Linux verhielt sich da we­sent­lich un­ru­higer.



Ent­wurf

Was kann man machen?

Das Werkzeug stellt 5 Puffer bereit, die Zahl der Puffer kann oh­ne wei­te­res er­höht werden - so steht etwa für jede An­wen­der­task ein Puf­fer zur Ver­fü­gung, oder aber auch für un­ter­schied­li­che Daten auch un­ter­schied­li­che Puffer.

Für die Puffer verwende ich die ‘Booch'schen Col­lect­ions’.

Die Daten werden als Zeichenketten, getrennt mit einem Tren­ner, hier das Zei­chen '|', in die Puffer geschrieben. Auf Befehl werden schließlich die Puf­fer­in­hal­te - samt Puf­fer­num­mer und Ein­gangs­rei­hen­fol­ge - zeitlich sortiert in eine Datei geschrieben.

Bei meinem oben erwähnten CentOS Testlauf war­te­te die Haupt­task einfach vor einem 'Ada.­Text_IO.­Skip_­Line' auf ei­nen Tas­ten­druck, wo­rauf­hin die Schreib­pro­ze­dur aus­ge­führt wurde.

Das Werkzeug erwartet im Pro­gramm­ver­zeich­nis eine klei­ne cfg-Da­tei, in der ich Puffer ein- oder abschalten kann. Ist die cfg-Da­tei nicht vor­han­den, wird auch nicht geloggt.



Ein­satz

Wie mache ich es?

Zwei Möglichkeiten hat man: Man kann eine Zei­chen­ket­te als Gan­zes so­fort in ei­nen Puf­fer schreiben, oder man sam­melt sich die Zeichenkette erst aus Teil­ket­ten zu­sam­men, um erst am Ende in den Puffer zu schrei­ben. Die Zei­len

i1:=123;
f2:=4.56789;
Do_Log_To_Ram (1, Str (i1) & Str (f2));


schreiben die aufgeführten Zahlen mitsamt dem Trenn­zei­chen in den Puf­fer '0', die Funk­tio­nen 'Str' sind Hilfsroutinen. Ei­ne Zei­le wird nach 240 Zei­chen ab­ge­schnit­ten. Nun die Ausgabe einer Zei­le in zwei Tei­len

Float_Array := (1.234, 10000.0, -200.0003);
Append_To_Log_Item (2, Put_Floating_Constrained_Array
   (Float_Array));
Append_To_Log_Item (2, Sep & "an array");
Do_Log_Item_To_Ram (2);


Put_Floating_Constrained_Array ist die Aus­prä­gung ei­ner ge­ne­ri­schen Hilfs­rou­ti­ne, die Funktion Sep gibt ein­fach das Zei­chen '|' zu­rück. Die Prozedur

Save_Logs_To_File;


schreibt die Pufferinhalte schließlich in eine Da­tei, die im Pro­gramm­ver­zeich­nis abgelegt wird. Man kann auch ein we­nig fil­tern:

Do_Log_To_Ram (1, "5a- abcdefghi", "def");
Do_Log_To_Ram (1, "5b- abcdefghi", "345");


Im zweiten Fall (5b) wird nichts in den Puffer ge­schrie­ben, weil das vor­ge­ge­be­ne Mus­ter "345" nicht in der Nutz-Zeichenkette enthalten ist. Wei­ter­ge­hen­des Filtern mit einfachen regulären Ausdrücken ist über ein Er­gän­zungs­pa­ket möglich, hierzu wird ein GNAT-Paket ver­wen­det, in dem die Re­geln knapp erläutert werden. Im Bei­spiel sä­he das so aus:

Re.Compile (Pos => 3, P => "[a-z]+");
Append_To_Log_Item (3, "14- ");
Re.Append_To_Log_With_Re (3, "match: ", "noarray");
Do_Log_Item_To_Ram (3);
Append_To_Log_Item (3, "15- ");
Re.Append_To_Log_With_Re (3, "no match: ", "12346789");
Do_Log_Item_To_Ram (3);

Er­geb­nis

Nachfolgend ein Ausschnitt der Ausgaben meines wüs­ten Test­programms, die Zeilen habe ich gekürzt. Jede Zeile be­ginnt mit zwei Zeit­stem­peln, es folgt der Puffername und ei­ne lau­fen­de Num­mer für je­den Puf­fer­ein­trag.

09:53:31,455|35611,455206|0_Buff|1|123456789
09:53:31,455|35611,455218|0_Buff|2|abcdefghi
09:53:31,455|35611,455220|1_Buff|2|123456789
09:53:31,455|35611,455220|1_Buff|3|abcdefghi
09:53:31,455|35611,455221|1_Buff|4|abcDEFghi
09:53:31,455|35611,455231|1_Buff|7|123|4,56789E+00|
09:53:31,455|35611,455237|0_Buff|3|1,23400E+00|1,00000E+04|-2,00000E+02|
09:53:31,455|35611,455247|2_Buff|1|1,23400E+00|1,00000E+04|-2,00000E+02||
09:53:31,455|35611,455250|2_Buff|2|1,23400E+00|1,00000E+04|-2,00000E+02||


Ein­blick

Wie sieht die Benutzerschnittstelle aus?

•  logs_to_ram.1.ada - das einfache Basispaket für den schnellen Einsatz

•  logs_to_ram.re.1.ada - eine Erweiterung um einfache reguläre Ausdrücke

(Ein Hinweis: Ich benutze das allerprächtige 'GNAT Programming Studio' von AdaCore. Die Navigation innerhalb der generierten Do­ku­men­ta­tion klappt nicht immer.)



Quell­code

•  Logs-To-Ram - der vollständige Ada-Quellcode als GPS-Projekt, gezippt