Skip to content

Commit 7e77de8

Browse files
committed
Update file: Last errors logs.ps1
1 parent e11d30d commit 7e77de8

1 file changed

Lines changed: 118 additions & 109 deletions

File tree

Lines changed: 118 additions & 109 deletions
Original file line numberDiff line numberDiff line change
@@ -1,79 +1,114 @@
11
<#
22
.SYNOPSIS
3-
This script retrieves and processes error events from the Windows Event Log within the last 48 and 12 hours.
3+
Monitors Windows 'System' event logs and reports error events with configurable thresholds.
44
55
.DESCRIPTION
6-
This script is useful for monitoring and alerting on error events in the Windows Event Log.
7-
The script processes error logs from the 'System' log only, only critical errors are counted and displayed.
8-
9-
1. Retrieves the last 20 error events from the 'System' log in the last 48 hours, excluding specified event IDs.
10-
2. Counts and displays the number of error events found in the last 48 hours (after filtering out ignored events).
11-
3. Retrieves error events from the last 12 hours and checks if there are 4 or more errors.
12-
4. If 4 or more errors are found in the last 12 hours, the script exits with an error code (1).
13-
5. If fewer than 4 errors are found, the script exits with a success code (0).
14-
15-
.EXEMPLE
16-
debug=true
6+
This script retrieves error events from the Windows 'System' log over a configurable lookback period
7+
(default 48 hours) and evaluates them within a configurable evaluation window
8+
(default 12 hours). It filters out events by specified Event IDs and keywords.
9+
10+
The script supports three severity thresholds (set unrealistic threshold to disable):
11+
- INFO: default 1 event
12+
- WARN: default 2 events
13+
- ERROR: default 4 events
14+
15+
Behavior:
16+
1. Retrieves error events (Level=2) from the 'System' log within the lookback period.
17+
2. Filters out ignored Event IDs and keywords (defaults or via environment variables).
18+
3. Evaluates events within the evaluation window:
19+
- If count >= ERROR threshold, exits with ERROR exit code (3).
20+
- If count >= WARN threshold, exits with WARN exit code (2).
21+
- Otherwise, exits with INFO exit code (1).
22+
4. Debug mode outputs filtered events and thresholds.
23+
24+
.EXAMPLE
25+
DEBUG=true
1726
FILTER_ID=1111,22222,3333
1827
FILTER_KEYWORD=keyword1,keyword2
28+
INFO_THRESHOLD=1
29+
WARN_THRESHOLD=2
30+
ERROR_THRESHOLD=4
31+
LOOKBACK_HOURS=72
32+
EVALUATION_WINDOW_HOURS=24
1933
2034
.NOTES
2135
Author: SAN
2236
Date: 24.10.2024
23-
#public
24-
25-
10016 safe to ignore
26-
https://learn.microsoft.com/en-us/troubleshoot/windows-client/application-management/event-10016-logged-when-accessing-dcom
27-
36874 to ignore
28-
Fixing the issue would be more dangerous than leaving it be it would require blocking tls 1.2 and forcing 1.1 with unsafe cyphers and loosing connection to devices that do not support 1.1
37+
#PUBLIC
38+
Default ignored Event IDs:
39+
10016 - safe to ignore, see:
40+
https://learn.microsoft.com/en-us/troubleshoot/windows-client/application-management/event-10016-logged-when-accessing-dcom
41+
36874 - ignored due to TLS/connection constraints
2942
3043
.CHANGELOG
31-
04.12.24 SAN added id to ignore in comma separeted variable
32-
12.12.24 SAN adding keyword filters, added filter addition via env var
33-
34-
.TODO
35-
Set 20 Error Events and 48 hours in vars same for 4 and 12
36-
Re-thing the thresholds to add info warn error limits
44+
04.12.24 SAN: Added environment variable support for ignored Event IDs.
45+
12.12.24 SAN: Added keyword filters and support for dynamic filter addition via environment variables.
46+
02.04.26 SAN: Added configurable info/warn/error thresholds with exit codes.
3747
3848
#>
3949

40-
$defaultEventIds = @(10016,36874)
41-
$defaultKeywords = @("gupdate","anotherkeyword")
50+
$defaultEventIds = @(10016, 36874)
51+
$defaultKeywords = @("gupdate", "anotherkeyword")
4252

43-
$debug = [System.Environment]::GetEnvironmentVariable("DEBUG")
44-
$filterIdEnv = [System.Environment]::GetEnvironmentVariable("FILTER_ID")
45-
$filterKeywordEnv = [System.Environment]::GetEnvironmentVariable("FILTER_KEYWORD")
53+
$defaultInfoThreshold = 1
54+
$defaultWarnThreshold = 2
55+
$defaultErrorThreshold = 4
4656

47-
$ignoredEventIds = if ($filterIdEnv) {
48-
$filterIdEnv.Split(",") + $defaultEventIds
49-
} else {
50-
$defaultEventIds
51-
}
57+
$defaultLookbackHours = 48
58+
$defaultEvaluationWindowHours = 12
5259

53-
$ignoredKeywords = if ($filterKeywordEnv) {
54-
$filterKeywordEnv.Split(",") + $defaultKeywords
55-
} else {
56-
$defaultKeywords
57-
}
60+
$infoExitCode = 1
61+
$warnExitCode = 2
62+
$errorExitCode = 3
5863

59-
$start48h = (Get-Date).AddHours(-48)
60-
$start12h = (Get-Date).AddHours(-12)
64+
$debug = $env:DEBUG
65+
$filterIdEnv = $env:FILTER_ID
66+
$filterKeywordEnv = $env:FILTER_KEYWORD
6167

62-
$allErrors48h = Get-WinEvent -FilterHashtable @{LogName='System'; Level=2; StartTime=$start48h} -ErrorAction SilentlyContinue
68+
$infoThresholdEnv = $env:INFO_THRESHOLD
69+
$warnThresholdEnv = $env:WARN_THRESHOLD
70+
$errorThresholdEnv = $env:ERROR_THRESHOLD
6371

64-
$eventsWithIdFilter = $allErrors48h | Where-Object { $ignoredEventIds -contains $_.Id.ToString() }
72+
$lookbackEnv = $env:LOOKBACK_HOURS
73+
$evaluationEnv = $env:EVALUATION_WINDOW_HOURS
6574

66-
$eventsWithKeywordFilter = $allErrors48h | Where-Object {
67-
$eventData = $_.Properties -join " "
68-
$eventData += " " + $_.Message
69-
$keywordMatches = $false
70-
$ignoredKeywords | ForEach-Object {
71-
$keyword = $_.Trim()
72-
if ($eventData -match "(?i)\b$($keyword)\b") {
73-
$keywordMatches = $true
74-
}
75-
}
76-
$keywordMatches
75+
$ignoredEventIds = if ($filterIdEnv) { ($filterIdEnv.Split(",") | ForEach-Object { $_.Trim() }) + $defaultEventIds } else { $defaultEventIds }
76+
$ignoredKeywords = if ($filterKeywordEnv) { ($filterKeywordEnv.Split(",") | ForEach-Object { $_.Trim() }) + $defaultKeywords } else { $defaultKeywords }
77+
78+
$infoThreshold = if ($infoThresholdEnv) { [int]$infoThresholdEnv } else { $defaultInfoThreshold }
79+
$warnThreshold = if ($warnThresholdEnv) { [int]$warnThresholdEnv } else { $defaultWarnThreshold }
80+
$errorThreshold = if ($errorThresholdEnv) { [int]$errorThresholdEnv } else { $defaultErrorThreshold }
81+
82+
$lookbackHours = if ($lookbackEnv) { [int]$lookbackEnv } else { $defaultLookbackHours }
83+
$evaluationWindowHours = if ($evaluationEnv) { [int]$evaluationEnv } else { $defaultEvaluationWindowHours }
84+
85+
$lookbackStartTime = (Get-Date).AddHours(-$lookbackHours)
86+
$evaluationStartTime = (Get-Date).AddHours(-$evaluationWindowHours)
87+
88+
$allErrors = Get-WinEvent -FilterHashtable @{ LogName='System'; Level=2; StartTime=$lookbackStartTime } -ErrorAction SilentlyContinue
89+
90+
function Test-KeywordMatch {
91+
param ($event, $keywords)
92+
$eventData = $event.Properties -join " " + " " + $event.Message
93+
foreach ($keyword in $keywords) { if ($eventData -match "(?i)\b$($keyword)\b") { return $true } }
94+
return $false
95+
}
96+
97+
$filteredErrors = $allErrors | Where-Object {
98+
$eventIdMatches = $ignoredEventIds -contains $_.Id.ToString()
99+
$keywordMatches = Test-KeywordMatch $_ $ignoredKeywords
100+
-not ($eventIdMatches -or $keywordMatches)
101+
}
102+
103+
if ($debug -eq "true") {
104+
Write-Output "DEBUG MODE ENABLED"
105+
Write-Output "Ignored Event IDs: $ignoredEventIds"
106+
Write-Output "Ignored Keywords: $ignoredKeywords"
107+
Write-Output "INFO Threshold: $infoThreshold"
108+
Write-Output "WARN Threshold: $warnThreshold"
109+
Write-Output "ERROR Threshold: $errorThreshold"
110+
Write-Output "Lookback Hours: $lookbackHours"
111+
Write-Output "Evaluation Window Hours: $evaluationWindowHours"
77112
}
78113

79114
if ($debug -eq "true") {
@@ -82,75 +117,49 @@ if ($debug -eq "true") {
82117
Write-Output "DEBUG: Filtered Keywords: $ignoredKeywords"
83118

84119
if ($eventsWithIdFilter.Count -gt 0) {
85-
Write-Output "Filtered Events by Event ID in the last 48 hours:"
86-
$eventsWithIdFilter | ForEach-Object {
87-
Write-Output "TimeCreated: $($_.TimeCreated)"
88-
Write-Output "Event ID: $($_.Id)"
89-
Write-Output "Message: $($_.Message)"
90-
Write-Output "----------------------------------------"
91-
}
92-
} else {
93-
Write-Output "No events found matching the specified Event IDs in the last 48 hours."
94-
}
120+
Write-Output "Filtered Events by Event ID in the last $lookbackHours hours:"
121+
$eventsWithIdFilter | ForEach-Object { Write-Output "TimeCreated: $($_.TimeCreated)"; Write-Output "Event ID: $($_.Id)"; Write-Output "Message: $($_.Message)"; Write-Output "----------------------------------------" }
122+
} else { Write-Output "No events found matching the specified Event IDs in the last $lookbackHours hours." }
95123

96124
if ($eventsWithKeywordFilter.Count -gt 0) {
97-
Write-Output "Filtered Events by Keyword in the last 48 hours:"
98-
$eventsWithKeywordFilter | ForEach-Object {
99-
Write-Output "TimeCreated: $($_.TimeCreated)"
100-
Write-Output "Event ID: $($_.Id)"
101-
Write-Output "Message: $($_.Message)"
102-
Write-Output "----------------------------------------"
103-
}
104-
} else {
105-
Write-Output "No events found matching the specified Keywords in the last 48 hours."
106-
}
125+
Write-Output "Filtered Events by Keyword in the last $lookbackHours hours:"
126+
$eventsWithKeywordFilter | ForEach-Object { Write-Output "TimeCreated: $($_.TimeCreated)"; Write-Output "Event ID: $($_.Id)"; Write-Output "Message: $($_.Message)"; Write-Output "----------------------------------------" }
127+
} else { Write-Output "No events found matching the specified Keywords in the last $lookbackHours hours." }
107128
}
108129

109-
$remainingErrors48h = $allErrors48h | Where-Object {
110-
$eventIdMatches = $ignoredEventIds -contains $_.Id.ToString()
111-
$eventData = $_.Properties -join " "
112-
$eventData += " " + $_.Message
113-
$keywordMatches = $false
114-
$ignoredKeywords | ForEach-Object {
115-
$keyword = $_.Trim()
116-
if ($eventData -match "(?i)\b$($keyword)\b") {
117-
$keywordMatches = $true
118-
}
119-
}
120-
if ($eventIdMatches -or $keywordMatches) {
121-
$false
122-
} else {
123-
$true
124-
}
125-
}
130+
$errorsInEvaluationWindow = $filteredErrors | Where-Object { $_.TimeCreated -gt $evaluationStartTime }
131+
$count = $errorsInEvaluationWindow.Count
126132

127-
if ($remainingErrors48h.Count -gt 0) {
128-
Write-Output "Remaining Error Events in the last 48 hours (after filtering out ignored Event IDs and Keywords):"
129-
$remainingErrors48h | ForEach-Object {
133+
if ($count -ge $errorThreshold) {
134+
Write-Output "CRITICAL: $count error events in last $evaluationWindowHours hours (threshold: $errorThreshold)."
135+
$errorsInEvaluationWindow | ForEach-Object {
130136
Write-Output "TimeCreated: $($_.TimeCreated)"
131137
Write-Output "Event ID: $($_.Id)"
132138
Write-Output "Message: $($_.Message)"
133139
Write-Output "----------------------------------------"
134140
}
141+
exit $errorExitCode
135142
}
136-
137-
$errors12h = $remainingErrors48h | Where-Object { $_.TimeCreated -gt $start12h }
138-
139-
if ($errors12h.Count -ge 4) {
140-
Write-Output "Error: 4 or more error events found in the last 12 hours."
141-
Write-Output "Error Events in the last 12 hours (excluding ignored event IDs and keywords):"
142-
$errors12h | ForEach-Object {
143+
elseif ($count -ge $warnThreshold) {
144+
Write-Output "WARNING: $count error events in last $evaluationWindowHours hours (threshold: $warnThreshold)."
145+
$errorsInEvaluationWindow | ForEach-Object {
143146
Write-Output "TimeCreated: $($_.TimeCreated)"
144147
Write-Output "Event ID: $($_.Id)"
145148
Write-Output "Message: $($_.Message)"
146149
Write-Output "----------------------------------------"
147150
}
148-
exit 1
149-
} else {
150-
if ($errors12h.Count -eq 0) {
151-
Write-Output "OK: No error events found in the last 12 hours."
152-
} else {
153-
Write-Output "OK: Less than 4 error events found in the last 12 hours."
154-
}
155-
exit 0
151+
exit $warnExitCode
156152
}
153+
else {
154+
if ($count -eq 0) { Write-Output "INFO: No error events in last $evaluationWindowHours hours." }
155+
else {
156+
Write-Output "INFO: $count error event(s) in last $evaluationWindowHours hours (below warning threshold: $warnThreshold)."
157+
$errorsInEvaluationWindow | ForEach-Object {
158+
Write-Output "TimeCreated: $($_.TimeCreated)"
159+
Write-Output "Event ID: $($_.Id)"
160+
Write-Output "Message: $($_.Message)"
161+
Write-Output "----------------------------------------"
162+
}
163+
}
164+
exit $infoExitCode
165+
}

0 commit comments

Comments
 (0)