In Part-1, we looked at why logging was important, established a set of guidelines or targets that we need to keep in mind while designing the framework and defined few variables that we will be using.
In Part-2, we expanded on the basics created a few more variables and created a function ‘Write-Log’, which as the name suggests writes messages to the log file.
In this part we will look at managing the logs that we will generate. What I mean is, we will need a way to archive the log files. For this we need a couple of functions:
- Add-BackSlashToPath, this function adds a backslash to a path.
- Switch-LogFile, this function archives the log files that are created for a script.
First let us look at Add-BackSlashToPath. The reason why we need this function is because PowerShell does not always return paths with a backslash appended at the end. So, we append it to the end of the path.
Function Add-BackSlashToPath ($Path){
<#
.SYNOPSIS
Add a backslash to any given path if it is missing.
.DESCRIPTION
Powershell usually returns path without a backslash.
This function takes care of that.
We need not expose this to the environment.
.EXAMPLE
Add-BackSlashToPath -Path "C:\Test-PS-1"
C:\Test-PS-1\
.EXAMPLE
Add-BackSlashToPath -Path C:\Windows\System32\
C:\Windows\System32\
.EXAMPLE
Add-BackSlashToPath -Path \\comp1\C$\Windows\System32
\\comp1\C$\Windows\System32\
#>
if(Test-Path -Path $Path -IsValid){
if($Path -match "\\$"){
$strPath = $Path
}else{
$strPath = $Path + "\"
}
} else{
$strPath = ".\"
}
$strPath
}
The second function archives the log files. The assumption is that the log file name will be scriptname.log. So, when the program finds a log with the name scriptname.log it will rename the existing log file to scriptname.001.log and then creates a new file with the scriptname.log name. This process will continue until we have as many log files as defined by the number of archives parameter. Once, this limit is reached the function will delete the last log file and update the names for all existing log files in the folder.
Function Switch-LogFile {
<#
.SYNOPSIS
Archive the log files for the script.
.DESCRIPTION
The number of archive files we maintain is determined by the numArch parameter.
Log file name is ProgramName.log.
.EXAMPLE
Switch-LogFile -Name "C:\Test-PS-1\First.log" -Arch 10
#>
Param (
[Parameter(Mandatory=$true)][string]$Name,
[Parameter(Mandatory=$false)][int]$Arch
)
try{
$pathToFile = [System.IO.Path]::GetDirectoryName($Name)
if ( ! (Test-Path -Path "$pathToFile")) {
$pathToFile = New-Item -Path "$pathToFile" -type directory
}
$pathToFile = Resolve-Path $pathToFile #Get full path for paths passed like '.\filename'
$pathToFile = Add-BackSlashToPath $pathToFile.Path.ToString()
$isValidPath = Test-Path -Path "$pathToFile" -IsValid
Write-Debug $isValidPath
if(!$Arch){
$Arch = $NumOfArchives
}
if($isValidPath){
#Get path that can be used by Get-ChildItem (gci) and Test-Path
$gciLogPath = $pathToFile + "*"
$Name = $Name.Substring($Name.LastIndexOf('\') + 1)
$logName = $Name.Substring(0,$Name.Length - 4)
Write-Debug $gciLogPath
#Test if the logfile exists
$defaultLogExists = Test-Path -Path $gciLogPath -include $Name
#If the default log i.e. "ScriptName.Log" exists
if($defaultLogExists){
$dirContent = Get-ChildItem $gciLogPath -Filter "$logName*.log" |Sort-Object -Property Name -Descending| Select-Object Name
ForEach($fileName in $dirContent){
if($fileName.Name -match "^*`.\d{3}")
{
$matchVal = $Matches[0]
if(([int]$matchVal.SubString(1,$matchVal.Length-1)) -eq ($Arch))
{
Write-Debug "Deleting log file: $($fileName.Name)"
$fileToDel = $pathToFile + "$($fileName.Name)"
Remove-Item -LiteralPath $fileToDel
}else{
$logNum = $matchVal.SubString(1,$matchVal.Length-1)
$logNum = "{0:D3}" -f (([int] $logNum) + 1)
$newName = "$logName.$logNum.log"
$fullPath = $pathToFile + "$($fileName.Name)"
Rename-Item -Path $fullPath -NewName "$newName"
}
}
}
#we are done with all the preprocessing so we can now rename "Log.log"
#as Log.001.log and create a new default log file.
$fullPath = $pathToFile + $Name
Write-Debug $fullPath
Rename-Item -Path $fullPath -NewName "$logName.001.log"
$newLogFile = New-Item -Path "$fullPath" -ItemType File -Force
} else { #default log does not exist go ahead and create the log file.
$fullPath = $pathToFile + $Name
$newLogFile = New-Item -Path $fullPath -ItemType File -Force
}
}
} catch{
Write-Error $_
}
}
# End Function Switch-LogFile
We now have a way of managing log files.
In the blog posts till now we have seen how to define a set of guidelines, define our variables based on these guidlines. We also, created a function that will log the data to a log file and created functions that will help us manage the log files that are generated.
In the next part we will tie all of this together and put them in a module so that we can use this as a standard way to log script actions.
Leave a comment