Tuesday, January 21, 2025
HomePowershellA Easy Logging Operate Tutorial

A Easy Logging Operate Tutorial


In the event you’re writing PowerShell scripts that do something significant, you want logging. Whether or not you’re deploying software program, managing companies, or automating duties, having a report of what your script did (or didn’t do) is essential. On this tutorial, you’ll learn to create a easy however efficient PowerShell logging operate.

Conditions

In the event you’d wish to comply with together with this tutorial, make certain you have got:

  • Home windows 10 or Home windows Server with PowerShell 5.1 or PowerShell 7+
  • A textual content editor (VSCode advisable)
  • Fundamental understanding of PowerShell capabilities

The Drawback with Fundamental Logging

Let’s say you’re writing a script to silently set up some software program. The essential method may look one thing like this:

Add-Content material -Path "C:Scriptsset up.log" -Worth "Beginning set up..."
Begin-Course of -FilePath 'installer.exe' -ArgumentList '/i /s' -Wait -NoNewWindow
Add-Content material -Path "C:Scriptsset up.log" -Worth "Completed set up."

This works, however it has some points:

  • No timestamps
  • Repetitive code
  • Inconsistent logging format
  • Laborious-coded log path

Let’s repair these issues by constructing a correct logging operate.

Constructing a Fundamental Write-Log Operate

First, let’s create a easy operate that provides timestamps to our log entries:

operate Write-Log {
    [CmdletBinding()]
    param (
        [Parameter(Mandatory = $true)]
        [string]$Message
    )

    $timeGenerated = Get-Date -Format HH:mm:ss
    Add-Content material -Path "C:Scriptsscript.log" -Worth "$timeGenerated - $Message"
}

Now you should use it like this:

Write-Log -Message "Beginning set up..."
Begin-Course of -FilePath 'installer.exe' -ArgumentList '/i /s' -Wait -NoNewWindow
Write-Log -Message "Completed set up."

The log file (C:Scriptsscript.log) will comprise entries that appear like:

09:42:15 - Beginning set up...
09:43:22 - Completed set up.

A lot cleaner! However we will do higher.

Including Extra Performance

Let’s improve our logging operate with some helpful options:

  • Customized log paths
  • Completely different log ranges (Information, Warning, Error)
  • Date in filename
  • Error dealing with

Right here’s the improved model:

operate Write-Log {
    [CmdletBinding()]
    param(
        [Parameter(Mandatory = $true)]
        [string]$Message,

        [Parameter()]
        [ValidateNotNullOrEmpty()]
        [string]$LogFilePath = "C:ScriptsLogs",

        [Parameter()]
        [ValidateSet('Information','Warning','Error')]
        [string]$Stage = "Data"
    )

    # Create the log listing if it would not exist
    if (!(Take a look at-Path $LogFilePath))  Out-Null
    

    # Construct the log file path with date
    $date = Get-Date -Format "MM-dd-yyyy"
    $logFile = Be part of-Path $LogFilePath "log-$date.txt"

    # Get the present timestamp
    $timeStamp = Get-Date -Format "HH:mm:ss"

    # Create the log entry
    $logEntry = "$timeStamp [$Level] - $Message"

    attempt {
        Add-Content material -Path $logFile -Worth $logEntry -ErrorAction Cease
    }
    catch {
        Write-Error "Failed to write down to log file: $_"
    }
}

This enhanced model provides you far more flexibility. Right here’s find out how to use it:

# Fundamental info logging
Write-Log -Message "Beginning software program set up"

# Warning a couple of non-critical problem
Write-Log -Message "Config file not discovered, utilizing defaults" -Stage Warning

# Log an error
Write-Log -Message "Set up failed!" -Stage Error

# Use a customized log path
Write-Log -Message "Customized path log" -LogFilePath "D:CustomLogs"

The ensuing log file (log-03-12-2024.txt) will appear like this:

10:15:22 [Information] - Beginning software program set up
10:15:23 [Warning] - Config file not discovered, utilizing defaults
10:15:25 [Error] - Set up failed!

And in D:CustomLogslog-03-12-2024.txt:

10:15:26 [Information] - Customized path log

Discover how every entry contains the timestamp, log degree in brackets, and the message. This structured format makes it straightforward to parse logs and rapidly determine points.

Actual-World Instance: Software program Set up Script

Let’s put our logging operate to work in an actual script that installs software program silently:

# First, dot-source the logging operate
. .Write-Log.ps1

# Script variables
$installer = "C:Installerssoftware program.exe"
$logPath = "C:ScriptsInstallLogs"

# Begin logging
Write-Log -Message "Starting set up course of" -LogFilePath $logPath

# Examine if installer exists
if (Take a look at-Path $installer) {
    Write-Log -Message "Discovered installer at: $installer"

    attempt {
        # Try set up
        Write-Log -Message "Beginning set up..."
        $course of = Begin-Course of -FilePath $installer -ArgumentList '/i /s' -Wait -NoNewWindow -PassThru

        # Examine the exit code
        if ($course of.ExitCode -eq 0) {
            Write-Log -Message "Set up accomplished efficiently"
        }
        else {
            Write-Log -Message "Set up failed with exit code: $($course of.ExitCode)" -Stage Error
        }
    }
    catch {
        Write-Log -Message "Set up failed with error: $_" -Stage Error
    }
}
else {
    Write-Log -Message "Installer not discovered at: $installer" -Stage Error
}

Write-Log -Message "Set up script accomplished"

The ensuing log file will look one thing like this:

09:15:22 [Information] - Starting set up course of
09:15:22 [Information] - Discovered installer at: C:Installerssoftware program.exe
09:15:22 [Information] - Beginning set up...
09:16:45 [Information] - Set up accomplished efficiently
09:16:45 [Information] - Set up script accomplished

Helpful Suggestions

Listed here are some finest practices when utilizing this logging operate:

  1. All the time log the beginning and finish of your script – This helps monitor script execution time and completion standing.

  2. Use applicable log ranges – Don’t mark the whole lot as an error; use the appropriate degree for the scenario:

    • Data: Regular operations
    • Warning: Non-critical points
    • Error: Essential issues that want consideration
  3. Embrace related particulars – Log sufficient info to grasp what occurred:

    # Dangerous
    Write-Log "Failed to attach"
    
    # Good
    Write-Log "Failed to connect with server 'SQL01' - timeout after 30 seconds" -Stage Error
    
  4. Clear up previous logs – Contemplate including log rotation to stop filling up disk house:

    # Delete logs older than 30 days
    Get-ChildItem -Path $LogFilePath -Filter "*.txt" |
        The place-Object { $_.LastWriteTime -lt (Get-Date).AddDays(-30) } |
        Take away-Merchandise
    

Conclusion

A great logging operate is crucial for any severe PowerShell script. With the Write-Log operate we’ve constructed, you now have a versatile and reusable approach so as to add correct logging to all of your scripts. Keep in mind to adapt the operate to your particular wants – you may wish to add options like:

Log Rotation

operate Write-Log {
    [CmdletBinding()]
    param(
        [Parameter(Mandatory = $true)]
        [string]$Message,

        [Parameter()]
        [int]$MaxLogFiles = 30  # Preserve final 30 days of logs
    )

    # Take away previous log recordsdata
    Get-ChildItem -Path $LogFilePath -Filter "*.txt" |
        The place-Object { $_.LastWriteTime -lt (Get-Date).AddDays(-$MaxLogFiles) } |
        Take away-Merchandise -Power

    # Proceed with regular logging...
}

Completely different Output Codecs (CSV, JSON)

operate Write-Log {
    [CmdletBinding()]
    param(
        [Parameter(Mandatory = $true)]
        [string]$Message,

        [Parameter()]
        [ValidateSet('TXT','CSV','JSON')]
        [string]$Format="TXT"
    )

    $logEntry = [PSCustomObject]@{
        Timestamp = Get-Date -Format "yyyy-MM-dd HH:mm:ss"
        Stage = $Stage
        Message = $Message
    }

    swap ($Format) {
        'CSV'   Export-Csv -Path "$LogFilePathlog.csv" -Append -NoTypeInformation 
        'JSON'  Add-Content material -Path "$LogFilePathlog.json" 
        'TXT'  
                 Add-Content material -Path "$LogFilePathlog.txt" 
    }
}

Community Path Assist

operate Write-Log {
    [CmdletBinding()]
    param(
        [Parameter(Mandatory = $true)]
        [string]$Message,

        [Parameter()]
        [string]$NetworkPath = "\serverlogs"
    )

    # Take a look at community path connectivity
    if (!(Take a look at-Path $NetworkPath)) {
        # Fallback to native logging if community is unavailable
        $NetworkPath = "C:ScriptsLogs"
        Write-Warning "Community path unavailable. Utilizing native path: $NetworkPath"
    }

    # Proceed with regular logging...
}

E mail Notifications for Errors

operate Write-Log {
    [CmdletBinding()]
    param(
        [Parameter(Mandatory = $true)]
        [string]$Message,

        [Parameter()]
        [string]$SmtpServer = "smtp.firm.com",

        [Parameter()]
        [string[]]$NotifyOnError = "[email protected]"
    )

    # Regular logging first...

    # Ship electronic mail if that is an error
    if ($Stage -eq 'Error' -and $NotifyOnError) {
        $emailParams = @{
            From = "[email protected]"
            To = $NotifyOnError
            Topic = "PowerShell Script Error"
            Physique = "Error occurred at $timeStamp`n`nMessage: $Message"
            SmtpServer = $SmtpServer
        }

        attempt {
            Ship-MailMessage @emailParams
        }
        catch {
            Write-Warning "Didn't ship error notification: $_"
        }
    }
}

The secret’s to start out with a strong basis and construct up from there based mostly in your particular wants. These examples ought to provide you with start line for extending the essential logging operate with extra superior options.

For instance, you may mix a number of of those options right into a single, complete logging resolution:

Write-Log -Message "Essential error in fee processing" `
          -Stage Error `
          -Format CSV `
          -NetworkPath "\serverlogs" `
          -NotifyOnError "[email protected]","[email protected]" `
          -MaxLogFiles 90

This could:

  • Log the error in CSV format
  • Retailer it on a community share
  • E mail a number of recipients
  • Keep 90 days of log historical past

Keep in mind to check totally, particularly when implementing community paths or electronic mail notifications, as these exterior dependencies can have an effect on your script’s reliability. Completely happy scripting!

RELATED ARTICLES

LEAVE A REPLY

Please enter your comment!
Please enter your name here

Most Popular

Recent Comments