SeqLogger.psm1
|
function Send-SeqEvent { <# .SYNOPSIS Send an event to a Seq server. .INPUTS System.Collections.Hashtable or System.Collections.Specialized.OrderedDictionary or System.Data.DataRow or an object .FUNCTIONALITY Seq .LINK Invoke-RestMethod .LINK https://getseq.net/ .EXAMPLE Send-SeqEvent 'Hello from PowerShell' -Server http://my-seq -LiteralMessage .EXAMPLE Send-SeqEvent 'Event: {User} on {Machine}' @{ User = $env:UserName; Machine = $env:ComputerName } -Server http://my-seq .EXAMPLE Send-SeqEvent -Properties @{ Message = $Error[0].Exception.Message } -Level Error -Server http://my-seq #> [CmdletBinding()][OutputType([void])] Param( <# The text to use as the log message, a Seq template unless -LiteralMessage is present. By default, the value of the Message property will be used. #> [Parameter(Position=0)][Alias('Text')][string] $Message = '{Message}', <# Logging properties to record in Seq, as an OrderedDictionary, Hashtable, DataRow, or any object with properties to use. #> [Parameter(Mandatory=$true,Position=1,ValueFromPipeline=$true)][Alias('Parameters')] $Properties, <# The type of event to record. Information by default. #> [ValidateSet('Verbose','Debug','Information','Warning','Error','Fatal')][string] $Level = 'Information', # The URL of the Seq server. [uri] $Server, # The Seq API key to use. [string] $ApiKey, # When present, indicates the Message parameter is to be used verbatim, not as a Seq template. [switch] $LiteralMessage ) Process { if($LiteralMessage) { $Properties += @{Message=$Message}; $Message = "{Message}" } Invoke-RestMethod -Uri (New-Object uri ([uri]$Server,"/api/events/raw?apiKey=$ApiKey")) ` -Method POST -ContentType application/json -Body (@{ Events = @( @{ Timestamp = Get-Date -Format o Level = $Level MessageTemplate = $Message Properties = $Properties } ) } |ConvertTo-Json -Depth 5 -Compress) |Write-Verbose } } function Send-SeqScriptEvent { <# .SYNOPSIS Sends an event (often an error) from a script to a Seq server, including script info. .FUNCTIONALITY Seq .LINK Send-SeqEvent .LINK https://getseq.net/ .EXAMPLE try { Connect-Thing } catch { Send-SeqScriptEvent.ps1 'Trying to connect' $_ -Level Error -Server http://my-seq } #> [CmdletBinding()][OutputType([void])] Param( # A description of what was being attempted. [Parameter(Position=0,Mandatory=$true)][string]$Action, <# An optional PowerShell ErrorRecord object to record. Will try to automatically find $_ in a calling "catch{}"" block. #> [Parameter(Position=1)][Management.Automation.ErrorRecord]$ErrorRecord = ((Get-Variable _ -Scope 1 -ValueOnly -EA SilentlyContinue) -as [Management.Automation.ErrorRecord]), <# The type of event to record. Defaults to Error if an ErrorRecord is found, Information otherwise. #> [Parameter(Position=2)][ValidateSet('Verbose','Debug','Information','Warning','Error','Fatal')][string] $Level = 'Error', <# The scope of the script InvocationInfo to use. Defaults to 1 (the script calling Send-SeqScriptEvent.ps1). Sending a 2 will try to use the script calling the script calling this one. #> [Alias('Scope')][string] $InvocationScope = '1', # The URL of the Seq server. [uri] $Server, # The Seq API key to use. [string] $ApiKey ) if(!($ErrorRecord -or $PSBoundParameters.ContainsKey('Level'))) { $Level = 'Information' } $caller = try{Get-Variable MyInvocation -Scope $InvocationScope -ValueOnly -EA Stop}catch{$MyInvocation} $SeqEvent = @{ Level = $Level } if($Server){[void]$SeqEvent.Add('Server',$Server)} if($ApiKey){[void]$SeqEvent.Add('ApiKey',$ApiKey)} $Properties = @{ Script = if($caller.ScriptName){Split-Path $caller.ScriptName -Leaf}else{$caller.MyCommand.Name} CommandName = $caller.MyCommand.Name Invocation = $caller Action = $Action CommandLine = [Environment]::GetCommandLineArgs() ComputerName = $env:COMPUTERNAME } if($ErrorRecord) { $Properties += @{ Message = $ErrorRecord.Exception.Message Error = $ErrorRecord } [void]$SeqEvent.Add('Message','{Script}: {Action}: {Message}') } else { [void]$SeqEvent.Add('Message','{Script}: {Action}') } [void]$SeqEvent.Add('Properties',$Properties) Send-SeqEvent @SeqEvent -WarningAction Ignore } function Use-SeqServer { <# .SYNOPSIS Set the default Server and ApiKey for Send-SeqEvent.ps1 .FUNCTIONALITY Seq .LINK https://getseq.net/ .EXAMPLE Use-SeqServer.ps1 http://my-seq $apikey #> [CmdletBinding()][OutputType([void])] Param( # The URL of the Seq server. [Parameter(Mandatory=$true)][uri] $Server, # The Seq API key to use. [string] $ApiKey ) Write-Verbose "Using Seq at $Server" $value = @{ 'Send-SeqEvent:Server' = $Server } if($ApiKey) {$value['Send-SeqEvent:ApiKey'] = $ApiKey} $defaults = Get-Variable -Scope 2 -Name PSDefaultParameterValues -EA SilentlyContinue if($defaults) {$value.Keys |Where-Object {$defaults.Value.Contains($_)} |ForEach-Object {$defaults.Value.Remove($_)}; $defaults.Value += $value} else {Set-Variable -Scope 2 -Name PSDefaultParameterValues -Value $value} } Export-ModuleMember -Function Send-SeqEvent,Send-SeqScriptEvent,Use-SeqServer |