Das tolle an Brückentagen ist ja, dass man relativ entspannt Dinge erledigen kann, die sonst immer im Büro liegen bleiben.

Die letzten Tage habe ich daran gearbeitet, das Logging von Powershell-Scripten zu erweitern, bzw. zu dynamisieren. Das Problem, auf dass ich in meinen Scripten gestoßen bin, ist kurz gesagt, dass ich zum Zeitpunkt des Erstellens eines Scriptes noch nicht sicher sagen kann, wo und wie Dinge zu loggen sind.

Wird mein Script direkt in der Konsole ausgeführt? Dann würde es ausreichen, den Log-Krempel in den Verbose-Stream zu werfen. Falls das Script jedoch als geplanter Task oder indirekt über ein drittes Script ausgeführt wird, hilft mir der Verbose-Channel relativ wenig. Ich kann ein Script zwar durch ein zweites ummanteln, die Verbose-Benachrichtigungen auffangen und mir wiederrum in eine Datei oder Datenbank schreiben, aber dann habe ich nur die Nachrichten ohne Zeitstempel.

Letzteres ist oft zwar kein Problem, aber so manches Mal eben doch noch ein Stück weit relevant.

Meine Idee ist, anstatt jetzt in jedem Script fest vorzugeben, was wohin geloggt wird, überlasse ich das dem Ausführenden des Script.

Der Befehl zum Schreiben eines Logs wird dabei in der Art wie diese Zeile aufgerufen:

Write-LogMessage -Message "Hello World!" -Type "Information"

Denkbar einfach und ohne großen Stress. Wenn ich das Ziel dynamisieren will, muss ich dem Write-LogMessage noch mitgeben, wohin die Nachricht gespeichert werden soll. Ich habe mir dafür eine Powershell-Klasse konstruiert:

class LogProfileData{
    [string]$BasePath
    [int]$MaxSize
    [switch]$FileRotation
    [int]$MaxFiles
    [string]$Mode
}

Das kann man wahrscheinlich noch wunderschön optimieren, aber für meine Zwecke reicht es zunächst.

Die Variable $Mode soll verschiedene Möglichkeiten repräsentieren, wohin eine Logzeile geschrieben werden soll. Für den Anfang reichen mir hier zwei Werte: "Verbose" und "File". Die anderen Werte in der Klasse beschreiben genauer, wo Logfiles abzulegen sind (Falls als $Mode der Wert "File" übergeben wird.

Die Funktion Write-LogMessage habe ich um einen weiteren Parameter erweitert:

Write-LogMessage -Message "Hello World2!" -Type "Informational" -LogProfile $Log

Die Parameterfunktionalität ValueFromPipeline und der foreach-Block in dem process-Teil der Funktion ermöglichen mir jetzt, sowohl ein einzelnes Logprofil zu übergeben, oder ein Array von mehreren Profilen. Bei jeder Nachricht wird geprüft, von welchem Typ die Nachricht sein soll und entsprechend verfahren.

Bei einem Logprofil mit $Mode = "Verbose" wird zum Beispiel einfach eine Logzeile an den Verbosestream ausgegeben.

Das PS-Modul hat noch ein wenig Feinschliff nötig, macht aber bereits einen guten Job. Zudem ist das Modul beliebig um weitere LogProfil-Varianten erweiterbar: Du willst einen Splunk-Server mit Nachrichten beglücken? Dann erweitern wir das LogProfil um einen weiteren Modus. Wichtig ist lediglich, dass man von Powershell oder .NET aus die Nachricht absetzen kann.

Eine erste Version des Moduls findet ihr hier:

https://gitlab.com/rldml/PowershellLogging

An dem Teil muss ich noch einiges an Krempel erledigen, bevor es wirklich spruchreif ist, aber diese Version lässt sich bereits verwenden