Ausführliches Logfile

  • Hallo zusammen,
    ich habe mal wieder eine etwas dämliche Frage ;)

    Ich habe ein (einwandfrei funktionierendes) Programm mit knapp 5'000 Zeilen Code.
    Nun ist gewünscht worden, dass das Programm zur Laufzeit so ziemlich alles "dokumentiert" (Logfile) was es macht, bzw. was die Rückgabewerte waren.

    Für mich bedeutet das natürlich ein sehr grosser Aufwand, da zu den 5'000 Zeilen vermutlich nun 2'000 Zeilen für die Doku dazukommen würden.

    • Ist es möglich, dass AutoIt nach jedem Befehl mit Rückgabewert automatisch in eine Funktion springt und den Rückgabewert übergibt? (Vermutlich eher nicht...)
    • Wie stelle ich es an, dass mein eigentliches Programm nicht durch das loggen ausgebremst wird? Soll ich die ganzen Texte und Rückgabewerte in ein Array schreiben und am Schluss erst in eine Datei?
      Was wäre der Beste Ansatz, um ein möglichst vollständiges Logfile zu erhalten und doch nicht unbedingt tagelang das Hauptprogramm anzupassen?.

    Die Leute möchten das Logfile einfach für den Fall, falls bei einem Kunden mal irgendetwas schief läuft. Dann könnte man einfacher nachvollziehen, wo das Problem liegt.

    Vielen Dank für Eure Ideen.
    Grüsse Veronesi

    Einmal editiert, zuletzt von veronesi (31. März 2011 um 11:38)

    • Offizieller Beitrag

    Hi,

    bei großen Programmen könntest du von log4j oder ähnlichem abgucken.
    In Autoit könnte man bspw eine globale Variable definieren.
    Global $loglevel = 0 ; 0 = kein log, 1 = fatal/error, 2 = info, 3 = debug
    Dann eine Funktion schrieben, in der formatiert die Ausgabe gemacht wird.
    Und im Code dann die Zeilen einfügen If $loglevel = ... Then _mylog("text")
    Alles in ein Array schreiben ist bei Fehlern schwierig, da im Abbruch dann gar nichts geloggt wird.
    Durch extremes loggen wird dein Skript sicher ausgebremst, aber ich denke das sollte zu verschmerzen sein. (Situativ)
    Ansonsten kannst du dir in Scite4Autoit mal DebugTo... unter Tools angucken. Das hilft ggf. auch.
    Mega

  • In Scite gibt es unter Tools den Punkt "Debug to Console" diese einfach auf jede "Zeile" in der ein Rückgabewerte kommt anwenden. Dadurch entstecht ein kompletter "Log" in der Console als Stdout. Dann erstellst du eine zweites Programm das mit StdoutRead eben diesen Stdout ausliest und in das Logfile speichert.

    Ist zwar nicht die schönste Lösung aber es verhindert das Ausbremsen deines Programmes und die Anpassung deines aktuellen Scriptes ist minimal weil einfach nur markieren und klicken.

    Andy hat mir ein Schnitzel gebacken aber da war ein Raupi drauf und bevor Oscar das Bugfixen konnte kam Alina und gab mir ein AspirinJunkie.

  • Hallo Mega!

    Vielen Dank!
    Ja, im Abbruchsfall würde nichts geloggt werden... Habe ich total übersehen!
    Auch das mit der globalen Variable ist eine gute Idee. So kann ich das loggen global Ein- / Aus- oder teilweise einschalten!

    Frage: Was ist die schnellste Methode um in eine Datei zu schreiben? Ich meine ich muss die Datei ja nach jeder Zeile wieder schliessen, sonst ist sie bei einem Absturz auch nicht gespeichert!

  • Schau dir mal meinen Post an veronesi ;).

    Andy hat mir ein Schnitzel gebacken aber da war ein Raupi drauf und bevor Oscar das Bugfixen konnte kam Alina und gab mir ein AspirinJunkie.

  • Hallo Chip, auch Dir vielen Dank.

    Ist eine Interessante Idee, muss ich mal anschauen.
    Das Problem ist, dass mein "Programm" bereits aus vier (4) parallel laufenden Programmen besteht!
    (Z.B. die GUI ist schon separat um das Programm nicht auszubremsen)

    Aber wie gesagt, alles läuft einwandfrei.

    Was meinen die Anderen? Wäre ein paralleles Program eine gute idee?

  • Ich kenne viele Programme die das Programm zum Log erstellen auslagern um das Log nur bei Bedarf bzw. wenn dann ohne Beeinflussung des Programmes zu aktivieren. Wenn du es in das Programm integrierst, dann hast du immer das Risiko, dass das Problem im Log erstellen liegt und nicht in deinem Programm, dann wirst du im Log dazu aber auch nichts finden und die evtl. tot suchen.

    Andy hat mir ein Schnitzel gebacken aber da war ein Raupi drauf und bevor Oscar das Bugfixen konnte kam Alina und gab mir ein AspirinJunkie.

  • Hallo Chip,

    ich habe mal die "automatische" Debug to Console angeschaut.
    Das Problem fängt schon bei einem einzeiligen Program an:

    [autoit]

    Dim $AskedUsername = InputBox("Benutzernamen eingeben", "Bitte Benutzernamen eingeben", "blabla")
    ConsoleWrite('@@ Debug(' & @ScriptLineNumber & ') : Dim = ' & Dim & @crlf & '>Error code: ' & @error & @crlf) ;### Debug Console

    [/autoit]

    Die zweite Zeile wurde durch Alt+D automatisch erzeugt. Trotzdem funktioniert sie so nicht....
    Ich möchte nicht alle Zeilen von Hand anpassen müssen. Was ist da falsch?

    Edit: OK, ohne das DIM am anfang bringt er zwar keine Fehlermeldung, aber die Abfrage kommt dann zweimal.......
    Irgendwie haut das automatisch noch nicht so hin...

  • Erschwerend kommt noch dazu, dass meine anderen Programme auch über den StdOut / In kommunizieren und Daten austauschen. Dann müsste ich auch noch ein "Protokoll" haben um zu wissen, was Logfile und was für die anderen Programme bestimmt ist.

    • Offizieller Beitrag

    Ich glaube nicht, dass der Weg über DebugConsole zum Ziel führt. Höchstens wenn du wirklich debuggen willst. Dann kannst du aber auch mit dem Traybereich arbeiten und die Geschwindigkeit ist dir egal.
    Ich würde mal schauen, wo ein Logeintrag wirklich Sinn ergibt. Bei Funktionsaufrufen kannst du sinnvoll loggen und außerdem ist die Ablaufsteuerung deines Programms ja nicht 4000 Zeilen. Sondern alles zusammen.
    Die Aktionen kommen ja aus deiner wahrscheinlich while wend Schleife. Kannst dort nicht beginnen und ggf. in einzelnen zentralen Funktionen ein, zwei Logzeilen einschieben.
    Das sollte doch erstmal für den Beginn reichen.

  • Ja, ich denke die DebugConsole ist zwar ein Interessanter Ansatz, aber für das Feld draussen eher weniger. Zumal ich ja diesen Kanal schon benötige um zwischen meinen Programmen zu kommunizieren.
    Ja, die ca. 5'000 Zeilen Code sind mit Kommentaren und so. Also die reinen Befehle, die einen Rückgabewert liefern, liegen vermutlich so bei knapp 2'000.

    Mit diesem Programm werden sehr viele unterschiedliche Dinge erledigt. Unter anderem werden diverse Tools installiert. Dort ist es einfach, das ist eine 20ig zeilige Schleife, die aus einer Datenbank die notwendigen Installationsbefehle ausliest und dann nur ausführt. Das ist schnell geloggt. Aber die hunderte von einzelnen Registryeinträge (Ja, das wollen die wirklich alles haben!) und das setzen der Hintergrundbilder, Bildschirmauflösung, Gruppenmitgliedschaften etc.... das ist alles einzeln.

    Vermutlich werde ich einfach Schritt für Schritt Logfileeinträge hinzufügen.
    Aber welches ist die schnellste Methode um eine Zeile in eine Datei zu schreiben, um möglichst keine Zeit zu verlieren?
    Ich möchte das Loggen schon am liebsten in einer Funktion erledigen. Ist am übersichtlichsten zum anpassen. Aber wie lange dauert ein Funktionsaufruf?

    FileWriteLine scheint mir bei einem ersten Test etwas "langsam" zu sein.

  • Su solltest auch nur die Varible ausgeben, dann gehts auch ;). Sprich nur die Variable markieren und dann Alt+D:

    [autoit]

    Dim $AskedUsername = InputBox("Benutzernamen eingeben", "Bitte Benutzernamen eingeben", "blabla")
    ConsoleWrite('@@ Debug(' & @ScriptLineNumber & ') : $AskedUsername = ' & $AskedUsername & @crlf & '>Error code: ' & @error & @crlf) ;### Debug Console

    [/autoit]

    Btw. wenn das Programm so Zeitkritisch ist solltes du ernsthaft überlegen ob dann Autoit das richtige dafür ist.

    Andy hat mir ein Schnitzel gebacken aber da war ein Raupi drauf und bevor Oscar das Bugfixen konnte kam Alina und gab mir ein AspirinJunkie.

  • Naja, zeitkritisch ist das falsche Wort.
    Es hängt keine kritische Applikation oder sowas daran.

    Die Leute möchten einfach nicht, dass das Programm noch länger hat um durchzulaufen. Jenachdem, wieviel installiert werden muss, dauert die Programmausführung zwischen 4 Sekunden und 120 Sekunden. Und manche Leute führen das Programm alle 1h aus. (Es hängen eben noch wichtige Synchronisationen an diesem Programm).

    Aber es ist nicht so wichtig ob das Programm nun 4-120 Sekunden oder 6-122 Sekunden hat. Das merkt sowieso keiner. Aber ich möchte aus Ehrgeiz die schnellste und schlankste Variante finden.

    Leider bin ich kein Programmierer, sondern mache das nur so nebenbei für die Firma. (Und die ist sehr froh darüber, denn die "richtigen" Programmierer bei uns sind extrem ausgelastet)
    Ich kann also nur Batch, Basic, RunCMD und AutoIt etwas programmieren.

    Von demher ist AutoIt goldrichtig. Auch wenn ich mir manchmal ETWAS mehr Geschwindigkeit wünschen würde.

  • Aber ich möchte aus Ehrgeiz die schnellste und schlankste Variante finden.

    Das stellt eine Wiederspruch zu Autoit da, da Autoit weder schnell noch schlank ist. Ich habe ja selbst eine Softwareverteilung geschrieben, aber mit der zunehmenden Menge an Programm und Rechner haben sie einfach die Nachteile von Autoit zu stark gezeigt wenn es um eine groß Anwendung geht. Daher steigen wird demnächst auf eine APP-V gestützte Softwarevirtuallisierung um.

    Andy hat mir ein Schnitzel gebacken aber da war ein Raupi drauf und bevor Oscar das Bugfixen konnte kam Alina und gab mir ein AspirinJunkie.

  • Das tönt interessant. Aber ich bin kein Programmierer und mache das nicht hauptberuflich. Deshalb ist für mich immer noch AutoIt ein gutes Tool.
    Ich programmiere darin nämlich nicht nur Softwareverteilungen, sondern auch automatisierte Prüfgeräte. Und ich weiss nicht, ob das APP-V Softwarevirtualisierung könnte.... (Kenne ich nicht)

  • Ok. Habe mir soeben die Wiki Seite von APP-V kurz quergelesen. Wenn man Offline ist, funktioniert das Ganze nicht - ausser die Anwendung wurde bereits vollständig auf den PC gestreamt.
    Das würde bei uns nicht funktionieren, da gewisse Auslandstellen mit einer extrem schlechten Internetverbindung ausgestattet sind.

    Zudem muss das auch auf Notebooks funktionieren, wenn die Leute zu Kundenanlagen gehen und dort ohne Netzwerk arbeiten müssen. Es muss also alles einmal komplett installiert werden.
    Für uns ist AutoIt momentan die eleganteste Lösung. Klar, unsere "richtigen" Programmierer arbeiten u.a. in Delphi. Irgendwie wäre es cool, wenn ich auch dort arbeiten könnte und die Softwareverteilung darüber machen würde.

    Doch ich traue mich nicht, in Delphi einzuarbeiten. (Weil ich kann keine Kurse oder so belegen. Und die andern können mir aus Zeitgründen auch keine Einführung geben...)

    • Offizieller Beitrag

    Nun, da befindest du dich in einem Dilemma. Das hört sich so an wie: Wasch mich, aber mach mich nicht naß.
    Wenn du sicher gehen willst, dass dein Log auch vorliegt, nachdem irgendein Vorgang versagt hat und evtl. dein Programm abgeschossen ist, bleibt dir tatsächlich nur ein finales Schreiben in die Log-Datei nach jedem Vorgang. Das dauert natürlich seine Zeit.
    Ich würde daher auch empfehlen, deine Programmabläufe in kritische Zonen zu unterteilen.
    Z.B. grob in relevant und wenig relevant. Dann legst du fest: wenig relevante Ereignisse sammeln und mit dem nächsten relevanten Ereignis final schreiben. Somit kannst du sicher schon einige Zeit sparen.
    Sag deinem Chef mal, er kann nicht verlangen, dass du ab sofort Sitzungsprotokolle wortwörtlich auf Papier schreibst aber gleichzeitig den Papierverbrauch senkst. :P

  • ;)
    Gut gesprochen!

    Mit diesem Script

    [autoit]

    #include <file.au3>

    [/autoit][autoit][/autoit][autoit]

    $Timer = TimerInit()
    For $i = 1 to 1000
    _FileWriteLog(@ScriptDir & "\my.log",$i)
    Next
    $End = TimerDiff($Timer)
    _FileWriteLog(@ScriptDir & "\my.log","Ausführdauer: " & $End)

    [/autoit]

    dauert es ca. 2 Sekunden um die Logeinträge zu schreiben.
    Was meint Ihr? Ist da Delphi deutlich schneller?

    Aber ich vermute mal, dass es auf das hinaus läuft, was BugFix geschrieben hat.
    Ich logge das, was wirklich notwendig ist.

  • So kann man schön den Unterschied erkennen, was es ausmacht, das File immer zu schliessen!

    [autoit]

    #include <file.au3>

    [/autoit][autoit][/autoit][autoit]

    $Timer = TimerInit()
    For $i = 1 to 1000
    _FileWriteLog(@ScriptDir & "\my.log",$i)
    Next
    $End = TimerDiff($Timer)
    _FileWriteLog(@ScriptDir & "\my.log","Ausführdauer: " & $End)

    [/autoit][autoit][/autoit][autoit]

    $Timer = TimerInit()
    $hFile = FileOpen(@ScriptDir & "\my2.log", 9)
    For $i = 1 to 1000
    FileWriteLine($hFile,@YEAR & "-" & @MON & "-" & @MDAY & " " & @HOUR & ":" & @MIN & ":" & @SEC & " : " & $i)
    Next
    FileClose($hFile)
    $End = TimerDiff($Timer)
    FileWriteLine(@ScriptDir & "\my2.log","Ausführdauer: " & $End)

    [/autoit]

    Erstes Logfile: 2 Sekunden
    Zweites Logfile: 20 Millisekunden

  • Eine interessante Möglichkeit bietet die neue Container UDF aus dem englischen Forum.
    Die Log-Funktion könntest du z.B so einbinden:

    [autoit]

    Dim $AskedUsername = _LOG(InputBox("Benutzernamen eingeben", "Bitte Benutzernamen eingeben", "blabla"))

    [/autoit][autoit][/autoit][autoit]

    Func _LOG($val)
    _Container_PutProperty($oContainer, "$val", $val)
    Return $val
    EndFunc

    [/autoit]

    nach jedem _Container_PutProperty sendest du eine MSG an das LOG Script, welches dann den Container ausliest und z.B in ein Array zwischenspeichert.
    Alle 10 Sekunden werden die Werte dann in eine Datei gespeichert.

    E