Logger.psm1 0.2 by Joel Bennett 22 months ago (modification of post by Joel Bennett view diff)
View followups from Joel Bennett and Joel Bennett | diff | embed code: <script type="text/javascript" src="http://PoshCode.org/embed/1745"></script>download | new post
The simplest logger. In your script just import-module Logger and debug, verbose, warnings and errors are logged to file.
This is a simple wrapper around Log4Net which (by default) causes Write-Verbose, Write-Warning, Write-Debug, and Write-Error to log their output when called from (any) script.
By default it logs to file, but it can log to the event log, console, .net trace, etc by simply using the Get-Logger function to configure new loggers (help is next)
There are a few extra helper methods in here, including Push-Context/Pop-Context (which you can call in your functions to enable stack tracing), and still more to come.
- <#
- Name : Universal Log4Net Logging Module (Logger.psm1)
- Version : 0.2
- Author : Joel Bennett (MVP)
- Site : http://www.HuddledMasses.org/
- Version History:
- 0.2 - Configless release.
- Now configures with inline XML, and supports switches to create "reasonable" default loggers
- Changed all the functions to Write-*Log so they don't overwrite the cmdlets
- Added -Logger parameter to take the name of the logger to use (it must be created beforehand via Get-Logger)
- Created aliases for Write-* to override the cmdlets -- these are easy for users to remove without breaking the module
- ** NEED to write some docs, but basically, this is stupid simple to use, just:
- Import-Module Logger
- Write-Verbose "This message will be saved in your profile folder in a file named PowerShellLogger.log (by default)"
- To change the defaults for your system, edit the last line in the module!!
- 0.1 - Initial release. http://poshcode.org/1744 (Required config: http://poshcode.org/1743)
- Uses Log4Net : http`://logging.apache.org/log4net/download.html
- Documentation: http`://logging.apache.org/log4net/release/sdk/
- NOTES:
- By default, this overwrites the Write-* cmdlets for Error, Warning, Debug, Verbose, and even Host.
- This means that you may end up logging a lot of stuff you didn't intend to log (ie: verbose output from other scripts)
- To avoid this behavior, remove the aliases after importing it
- Import-Module Logger; Remove-Item Alias:Write-*
- Write-Warning "This is your warning"
- Write-Debug "You should know that..."
- Write-Verbose "Everything would be logged, otherwise"
- ***** NOTE: IT ONLY OVERRIDES THE DEFAULTS FOR SCRIPTS *****
- It currently has no effect on error/verbose/warning that is logged from cmdlets.
- #>
- Add-Type -Path $PSScriptRoot\log4net.dll
- function Get-Logger {
- param(
- [Parameter(Mandatory=$false)]
- [string]$LoggerName = "*"
- ,
- [Parameter(Mandatory=$false)]
- [ValidateSet("DEBUG","INFO","WARN","ERROR","FATAL","VERBOSE","HOST","WARNING")]
- [string]$LogLevel = "DEBUG"
- ,
- [Parameter(Mandatory=$false)]
- [string]$LogFolder = $PSScriptRoot
- , [Switch]$Force
- , [Switch]$Console
- , [Switch]$EventLog
- , [Switch]$Trace
- , [Switch]$File
- , [Switch]$RollingFile
- )
- $Script:Logger = [log4net.LogManager]::GetCurrentLoggers() | Where-Object { $_.Logger.Name -Like $LoggerName }
- if(!$script:Logger -or $Force -and $LoggerName -ne "*") {
- if($LogLevel -eq "VERBOSE") { $LogLevel = "INFO" }
- if($LogLevel -eq "HOST") { $LogLevel = "INFO" }
- if($LogLevel -eq "WARNING") { $LogLevel = "WARN" }
- $AppenderRefs = ''
- if($EventLog) { $AppenderRefs += "<appender-ref ref=""EventLogAppender"" />`n" }
- if($Trace) { $AppenderRefs += "<appender-ref ref=""TraceAppender"" />`n" }
- if($File) { $AppenderRefs += "<appender-ref ref=""FileAppender"" />`n" }
- if($RollingFile) { $AppenderRefs += "<appender-ref ref=""RollingFileAppender"" />`n" }
- if($Console -or ($AppenderRefs.Length -eq 0)) { $AppenderRefs += "<appender-ref ref=""ColoredConsoleAppender"" />`n" }
- $Script:Logger = [log4net.LogManager]::GetLogger($LoggerName)
- [xml]$config = @"
- <log4net>
- <appender name="ColoredConsoleAppender" type="log4net.Appender.ColoredConsoleAppender">
- <mapping>
- <level value="FATAL" />
- <foreColor value="Red, HighIntensity" />
- <backColor value="White, HighIntensity" />
- </mapping>
- <mapping>
- <level value="ERROR" />
- <foreColor value="Red, HighIntensity" />
- </mapping>
- <mapping>
- <level value="DEBUG" />
- <foreColor value="Green, HighIntensity" />
- </mapping>
- <mapping>
- <level value="INFO" />
- <foreColor value="Cyan, HighIntensity" />
- </mapping>
- <mapping>
- <level value="WARN" />
- <foreColor value="Yellow, HighIntensity" />
- </mapping>
- <layout type="log4net.Layout.PatternLayout">
- <conversionPattern value="%date %-5level %logger [%property{NDC}] - %message%newline" />
- </layout>
- </appender>
- <appender name="EventLogAppender" type="log4net.Appender.EventLogAppender" >
- <applicationName value="$LoggerName" />
- <layout type="log4net.Layout.PatternLayout">
- <conversionPattern value="%date %-5level %logger [%property{NDC}] - %message%newline" />
- </layout>
- </appender>
- <appender name="TraceAppender" type="log4net.Appender.TraceAppender">
- <layout type="log4net.Layout.PatternLayout">
- <conversionPattern value="%date %-5level %logger [%property{NDC}] - %message%newline" />
- </layout>
- </appender>
- <appender name="FileAppender" type="log4net.Appender.FileAppender">
- <file value="$LogFolder\$LoggerName.Log" />
- <appendToFile value="true" />
- <layout type="log4net.Layout.PatternLayout">
- <conversionPattern value="%date %-5level %logger [%property{NDC}] - %message%newline" />
- </layout>
- </appender>
- <appender name="RollingFileAppender" type="log4net.Appender.RollingFileAppender">
- <file value="$LogFolder\$LoggerName.Log" />
- <appendToFile value="true" />
- <maximumFileSize value="100KB" />
- <maxSizeRollBackups value="2" />
- <layout type="log4net.Layout.PatternLayout">
- <conversionPattern value="%date %-5level %logger [%property{NDC}] - %message%newline" />
- </layout>
- </appender>
- <root>
- <level value="DEBUG" />
- </root>
- <logger name="$LoggerName">
- <level value="$LogLevel" />
- $AppenderRefs
- </logger>
- </log4net>
- "@
- [log4net.Config.XmlConfigurator]::Configure( $config.log4net )
- }
- return $Script:Logger
- }
- function Set-Logger {
- param(
- [Parameter(Mandatory=$true, ValueFromPipeline=$true)]
- [log4net.Core.LogImpl]$Logger
- )
- $script:Logger = $Logger
- }
- function Push-LogContext {
- param(
- [Parameter(Mandatory=$true)]
- [string]$Name
- )
- [log4net.NDC]::Push($Name)
- }
- function Pop-LogContext {
- [log4net.NDC]::Pop()
- }
- function Write-DebugLog {
- [CmdletBinding()]
- param(
- [Parameter(Mandatory=$true, Position=0, ValueFromPipeline=$true)]
- [Alias('Msg')]
- [AllowEmptyString()]
- [System.String]
- ${Message}
- ,
- [Parameter(Mandatory=$false, Position=99)]
- ${Logger})
- begin
- {
- try {
- if($PSBoundParameters.ContainsKey("Logger")) {
- if($Logger -is [log4net.Core.LogImpl]) { Set-Logger $Logger } else { $script:Logger = Get-Logger "$Logger" }
- $null = $PSBoundParameters.Remove("Logger")
- }
- $outBuffer = $null
- if ($PSBoundParameters.TryGetValue('OutBuffer', [ref]$outBuffer))
- {
- $PSBoundParameters['OutBuffer'] = 1
- }
- $wrappedCmd = $ExecutionContext.InvokeCommand.GetCommand('Write-Debug', [System.Management.Automation.CommandTypes]::Cmdlet)
- $scriptCmd = {& $wrappedCmd @PSBoundParameters }
- $steppablePipeline = $scriptCmd.GetSteppablePipeline($myInvocation.CommandOrigin)
- $steppablePipeline.Begin($PSCmdlet)
- } catch {
- throw
- }
- }
- process
- {
- try {
- $script:logger.debug($Message) #Write-Debug
- $steppablePipeline.Process($_)
- } catch {
- throw
- }
- }
- end
- {
- try {
- $steppablePipeline.End()
- } catch {
- throw
- }
- }
- <#
- .ForwardHelpTargetName Write-Debug
- .ForwardHelpCategory Cmdlet
- #>
- }
- function Write-VerboseLog {
- [CmdletBinding()]
- param(
- [Parameter(Mandatory=$true, Position=0, ValueFromPipeline=$true)]
- [Alias('Msg')]
- [AllowEmptyString()]
- [System.String]
- ${Message}
- ,
- [Parameter(Mandatory=$false, Position=99)]
- ${Logger})
- begin
- {
- try {
- if($PSBoundParameters.ContainsKey("Logger")) {
- if($Logger -is [log4net.Core.LogImpl]) { Set-Logger $Logger } else { $script:Logger = Get-Logger "$Logger" }
- $null = $PSBoundParameters.Remove("Logger")
- }
- $outBuffer = $null
- if ($PSBoundParameters.TryGetValue('OutBuffer', [ref]$outBuffer))
- {
- $PSBoundParameters['OutBuffer'] = 1
- }
- $wrappedCmd = $ExecutionContext.InvokeCommand.GetCommand('Write-Verbose', [System.Management.Automation.CommandTypes]::Cmdlet)
- $scriptCmd = {& $wrappedCmd @PSBoundParameters }
- $steppablePipeline = $scriptCmd.GetSteppablePipeline($myInvocation.CommandOrigin)
- $steppablePipeline.Begin($PSCmdlet)
- } catch {
- throw
- }
- }
- process
- {
- try {
- $script:logger.info($Message)
- $steppablePipeline.Process($_)
- } catch {
- throw
- }
- }
- end
- {
- try {
- $steppablePipeline.End()
- } catch {
- throw
- }
- }
- <#
- .ForwardHelpTargetName Write-Verbose
- .ForwardHelpCategory Cmdlet
- #>
- }
- function Write-WarningLog {
- [CmdletBinding()]
- param(
- [Parameter(Mandatory=$true, Position=0, ValueFromPipeline=$true)]
- [Alias('Msg')]
- [AllowEmptyString()]
- [System.String]
- ${Message}
- ,
- [Parameter(Mandatory=$false, Position=99)]
- ${Logger})
- begin
- {
- try {
- if($PSBoundParameters.ContainsKey("Logger")) {
- if($Logger -is [log4net.Core.LogImpl]) { Set-Logger $Logger } else { $script:Logger = Get-Logger "$Logger" }
- $null = $PSBoundParameters.Remove("Logger")
- }
- $outBuffer = $null
- if ($PSBoundParameters.TryGetValue('OutBuffer', [ref]$outBuffer))
- {
- $PSBoundParameters['OutBuffer'] = 1
- }
- $wrappedCmd = $ExecutionContext.InvokeCommand.GetCommand('Write-Warning', [System.Management.Automation.CommandTypes]::Cmdlet)
- $scriptCmd = {& $wrappedCmd @PSBoundParameters }
- $steppablePipeline = $scriptCmd.GetSteppablePipeline($myInvocation.CommandOrigin)
- $steppablePipeline.Begin($PSCmdlet)
- } catch {
- throw
- }
- }
- process
- {
- try {
- $script:logger.warn($Message) #Write-Warning
- $steppablePipeline.Process($_)
- } catch {
- throw
- }
- }
- end
- {
- try {
- $steppablePipeline.End()
- } catch {
- throw
- }
- }
- <#
- .ForwardHelpTargetName Write-Warning
- .ForwardHelpCategory Cmdlet
- #>
- }
- function Write-ErrorLog {
- [CmdletBinding(DefaultParameterSetName='NoException')]
- param(
- [Parameter(ParameterSetName='WithException', Mandatory=$true)]
- [System.Exception]
- ${Exception},
- [Parameter(ParameterSetName='NoException', Mandatory=$true, Position=0, ValueFromPipeline=$true)]
- [Parameter(ParameterSetName='WithException')]
- [Alias('Msg')]
- [AllowNull()]
- [AllowEmptyString()]
- [System.String]
- ${Message},
- [Parameter(ParameterSetName='ErrorRecord', Mandatory=$true)]
- [System.Management.Automation.ErrorRecord]
- ${ErrorRecord},
- [Parameter(ParameterSetName='NoException')]
- [Parameter(ParameterSetName='WithException')]
- [System.Management.Automation.ErrorCategory]
- ${Category},
- [Parameter(ParameterSetName='WithException')]
- [Parameter(ParameterSetName='NoException')]
- [System.String]
- ${ErrorId},
- [Parameter(ParameterSetName='NoException')]
- [Parameter(ParameterSetName='WithException')]
- [System.Object]
- ${TargetObject},
- [System.String]
- ${RecommendedAction},
- [Alias('Activity')]
- [System.String]
- ${CategoryActivity},
- [Alias('Reason')]
- [System.String]
- ${CategoryReason},
- [Alias('TargetName')]
- [System.String]
- ${CategoryTargetName},
- [Alias('TargetType')]
- [System.String]
- ${CategoryTargetType}
- ,
- [Parameter(Mandatory=$false, Position=99)]
- ${Logger})
- begin
- {
- try {
- if($PSBoundParameters.ContainsKey("Logger")) {
- if($Logger -is [log4net.Core.LogImpl]) { Set-Logger $Logger } else { $script:Logger = Get-Logger "$Logger" }
- $null = $PSBoundParameters.Remove("Logger")
- }
- $outBuffer = $null
- if ($PSBoundParameters.TryGetValue('OutBuffer', [ref]$outBuffer))
- {
- $PSBoundParameters['OutBuffer'] = 1
- }
- $wrappedCmd = $ExecutionContext.InvokeCommand.GetCommand('Write-Error', [System.Management.Automation.CommandTypes]::Cmdlet)
- $scriptCmd = {& $wrappedCmd @PSBoundParameters }
- $steppablePipeline = $scriptCmd.GetSteppablePipeline($myInvocation.CommandOrigin)
- $steppablePipeline.Begin($PSCmdlet)
- } catch {
- throw
- }
- }
- process
- {
- try {
- $script:logger.error($Message,$Exception) #Write-Error
- $steppablePipeline.Process($_)
- } catch {
- throw
- }
- }
- end
- {
- try {
- $steppablePipeline.End()
- } catch {
- throw
- }
- }
- <#
- .ForwardHelpTargetName Write-Error
- .ForwardHelpCategory Cmdlet
- #>
- }
- function Write-HostLog {
- [CmdletBinding()]
- param(
- [Parameter(Position=0, ValueFromPipeline=$true, ValueFromRemainingArguments=$true)]
- [System.Object]
- ${Object},
- [Switch]
- ${NoNewline},
- [System.Object]
- ${Separator} = $OFS,
- [System.ConsoleColor]
- ${ForegroundColor},
- [System.ConsoleColor]
- ${BackgroundColor}
- ,
- [Parameter(Mandatory=$false, Position=99)]
- ${Logger})
- begin
- {
- try {
- if($PSBoundParameters.ContainsKey("Logger")) {
- if($Logger -is [log4net.Core.LogImpl]) { Set-Logger $Logger } else { $script:Logger = Get-Logger "$Logger" }
- $null = $PSBoundParameters.Remove("Logger")
- }
- $outBuffer = $null
- if ($PSBoundParameters.TryGetValue('OutBuffer', [ref]$outBuffer))
- {
- $PSBoundParameters['OutBuffer'] = 1
- }
- $wrappedCmd = $ExecutionContext.InvokeCommand.GetCommand('Write-Host', [System.Management.Automation.CommandTypes]::Cmdlet)
- $scriptCmd = {& $wrappedCmd @PSBoundParameters }
- $steppablePipeline = $scriptCmd.GetSteppablePipeline($myInvocation.CommandOrigin)
- $steppablePipeline.Begin($PSCmdlet)
- } catch {
- throw
- }
- }
- process
- {
- try {
- $script:logger.info(($Object -join $Separator)) #Write-Verbose
- $steppablePipeline.Process($_)
- } catch {
- throw
- }
- }
- end
- {
- try {
- $steppablePipeline.End()
- } catch {
- throw
- }
- }
- <#
- .ForwardHelpTargetName Write-Host
- .ForwardHelpCategory Cmdlet
- #>
- }
- Set-Alias Write-Debug Write-DebugLog
- Set-Alias Write-Verbose Write-VerboseLog
- Set-Alias Write-Warning Write-WarningLog
- Set-Alias Write-Error Write-ErrorLog
- #Set-Alias Write-Host Write-HostLog
- Export-ModuleMember -Function * -Alias *
- $script:Logger = Get-Logger "PowerShellLogger" -RollingFile -LogFolder (Split-Path $Profile.CurrentUserAllHosts)
- ## THIS IS THE DEFAULT LOGGER. CONFIGURE AS YOU SEE FIT
Submit a correction or amendment below (click here to make a fresh posting)
After submitting an amendment, you'll be able to view the differences between the old and new posts easily.
PowerShell Code Repository