PowerShell is often used to automate and script certain tasks and run it in background on specific time or based on specific action. complex scripts might also have more chance of breaking (services may not respond, machine configurations may have changed) no matter where you are running the script (laptop, az automation, az functions, vm) and how you are running script (interactive / non-interactive).

Without logging, it’s hard to know if scripts ran fine or if something went wrong. If something went wrong, logging will help us find out where and why it did.
Logging options:
Standalone script / Script with Schedule task – if you are preparing script which will be executed by schedule task or timer on the windows VM then its recommended to store the log ot text/log file in readable format. on each line you can add the timestamp + log type (error/warning/info) + log content. you can use logging modules available in PS gallery or you can create your own function to write logs in specific format. Please refer Write-Log function section for sample code
Azure Automation runbook – Azure automation account is capable to store the runbook output /log for 30 days and also we can specify logging level on each runbook. by default the automation account will store all the logs in output so if you use write-output command in the runbbok then it will get store in runbook job logs.


Write-Log – This function can help to write log to file or eventviewer or output (usefull for Az automation runbooks /functions)
<#PSScriptInfo
.SYNOPSIS
Log a message with the specified log level in output or eventlog or log file.
.VERSION 1.1.1
.AUTHOR Arun sabale
.DESCRIPTION
Log a message with the specified log level and additional detail like date+time, line number and message in output console or eventlog or log file.
.EXAMPLE
#write to log file
Write-Log -Message 'My Warning Msg' -Level Warning -Path C:\tmp\temp.log
#write log to eventlog
Write-Log -Message "my info msg" -Level Information -Eventlog
#write log to output screen
Write-Log -Message "my info msg" -Level Information -output
#>
function Write-Log
{
param
(
[Parameter(Mandatory=$false,ParameterSetName='output')]
[parameter(Mandatory=$false,ParameterSetName = 'Eventlog')]
[Parameter(Position=0,Mandatory=$true,ParameterSetName='path')]
[String] $Message,
[Parameter(Mandatory=$false,ParameterSetName='output')]
[parameter(Mandatory=$false,ParameterSetName = 'Eventlog')]
[Parameter(Mandatory=$false,ParameterSetName='path')]
[ValidateSet('Verbose', 'Information', 'Warning', 'Error')]
[String] $Level="Information",
[Parameter(Mandatory=$false,ParameterSetName='output')]
[Switch] $output,
[Parameter(Mandatory=$false,ParameterSetName='path')]
[string] $path,
[Parameter(Mandatory=$false,ParameterSetName='Eventlog')]
[Switch] $Eventlog
)
[string]$MessageTimeStamp = (Get-Date).ToString('yyyy-MM-dd HH:mm:ss')
$Message1 = "$MessageTimeStamp -[Line $($MyInvocation.ScriptLineNumber)] $Message"
# Output to log file
if ($path)
{
$Line = $env:ComputerName +", "+ $Env:Username+", "+ $Level+", "+ $Message1
$Line | Out-File -FilePath $Path -Append
}
# Output to event log
if ($Eventlog -eq $true)
{
if ($Level -eq 'Verbose')
{
$EntryType = 'Information'
}
else
{
$EntryType = $Level
}
Write-EventLog -LogName 'Windows PowerShell' -Source 'PowerShell' -EventId 0 -Category 0 -EntryType $EntryType -Message $Message1
}
# Output to console
if((!$path) -and $Eventlog -eq $false)
{
switch ($Level)
{
'Verbose' { Write-Verbose -Message $Message1 }
'Information' { try { Write-Output $Message1 } catch { Write-Host $Message1 } }
'Warning' { Write-Warning -Message $Message1 }
'Error' { Write-Error -Message $Message1 }
}
}
}
Log Levels in PowerShell – Debug, Information, and Warning
The Debug, Information, and Warning log levels work a little different than we’re used to from traditional logging frameworks in other languages. Let’s add some extra statements first:
Write-Debug "debug statement" Write-Information "info statement" Write-Warning "warning statement"
Avoid:
When you write your logging statements, make sure you leave out sensitive or personal data. Examples include:
- passwords, access tokens
- credit card numbers , bank account numbers, social security numbers
- encryption keys
Below are few more PS best practices :-
ps-click on links for more detail about each topic.
1> Comments -> Always use comments to explain code .. click for more detail
3> Error handling -> custom and system error handling with with try-catch
4> Functions -> Powershell function to avoid duplicate code
5> Parameters or User-defined variables -> No Hard-Coding so better to keep all input as parameters for functions or Place user-defined variables at top of script in case required.
6> #regions -> Grouping of code with regions for easy reading and troubleshooting
7> beautify/ Auto indent powershell -> beautify and auto indent powershell code with visual studio code