Keeping tabs on what a script is doing is critical for monitoring and debugging.
Monitoring a script can be done in many different ways, but it is usually dependent on how it's being executed. If a script is invoked interactively, meaning directly from the console using techniques such as Write-Verbose, Write-Information or Write-Host, it is useful because each command can display messages on the console as the script runs. But what if this script is getting invoked by a scheduled task or some other process that doesn't involve a human staring at a screen while it runs? In this case, we'll need to incorporate another level of monitoring. An excellent way to monitor a script that doesn't run interactively is by writing to a log file.
There are a few different ways to write text to a log file in PowerShell, and the approach that's used is completely up to the scripter. However, before embarking on creating your own logging function, there are a few things to keep in mind.
- All log file lines need to be structured content. No loosey-goosey text messages strewed about.
- The time should be recorded for each log entry.
- A severity is recommended or other "tags" to quickly filter information in the log file later.
Let's see how we can build a PowerShell function to incorporate into any of our scripts. Because this function will need to be available to several different scripts, we're going to create a PS1 script just to store our function. The function's name will be Write-Log.
Write-Log.ps1 function Write-Log
This logging function will write a single line to the log file every time it's called. Each line in the log is going to have two attributes that will change depending on what I'd like to record; message and severity, so I will add those as parameters to our function.
function Write-Log
Notice that I've chosen to limit the value of the Severity parameter to three choices. By limiting the options, it ensures that I can rely on this field to always be one of three different severities. Once I've got the parameters built out, I’ll use CSV to create a structured log file. This will ensure that I can quickly pull up the log file in a spreadsheet program and look through the data, if necessary. Notice below that I've also added the time. This isn't a parameter because this will always be the time the function was executed.
function Write-Log
That's all there is to our Write-Log function. We can now add this to any script we like as long as we dot-source it in first. If the Write-Log.ps1 script was in the same folder as the script we're calling it from; we could dot-source it like this:
Script.ps1 . "$PSScriptRootWrite-Log.ps1
Once the script knows about the function, it can then be called as many times as necessary in a script.
$foo = $false if ($foo)
The information would then get written to the log file, which would look like this:
PS> Import-Csv "$env:TempLogFile.csv" Time Message Severity ---- ------- -------- 5/13/2017 2:19 PM Foo was $false Error