In my home network, I run a Graylog Syslog instance in Docker for logging network and Linux events. But you can also log events from PowerShell scripts to Syslog for easy filtering or correlation. In this blog post, I will show you how that works.
What is Syslog?
“In computing, syslog (/ˈsɪslɒɡ/) is a standard for message logging. It allows separation of the software that generates messages, the system that stores them, and the software that reports and analyzes them. Each message is labeled with a facility code, indicating the type of system generating the message, and is assigned a severity level.
Computer system designers may use syslog for system management and security auditing as well as general informational, analysis, and debugging messages. A wide variety of devices, such as printers, routers, and message receivers across many platforms, use the syslog standard. This permits the consolidation of logging data from different types of systems in a central repository. Implementations of syslog exist for many operating systems.
When operating over a network, syslog uses a client-server architecture where a syslog server listens for and logs messages coming from clients.”
Source: https://en.wikipedia.org/wiki/Syslog
What does the POSH-SYSLOG module do?
“A module for sending SYSLOG messages from PowerShell.
The module supports RFC5424 and RFC3164, and can send messages via TCP and UDP.
Authored by Kieran Jacobsen”
Source: https://github.com/poshsecurity/Posh-SYSLOG
How to use
Installation
You can install it from the PowerShell gallery using this:
Install-Module -Name Posh-SYSLOG
Or, when you have PSResourceGet installed:
Install-PSResource -Name Posh-SYSLOG
After installation, you will have this Cmdlet available:

Parameters
-Server <String>
Destination SYSLOG server that message is to be sent to.
Required? true
Position? named
Default value
Accept pipeline input? false
Aliases
Accept wildcard characters? false
-Message <String>
Our message or content that we want to send to the server. This is option in RFC 5424, the CMDLet still has this
as a madatory parameter, to send no message, simply specifiy '-' (as per RFC).
Required? true
Position? named
Default value
Accept pipeline input? true (ByPropertyName)
Aliases
Accept wildcard characters? false
-Severity
Severity level as defined in SYSLOG specification, must be of ENUM type Syslog_Severity
Required? true
Position? named
Default value
Accept pipeline input? true (ByPropertyName)
Aliases
Accept wildcard characters? false
-Facility
Facility of message as defined in SYSLOG specification, must be of ENUM type Syslog_Facility
Required? true
Position? named
Default value
Accept pipeline input? true (ByPropertyName)
Aliases
Accept wildcard characters? false
-Hostname <String>
Hostname of machine the message is about, if not specified, RFC 5425 selection rules will be followed.
Required? false
Position? named
Default value
Accept pipeline input? false
Aliases
Accept wildcard characters? false
-ApplicationName <String>
Specify the name of the application or script that is sending the mesage. If not specified, will select the ScriptName,
or if empty, powershell.exe will be sent. To send Null, specify '-' to meet RFC 5424.
Required? false
Position? named
Default value
Accept pipeline input? true (ByPropertyName)
Aliases
Accept wildcard characters? false
-Timestamp <DateTime>
Time and date of the message, must be of type DateTime. Correct format will be selected depending on RFC requested.
If not specified, will call get-date to get appropriate date time.
Required? false
Position? named
Default value (Get-Date)
Accept pipeline input? true (ByPropertyName)
Aliases
Accept wildcard characters? false
-Port <UInt16>
SYSLOG UDP (or TCP) port to which to send the message. Defaults to 514, if not specified.
Required? false
Position? named
Default value 514
Accept pipeline input? true (ByPropertyName)
Aliases
Accept wildcard characters? false
-Transport
Transport protocol (TCP or UDP or TCP with TLS) over which the message will be sent. Default is UDP.
[ValidateSet('UDP','TCP', 'TCPwithTLS')]
[String]
Required? false
Position? named
Default value UDP
Accept pipeline input? true (ByPropertyName)
Aliases
Accept wildcard characters? false
-ProcessID <String>
ProcessID or PID of generator of message. Will automatically use $PID global variable. If you want to override
this and send null, specify '-' to meet RFC 5424 rquirements.
Required? false
Position? named
Default value $PID
Accept pipeline input? true (ByPropertyName)
Aliases
Accept wildcard characters? false
-MessageID <String>
Error message or troubleshooting number associated with the message being sent. If you want to override this and
send null, specify '-' to meet RFC 5424 rquirements.
Required? false
Position? named
Default value -
Accept pipeline input? true (ByPropertyName)
Aliases
Accept wildcard characters? false
-StructuredData <String>
Key Pairs of structured data as a string as defined in RFC5424. Default will be '-' which means null.
Required? false
Position? named
Default value -
Accept pipeline input? true (ByPropertyName)
Aliases
Accept wildcard characters? false
-FramingMethod <String>
Framing method used for the message, default is 'Octet-Counting' (see RFC6587 section 3.4). This only applies when
TCP is used for transport (no effect on UDP messages).
Required? false
Position? named
Default value Octet-Counting
Accept pipeline input? true (ByPropertyName)
Aliases
Accept wildcard characters? false
-SslProtocols
SSL/TLS Protocols to be used when connecting to server. Default is TLS1.2.
Required? false
Position? named
Default value Tls12
Accept pipeline input? true (ByPropertyName)
Aliases
Accept wildcard characters? false
-DoNotValidateTLSCertificate [<SwitchParameter>]
Do not validate the SSL/TLS certificate presented by the server.
Required? false
Position? named
Default value False
Accept pipeline input? true (ByPropertyName)
Aliases
Accept wildcard characters? false
-RFC3164 [<SwitchParameter>]
Send an RFC3164 fomatted message instead of RFC5424.
Required? true
Position? named
Default value False
Accept pipeline input? true (ByPropertyName)
Aliases
Accept wildcard characters? false
<CommonParameters>
This cmdlet supports the common parameters: Verbose, Debug,
ErrorAction, ErrorVariable, WarningAction, WarningVariable,
OutBuffer, PipelineVariable, and OutVariable. For more information, see
about_CommonParameters (https://go.microsoft.com/fwlink/?LinkID=113216).
Facility and Severity level
You can specify more details using the -Facility and -Severity Parameters, following the standards described in the Wiki link above. You can auto-complete, CTRL+Space them, but these are the ones that you can use with the details:

and

Examples
Line in script
You can use the Cmdlet in your script so that instead of writing output to a log file or screen, you can send it to your Syslog server like this:
Send-SyslogMessage -Server 192.168.168.192 -Message "PowerShell is fun!" -Severity Critical -Facility user -ApplicationName PowerShell -Port 1514 -Transport UDP -Hostname P16SG2 -MessageID 1
The message will look like this in your SYSLOG server (In my case, Graylog):

As a Function
You can use the Send-SyslogMessage in a small Function, which makes it easier to use in larger scripts. For example:
# You need to install the POSH-SYSLOG module first
# https://www.powershellgallery.com/packages/Posh-SYSLOG/4.1.5
function Write-Log {
param (
[Parameter(Mandatory = $true)][string]$Message,
[Parameter(Mandatory = $false)][validateset('Emergency', 'Alert', 'Critical', 'Error', 'Warning', 'Notice', 'Info', 'Debug')][string]$Severity = 'Info',
[Parameter(Mandatory = $false)][validateset('auth', 'clock', 'daemon', 'kern', 'local1', 'local3', 'local5', 'local7', 'logaudit', 'mail', 'ntp', 'user', 'authpriv', 'cron', 'ftp', 'local0', 'local2', 'local4', 'local6', 'logalert', 'lpr', ' news', 'syslog', 'uucp')][string]$Facility = 'User'
)
Send-SyslogMessage -Server 192.168.168.192 -Port 1514 -Transport UDP -Message $Message -Severity $Severity -Facility $Facility -Hostname $env:COMPUTERNAME -Timestamp (Get-Date) -ProcessID $PID -MessageID 1
}
This will look like this after running Write-Log -Message “PowerShell is fun!”

Because I didn’t use the -Facility or -Severity Parameter, it used the defaults (User and Info). The timestamp was from Get-Date, the Process ID was from VSCode’s PID, the ComputerName from $ENV:COMPUTERNAME, and the nice thing is… It also logs the script that it was run from (That’s the -ApplicationName Parameter from the Send-SysLogMessage Cmdlet)
Wrapping up
And that’s how you log messages into your SYSLOG server using the POSH-SYSLOG module. I showed how you can use it from the command line or as a nice, small function for easy usage. Have a lovely weekend!