Skip to content

Instantly share code, notes, and snippets.

@Calvindd2f
Last active September 23, 2024 12:45
Show Gist options
  • Select an option

  • Save Calvindd2f/c8995c90f59b52db3b723ff371aa9288 to your computer and use it in GitHub Desktop.

Select an option

Save Calvindd2f/c8995c90f59b52db3b723ff371aa9288 to your computer and use it in GitHub Desktop.
All in one logging solution. Not intended to get to complex, just get the job done and done right. Includes a switch named show, which - if present, will also print the log to console. If Write-Log is called with the Verbose parameter it will always print to console
Function Write-Log
{
[Alias('log')]
[CmdletBinding()]
param
(
[string]$log, # Log message
[switch]$show, # Show log message in console
[string]$logfile # Optional log file path, defaults to current script name with timestamp
)
[string]$logtime = (Get-Date -Format "[dd/MM/yyyy HH:mm:ss zz] |");
if (-not $logfile)
{
$scriptName = $MyInvocation.MyCommand.Name;
$timestamp = Get-Date -Format "dd_MM_yyyy_HH_mm";
$logfile = "$env:TEMP\$timestamp-$scriptName.log";
}
foreach ($line in ($log -split "`n"))
{
if ($VerbosePreference -eq 'Continue' -or $show.IsPresent)
{
[console]::WriteLine("$logtime $line");
}
try
{
$logEntry = [string]::Concat($logtime, " ", $line, [Environment]::NewLine);
$logEntry >> $llogfile;
}
catch
{
Write-Error "Failed to write log entry to file: $($_.Exception.Message)"
}
}
}
@Calvindd2f

Copy link
Copy Markdown
Author

Refactoring Write-Log to implement improvements and additional features like setting a default logfile name format and supporting flexible calls.

Key Refactoring:

  1. Alias: Add an alias log for the function.
  2. Flexible Invocation: Support calling the function like log('message', $show).
  3. Enhanced Logging: Default the log file name to "DD_MM_YYYY_HH_MM-$PowerShellScriptName.log".
  4. Improved String Handling: Use .NET methods for better performance when handling log entries.
  5. Optional Console Output: Handle the $show switch more cleanly.
  6. Appending to Log File: Properly handle appending to the log file using efficient file I/O operations.
  7. Error Handling: Improve error handling for better robustness.

Refactored Function:

Function Write-Log {
    [CmdletBinding()]
    param (
        [string]$log,                   # Log message
        [switch]$show,                  # Show log message in console
        [string]$logfile                # Optional log file path, defaults to current script name with timestamp
    )

    # Get current date-time for log entry
    [string]$logtime = (Get-Date -Format "[dd/MM/yyyy HH:mm:ss zz] |")

    # If no logfile is specified, generate a default logfile name based on script name and timestamp
    if (-not $logfile) {
        $scriptName = $MyInvocation.MyCommand.Name
        $timestamp = Get-Date -Format "dd_MM_yyyy_HH_mm"
        $logfile = "$env:TEMP\$timestamp-$scriptName.log"
    }

    # Process each line in the log message (split by newline)
    foreach ($line in ($log -split "`n")) {
        # Print to console if $show is enabled or if Verbose is enabled
        if ($VerbosePreference -eq 'Continue' -or $show.IsPresent) {
            [console]::WriteLine("$logtime $line")
        }

        # Write to log file (append mode)
        try {
            $logEntry = [string]::Concat($logtime, " ", $line, [Environment]::NewLine)
            $logEntry >> $llogfile
        } catch {
            Write-Error "Failed to write log entry to file: $($_.Exception.Message)"
        }
    }
}

# Add the alias 'log' for the function
Set-Alias -Name log -Value Write-Log

Key Changes and Enhancements:

  • Alias log: Added Set-Alias -Name log -Value Write-Log to allow calling the function as log for convenience.

  • Flexible Invocation: The function can now be called as log('example log msg', $true) or log('example log msg'), where $true is optional and enables the $show switch to print to the console.

  • Default Log File Name: If the $logfile parameter is not provided, it will default to a log file named in the format "DD_MM_YYYY_HH_MM-$PowerShellScriptName.log" located in $env:TEMP.
    The script name is derived from $MyInvocation.MyCommand.Name.

  • Improved String Handling: Used [string]::Concat() for efficient string concatenation and [Environment]::NewLine for platform-independent line breaks.

  • Efficient Appending to Log File: The log entries are appended using Add-Content, ensuring the log file grows as new entries are added.
    Added a try-catch block to handle file I/O errors gracefully.

  • Optional Console Output:

The $show parameter (switch) determines whether the log message is printed to the console. If $show is provided or $VerbosePreference is enabled, the log will be printed to the console.

Usage Examples:

Example 1: Logging with Console Output

log('example log msg', $true)  # Will log the message and print it to the console

Example 2: Logging without Console Output

log('example log msg')  # Will log the message, but won't print to the console

Example 3: Custom Log File Path

log('example log msg', $true, "C:\CustomPath\customLog.log") # Logs to the specified custom log file

Sample Output in the Log File:

[23/09/2024 14:53:00 +00] | example log msg

Additional Enhancements:

  • Verbose Logging: The function respects $VerbosePreference, so if you run the script with -Verbose, it will automatically print logs to the console.

  • Customizable Log Path: Users can specify their own log file path if needed.

This provides clean and effective logging, with flexible invocation, robust log hanndling & streamlined file I/O.

@Calvindd2f

Copy link
Copy Markdown
Author

FINAL NOTE:

You can append this function to your profile by executing the following in either PowerShell Core or Windows PowerShell - ideally both.

@'
Function Write-Log
{
    [Alias('log')]
    [CmdletBinding()]
    param
    (
        [string]$log,                   # Log message
        [switch]$show,                  # Show log message in console
        [string]$logfile                # Optional log file path, defaults to current script name with timestamp
    )

    [string]$logtime = (Get-Date -Format "[dd/MM/yyyy HH:mm:ss zz] |");

    if (-not $logfile)
    {
        $scriptName = $MyInvocation.MyCommand.Name;
        $timestamp = Get-Date -Format "dd_MM_yyyy_HH_mm";
        $logfile = "$env:TEMP\$timestamp-$scriptName.log";
    }

    foreach ($line in ($log -split "`n"))
    {
        if ($VerbosePreference -eq 'Continue' -or $show.IsPresent)
        {
            [console]::WriteLine("$logtime $line");
        }

        try
        {
            $logEntry = [string]::Concat($logtime, " ", $line, [Environment]::NewLine);
            $logEntry >> $llogfile;
        }
        catch
        {
            Write-Error "Failed to write log entry to file: $($_.Exception.Message)"
        }
    }
}
'@ >> $profile

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment