Skip to content

Instantly share code, notes, and snippets.

@sean-m
Created May 13, 2014 19:25
Show Gist options
  • Save sean-m/52a9bd4c265903a752d6 to your computer and use it in GitHub Desktop.
Save sean-m/52a9bd4c265903a752d6 to your computer and use it in GitHub Desktop.
Read Windows event logs with Get-WinEvent cmd-let and serialize to json for shipping with logstash-forwarder. Much lighter weight than using logstash with the eventlog codec. Runtime memory usage is ~30Mb vs ~320Mb. Note: must be run with elevated privileges to read Security event logs.
<#
Configuration for log-reader.ps1
This file is only read if log-reader.ps1 is invoked without arguments
from the command-line. This file will configure any tunable variabes
in log-reader.ps1. Thus far, the only setting is which logs to track.
#>
[string[]]$logname = $("Application", "System", "Security")
#Requires -Version 3
param ([string]$logname, [switch]$writelog)
##################################
# Functions #
##################################
function EvenSpace{
param ($word)
$tabWidth = 48
$wordTabs = $tabWidth - $word.Length
$tabNum = [Math]::Floor($($wordTabs/4)) / 2
("`t" * $tabNum)
}
## Read events, write to file
function ReadEvents {
param ([hashtable]$filter, [string]$OutFile=[String]::Empty)
## Make it look pretty if writting to stdout
try {
[object[]]$data = Get-WinEvent -FilterHashtable $filter -ErrorAction SilentlyContinue | sort RecordId
[int]$count = 0
if ((-not $data -eq $null) -or ($data.Count -gt 0)) {
$count = $data.Count
}
"Log: $($filter["LogName"])" + (EvenSpace -word $filter["LogName"]) + "Count: $count"
}
catch {
$Error[0]
Write-Host ""
Write-Host "Filter:"
$filter
return
}
if ($data.Count -gt 0) {
foreach ($event in $data) {
if (-not $writelog) {
$event | ConvertTo-Json | Write-Host
}
else {
$event | Add-Member -MemberType NoteProperty -Name timestamp -Value $($event.TimeCreated | Get-Date -Format o) | ConvertTo-Json -Compress | Out-File -FilePath $OutFile -Encoding utf8 -Append
}
}
}
}
##################################
# Setup #
##################################
if ([String]::IsNullOrEmpty($logname)) {
$writelog = $true
try {
. .\log-reader-config.ps1
}
catch {
Write-Warning "Can't read config file, try that again after you've gotten yourself situated."
exit 1
}
}
## Setup logfile and time tracking filenames
if ($writelog) {
if ($logname.Count -gt 1) {
$output = "log\events.log"
$timefile = "log\events.time"
}
else{
$output = "log\$logname.log"
$timefile = "log\$logname.time"
}
}
if (-not $writelog) {
Write-Warning "Not writing log file"
}
else {
Write-Host "Writing to: $output" -ForegroundColor Cyan
## Setup log directory
$checkPath = Test-Path -Path $(Split-Path -Parent -Path $output)
if (-not $checkPath) {
New-Item -Path $(Split-Path -Parent -Path $output) -ItemType Directory
}
## Check for timefile and set $time to where we left off
$endTime = New-Object -TypeName DateTime
if (-not [String]::IsNullOrEmpty($timefile)) {
if ($(Test-Path -Path $timefile)) {
$stub = $(Get-Content $timefile) -join "`n" | ConvertFrom-Csv
[DateTime]$endTime = Get-Date $stub.DateTime
}
else {
$endTime = Get-Date
}
}
Write-Host "Starting reading logs from: $endTime"
}
##################################
# Main Logic #
##################################
## Loop to capture events
while ($true) {
[String]::Empty | Write-Host
Start-Sleep -Seconds 5
$startTime = $endTime
[TimeSpan]$diff = (Get-Date) - $startTime
if ($diff.TotalHours -gt 1) {
$endTime = $startTime + (New-TimeSpan -Minutes 30)
}
else {
$endTime = Get-Date
}
Write-Host "Starting timespan $($startTime) -> $($endTime)"
## Supports reading multiple logs
if ($logname.Count -gt 1) {
foreach ($log in $logname) {
ReadEvents -filter @{LogName=$log; StartTime=$startTime; EndTime=$endTime} -OutFile $output
}
}
else {
ReadEvents -filter @{LogName=$logname; StartTime=$startTime; EndTime=$endTime} -OutFile $output
}
if ($writelog) {
$endTime | ConvertTo-Csv | Out-File $timefile
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment