Quick Start • Log Styles • Functions • Concurrency • Development
Lightweight PowerShell logging for scripts, scheduled tasks, and automation jobs.
PSLogging2 provides file-based logging with simple writer functions, multiple log file layouts, optional timestamps, and SMTP delivery for completed logs. The module is designed for straightforward use in PowerShell 5.1 style environments while still being usable in newer shells.
- Three log file layouts:
Simple,Standard, andDaily - Dedicated helpers for info, warning, and error messages
- Optional timestamp placement controlled by
-TimestampPosition <Front|Back|None> - Daily log reuse with automatic run separators
- Atomic append logic for safer concurrent writes
- Optional SMTP delivery with
Send-Log
PSLogging2/
|- Functions/ # Module functions
|- Docs/ # Review notes and planning docs
|- Tests/ # Validation and smoke-test scripts
|- PSLogging2.psm1
|- PSLogging2.psd1
`- README.md
Import-Module .\PSLogging2.psm1 -ForceCopy the PSLogging2 folder into one of your PowerShell module paths, then import it normally:
Import-Module PSLogging2Import-Module .\PSLogging2.psm1 -Force
# Explicit LogContext pattern (recommended)
`$ctx = Start-Log -Style Simple -LogDir .\log -Title 'Inventory Script' -Version '1.0' -ToScreen -ReturnContext
Write-LogInfo -Message 'Starting run' -LogContext `$ctx
Write-LogWarning -Message 'Using fallback configuration' -TimestampPosition Front -LogContext `$ctx
Write-LogInfo -Message 'Completed step 1' -TimestampPosition Back -LogContext `$ctx
Stop-Log -LogContext `$ctxCreates one log file per run.
Example output path:
log\2026-08-15_214530.log
Creates nested year and month folders, then writes a timestamped file for each run.
Example output path:
log\2026\2026-08\2026-08-15_214530.log
Use this when you want a clean archive layout for long-running or recurring automation.
Writes all runs for the same day into a shared daily log.
Example output path:
log\2026\2026-08\2026-08-15.log
When the file already exists, the module appends a run separator unless -DisableDailySeparator is used.
`$ctx = Start-Log -Style Standard -LogDir .\log -Title 'Nightly Job' -Version '2.3' -ReturnContext
Write-LogInfo -Message 'Job started' -LogContext `$ctx
Write-LogInfo -Message 'Import complete' -TimestampPosition Back -LogContext `$ctx
Stop-Log -LogContext `$ctx`$ctx = Start-Log -Style Daily -LogDir .\log -Title 'Daily Sync' -ReturnContext
Write-LogInfo -Message 'Sync started' -TimestampPosition Front -LogContext `$ctx
Write-LogWarning -Message 'Remote system responded slowly' -LogContext `$ctx
Stop-Log -LogContext `$ctx`$ctx = Start-Log -Style Simple -LogDir .\log -Title 'Deployment' -ReturnContext
Write-LogError -Message 'Deployment failed' -TimestampPosition Back -ToScreen -LogContext `$ctx
Stop-Log -LogContext `$ctxTimestamps are optional and controlled by the -TimestampPosition parameter.
-TimestampPosition None(default): message is written as-is-TimestampPosition Front: timestamp is prepended-TimestampPosition Back: timestamp is appended
This behavior is covered by Pester tests for Write-LogInfo, Write-LogWarning, and Write-LogError, including invalid value rejection.
Example:
Write-LogInfo -Message 'Processing item' -TimestampPosition Front
Write-LogWarning -Message 'Retrying request' -TimestampPosition Back| Function | Purpose |
|---|---|
Start-Log |
Initializes the log path and writes the run header |
Write-LogInfo |
Appends informational messages |
Write-LogWarning |
Appends warning messages |
Write-LogError |
Appends error messages and can optionally stop execution |
Stop-Log |
Writes footer information and returns a status; use -Exit to terminate the caller |
Send-Log |
Emails a completed log file through SMTP |
PSLogging2 now uses atomic append logic for log writes.
- Safer concurrent writes for
Simple,Standard, andDaily - Daily mode can be shared across multiple runs without the earlier append race
- Header and separator creation are also protected through the same log I/O helper approach
The repo includes a basic concurrency test:
Set-Location .\Tests
.\Test-ConcurrentDaily.ps1 -Jobs 8 -LinesPerJob 250Send-Log sends the full log body through .NET SmtpClient.
# Using explicit LogContext (preferred)
`$ctx = Start-Log -Style Standard -LogDir .\log -Title 'Nightly Job' -ReturnContext
Send-Log `
-SMTPServer 'smtp.example.com' `
-LogContext `$ctx `
-EmailFrom 'me@example.com' `
-EmailTo 'team@example.com' `
-EmailSubject 'Nightly Job Log'Notes:
- This currently uses legacy
SmtpClient - The full log is read into memory before sending
- Modern auth and large-log handling are future hardening items
-
Writer functions now prefer explicit
LogContextobjects returned byStart-Log -ReturnContextor created withNew-LogContext. -
Send-Logis functional but not fully enterprise-hardened yet (modern auth, large-log handling) -
Pipeline support for
Write-LogErroris not fully implemented and may be removed or revised -
Notes:
-
Stop-Logdoes not exit by default after writing the footer; pass-Exitto terminate the caller. -
Timestamp switches were replaced with
-TimestampPositionand writer functions now validateMessageinput.
Import-Module .\PSLogging2.psm1 -Force
Invoke-Pester .\Tests\PesterImport-Module .\PSLogging2.psm1 -Force
Invoke-Pester .\Tests\Pester\Timestamp.Tests.ps1Set-Location .\Tests
.\Test-ConcurrentDaily.ps1- Implementation roadmap:
Docs/plans.md - Review notes:
Docs/Review.md
Issues, fixes, and improvements are welcome. If you are planning a broader change, check Docs/plans.md first so the work lines up with the current roadmap.
This project is licensed under the terms in LICENSE.