mirror of
https://github.com/Icinga/icinga-powershell-framework.git
synced 2026-02-03 04:09:29 -05:00
Adds feature to check Eventlog for problem and acknowleding events
This commit is contained in:
parent
15b464f78c
commit
307a57a5bf
4 changed files with 135 additions and 44 deletions
|
|
@ -15,10 +15,12 @@ Released closed milestones can be found on [GitHub](https://github.com/Icinga/ic
|
||||||
|
|
||||||
* [#729](https://github.com/Icinga/icinga-powershell-framework/issues/729) Fixes `Update-Icinga` to print an error in case a component is not installed, instead of silently continue
|
* [#729](https://github.com/Icinga/icinga-powershell-framework/issues/729) Fixes `Update-Icinga` to print an error in case a component is not installed, instead of silently continue
|
||||||
* [#734](https://github.com/Icinga/icinga-powershell-framework/issues/734) Fixes a scenario on which a JEA service could become orphaned while manually stopping the Icinga for Windows service, without gracefully shutting down JEA
|
* [#734](https://github.com/Icinga/icinga-powershell-framework/issues/734) Fixes a scenario on which a JEA service could become orphaned while manually stopping the Icinga for Windows service, without gracefully shutting down JEA
|
||||||
|
* [#735](https://github.com/Icinga/icinga-powershell-framework/pull/735) Fixes an issue with filter for EventLog events, which did not properly handle multiple event id includes, causing empty results
|
||||||
|
|
||||||
### Enhancements
|
### Enhancements
|
||||||
|
|
||||||
* [#732](https://github.com/Icinga/icinga-powershell-framework/pull/732) Adds support for TLS 1.3 and improves startup response
|
* [#732](https://github.com/Icinga/icinga-powershell-framework/pull/732) Adds support for TLS 1.3 and improves startup response
|
||||||
|
* [#735](https://github.com/Icinga/icinga-powershell-framework/pull/735) Adds support to provide occuring problem event id's for the Eventlog and corresponding acknowledgement id's, providing an indicator if certain issues are resolved or still present
|
||||||
|
|
||||||
## 1.12.3 (2024-04-24)
|
## 1.12.3 (2024-04-24)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -37,6 +37,7 @@
|
||||||
[hashtable]$Configuration = @{
|
[hashtable]$Configuration = @{
|
||||||
PluginArgumentConflict = 'Your plugin argument configuration is causing a conflict. Mostly this error is caused by mismatching configurations by enabling multiple switch arguments which are resulting in a conflicting configuration for the plugin.';
|
PluginArgumentConflict = 'Your plugin argument configuration is causing a conflict. Mostly this error is caused by mismatching configurations by enabling multiple switch arguments which are resulting in a conflicting configuration for the plugin.';
|
||||||
PluginArgumentMissing = 'Your plugin argument configuration is missing mandatory arguments. This error is caused when mandatory or required arguments are missing from a plugin call and the operation is unable to process without them.';
|
PluginArgumentMissing = 'Your plugin argument configuration is missing mandatory arguments. This error is caused when mandatory or required arguments are missing from a plugin call and the operation is unable to process without them.';
|
||||||
|
PluginArgumentAsymmetry = 'Your plugin argument configuration is causing an asymmetry. This error is caused by an uneven amount of arguments in your plugin call. Please ensure that your plugin call is properly configured and all arguments are set correctly.';
|
||||||
PluginNotInstalled = 'The plugin assigned to this service check seems not to be installed on this machine. Please review your service check configuration for spelling errors and check if the plugin is installed and executable on this machine by PowerShell. You can ensure modules are available by manually importing them by their name with the following commands: Import-Module -Name "module name" -Force; Import-Module -Name "module name" -Global -Force;';
|
PluginNotInstalled = 'The plugin assigned to this service check seems not to be installed on this machine. Please review your service check configuration for spelling errors and check if the plugin is installed and executable on this machine by PowerShell. You can ensure modules are available by manually importing them by their name with the following commands: Import-Module -Name "module name" -Force; Import-Module -Name "module name" -Global -Force;';
|
||||||
PluginNotAssigned = 'Your check for this service could not be processed because it seems like no valid Cmdlet was assigned to the check command. Please review your check command to ensure that a valid Cmdlet is assigned and executed by a PowerShell call.';
|
PluginNotAssigned = 'Your check for this service could not be processed because it seems like no valid Cmdlet was assigned to the check command. Please review your check command to ensure that a valid Cmdlet is assigned and executed by a PowerShell call.';
|
||||||
EventLogNotInstalled = 'Your Icinga PowerShell Framework has been executed by an unprivileged user before it was properly installed. The Windows EventLog application could not be registered because the current user has insufficient permissions. Please log into the machine and run "Use-Icinga" once from an administrative shell to complete the setup process. Once done this error should vanish.';
|
EventLogNotInstalled = 'Your Icinga PowerShell Framework has been executed by an unprivileged user before it was properly installed. The Windows EventLog application could not be registered because the current user has insufficient permissions. Please log into the machine and run "Use-Icinga" once from an administrative shell to complete the setup process. Once done this error should vanish.';
|
||||||
|
|
|
||||||
|
|
@ -12,6 +12,7 @@ function Get-IcingaProviderDataValuesEventlog()
|
||||||
|
|
||||||
$EventLogData.Metrics | Add-Member -MemberType NoteProperty -Name 'List' -Value $FilterObject.EventLog.Query.List;
|
$EventLogData.Metrics | Add-Member -MemberType NoteProperty -Name 'List' -Value $FilterObject.EventLog.Query.List;
|
||||||
$EventLogData.Metrics | Add-Member -MemberType NoteProperty -Name 'Events' -Value $FilterObject.EventLog.Query.Events;
|
$EventLogData.Metrics | Add-Member -MemberType NoteProperty -Name 'Events' -Value $FilterObject.EventLog.Query.Events;
|
||||||
|
$EventLogData.Metrics | Add-Member -MemberType NoteProperty -Name 'Problems' -Value $FilterObject.EventLog.Query.Problems;
|
||||||
$EventLogData.Metrics | Add-Member -MemberType NoteProperty -Name 'HasEvents' -Value $FilterObject.EventLog.Query.HasEvents;
|
$EventLogData.Metrics | Add-Member -MemberType NoteProperty -Name 'HasEvents' -Value $FilterObject.EventLog.Query.HasEvents;
|
||||||
|
|
||||||
$FilterObject = $null;
|
$FilterObject = $null;
|
||||||
|
|
|
||||||
|
|
@ -6,25 +6,32 @@
|
||||||
function New-IcingaProviderFilterDataEventlog()
|
function New-IcingaProviderFilterDataEventlog()
|
||||||
{
|
{
|
||||||
param(
|
param(
|
||||||
[string]$LogName = '',
|
[string]$LogName = '',
|
||||||
[array]$IncludeEventId = @(),
|
[array]$IncludeEventId = @(),
|
||||||
[array]$ExcludeEventId = @(),
|
[array]$ExcludeEventId = @(),
|
||||||
[array]$IncludeUsername = @(),
|
[array]$IncludeUsername = @(),
|
||||||
[array]$ExcludeUsername = @(),
|
[array]$ExcludeUsername = @(),
|
||||||
[array]$IncludeEntryType = @(),
|
[array]$IncludeEntryType = @(),
|
||||||
[array]$ExcludeEntryType = @(),
|
[array]$ExcludeEntryType = @(),
|
||||||
[array]$IncludeMessage = @(),
|
[array]$IncludeMessage = @(),
|
||||||
[array]$ExcludeMessage = @(),
|
[array]$ExcludeMessage = @(),
|
||||||
[array]$IncludeSource = @(),
|
[array]$IncludeSource = @(),
|
||||||
[array]$ExcludeSource = @(),
|
[array]$ExcludeSource = @(),
|
||||||
[string]$EventsAfter = $null,
|
[array]$ProblemId = @(),
|
||||||
[string]$EventsBefore = $null,
|
[array]$AcknowledgeId = @(),
|
||||||
[int]$MaxEntries = 40000,
|
[string]$EventsAfter = $null,
|
||||||
[switch]$DisableTimeCache = $FALSE
|
[string]$EventsBefore = $null,
|
||||||
|
[int]$MaxEntries = 40000,
|
||||||
|
[switch]$DisableTimeCache = $FALSE
|
||||||
);
|
);
|
||||||
|
|
||||||
|
if ($ProblemId.Count -ne $AcknowledgeId.Count) {
|
||||||
|
Exit-IcingaThrowException -ExceptionType 'Input' -ExceptionThrown $IcingaExceptions.Configuration.PluginArgumentAsymmetry -ExceptionList $IcingaPluginExceptions -CustomMessage ([string]::Format('ProblemId count: {0}, AcknowledgeId count: {1}', $ProblemId.Count, $AcknowledgeId.Count)) -Force;
|
||||||
|
}
|
||||||
|
|
||||||
[string]$EventLogFilter = '';
|
[string]$EventLogFilter = '';
|
||||||
$EventIdFilter = New-Object -TypeName 'System.Text.StringBuilder';
|
$EventIdFilter = New-Object -TypeName 'System.Text.StringBuilder';
|
||||||
|
$EventIdInternalFilter = New-Object -TypeName 'System.Text.StringBuilder';
|
||||||
$EntryTypeFilter = New-Object -TypeName 'System.Text.StringBuilder';
|
$EntryTypeFilter = New-Object -TypeName 'System.Text.StringBuilder';
|
||||||
$SourceFilter = New-Object -TypeName 'System.Text.StringBuilder';
|
$SourceFilter = New-Object -TypeName 'System.Text.StringBuilder';
|
||||||
$UserFilter = New-Object -TypeName 'System.Text.StringBuilder';
|
$UserFilter = New-Object -TypeName 'System.Text.StringBuilder';
|
||||||
|
|
@ -33,7 +40,31 @@ function New-IcingaProviderFilterDataEventlog()
|
||||||
$EventBeforeFilter = $null;
|
$EventBeforeFilter = $null;
|
||||||
$EventsAfter = (Convert-IcingaPluginThresholds -Threshold $EventsAfter).Value;
|
$EventsAfter = (Convert-IcingaPluginThresholds -Threshold $EventsAfter).Value;
|
||||||
$EventsBefore = (Convert-IcingaPluginThresholds -Threshold $EventsBefore).Value;
|
$EventsBefore = (Convert-IcingaPluginThresholds -Threshold $EventsBefore).Value;
|
||||||
[string]$CheckHash = (Get-StringSha1 ($LogName + $IncludeEventId + $ExcludeEventId + $IncludeUsername + $ExcludeUsername + $IncludeEntryType + $ExcludeEntryType + $IncludeMessage + $ExcludeMessage)) + '.lastcheck';
|
[string]$CheckHash = (Get-StringSha1 ($LogName + $IncludeEventId + $ExcludeEventId + $IncludeUsername + $ExcludeUsername + $IncludeEntryType + $ExcludeEntryType + $IncludeMessage + $ExcludeMessage + $ProblemId + $AcknowledgeId)) + '.lastcheck';
|
||||||
|
[hashtable]$ProblemList = @{ };
|
||||||
|
[hashtable]$ResolveList = @{ };
|
||||||
|
[int]$IndexOfEntries = 0;
|
||||||
|
|
||||||
|
foreach ($entry in $ProblemId) {
|
||||||
|
Add-IcingaHashtableItem -Hashtable $ProblemList -Key ([string]$entry) -Value @{
|
||||||
|
'NewestEntry' = '';
|
||||||
|
'Message' = '';
|
||||||
|
'Count' = 0;
|
||||||
|
'ResolvedId' = $AcknowledgeId[$IndexOfEntries];
|
||||||
|
'IsProblem' = $TRUE;
|
||||||
|
} | Out-Null;
|
||||||
|
}
|
||||||
|
|
||||||
|
# Reset the Id's
|
||||||
|
[int]$IndexOfEntries = 0;
|
||||||
|
|
||||||
|
foreach ($entry in $AcknowledgeId) {
|
||||||
|
Add-IcingaHashtableItem -Hashtable $ResolveList -Key ([string]$entry) -Value @{
|
||||||
|
'NewestEntry' = '';
|
||||||
|
'Count' = 0;
|
||||||
|
'ProblemId' = $ProblemId[$IndexOfEntries];
|
||||||
|
} | Out-Null;
|
||||||
|
}
|
||||||
|
|
||||||
if ([string]::IsNullOrEmpty($EventsAfter) -and $DisableTimeCache -eq $FALSE) {
|
if ([string]::IsNullOrEmpty($EventsAfter) -and $DisableTimeCache -eq $FALSE) {
|
||||||
$time = Get-IcingaCacheData -Space 'provider' -CacheStore 'eventlog' -KeyName $CheckHash;
|
$time = Get-IcingaCacheData -Space 'provider' -CacheStore 'eventlog' -KeyName $CheckHash;
|
||||||
|
|
@ -67,28 +98,42 @@ function New-IcingaProviderFilterDataEventlog()
|
||||||
[string]$EventBeforeFilter = ([datetime]::FromFileTime(((Get-Date).ToFileTime()))).ToString("yyyy-MM-dd HH:mm:ss");
|
[string]$EventBeforeFilter = ([datetime]::FromFileTime(((Get-Date).ToFileTime()))).ToString("yyyy-MM-dd HH:mm:ss");
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach ($entry in $IncludeEventId) {
|
# The filter string can be used to query Event Log entries based on the specified Event IDs, to filter correctly
|
||||||
if ($EventIdFilter.Length -ne 0) {
|
# between included and excluded Event IDs to ensure that includes are separated with OR while excludes
|
||||||
$EventIdFilter.Append(
|
# are added with AND to ensure that the filter string is correctly constructed.
|
||||||
([string]::Format(' and EventID={0}', $entry))
|
if ($IncludeEventId.Count -ne 0 -Or $ExcludeEventId.Count -ne 0) {
|
||||||
) | Out-Null;
|
$EventIdInternalFilter.Append('(') | Out-Null;
|
||||||
} else {
|
|
||||||
$EventIdFilter.Append(
|
|
||||||
([string]::Format('EventID={0}', $entry))
|
|
||||||
) | Out-Null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach ($entry in $ExcludeEventId) {
|
foreach ($entry in $IncludeEventId) {
|
||||||
if ($EventIdFilter.Length -ne 0) {
|
if ($EventIdFilter.Length -ne 0) {
|
||||||
$EventIdFilter.Append(
|
$EventIdFilter.Append(
|
||||||
([string]::Format(' and EventID!={0}', $entry))
|
([string]::Format(' or EventID={0}', $entry))
|
||||||
) | Out-Null;
|
) | Out-Null;
|
||||||
} else {
|
} else {
|
||||||
$EventIdFilter.Append(
|
$EventIdFilter.Append(
|
||||||
([string]::Format('EventID!={0}', $entry))
|
([string]::Format('( EventID={0}', $entry))
|
||||||
) | Out-Null;
|
) | Out-Null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ($EventIdFilter.Length -ne 0) {
|
||||||
|
$EventIdFilter.Append(' )');
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach ($entry in $ExcludeEventId) {
|
||||||
|
if ($EventIdFilter.Length -ne 0) {
|
||||||
|
$EventIdFilter.Append(
|
||||||
|
([string]::Format(' and EventID!={0}', $entry))
|
||||||
|
) | Out-Null;
|
||||||
|
} else {
|
||||||
|
$EventIdFilter.Append(
|
||||||
|
([string]::Format('EventID!={0}', $entry))
|
||||||
|
) | Out-Null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$EventIdInternalFilter.Append($EventIdFilter.ToString()) | Out-Null;
|
||||||
|
$EventIdInternalFilter.Append(')') | Out-Null;
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach ($entry in $IncludeEntryType) {
|
foreach ($entry in $IncludeEntryType) {
|
||||||
|
|
@ -175,7 +220,7 @@ function New-IcingaProviderFilterDataEventlog()
|
||||||
([string]::Format(' and TimeCreated[@SystemTime<="{0}"]', (Get-Date $EventBeforeFilter).ToUniversalTime().ToString("yyyy-MM-dd'T'HH:mm:ssZ")))
|
([string]::Format(' and TimeCreated[@SystemTime<="{0}"]', (Get-Date $EventBeforeFilter).ToUniversalTime().ToString("yyyy-MM-dd'T'HH:mm:ssZ")))
|
||||||
) | Out-Null;
|
) | Out-Null;
|
||||||
|
|
||||||
[string]$EventLogFilter = Add-IcingaProviderEventlogFilterData -EventFilter $EventLogFilter -StringBuilderObject $EventIdFilter;
|
[string]$EventLogFilter = Add-IcingaProviderEventlogFilterData -EventFilter $EventLogFilter -StringBuilderObject $EventIdInternalFilter;
|
||||||
[string]$EventLogFilter = Add-IcingaProviderEventlogFilterData -EventFilter $EventLogFilter -StringBuilderObject $EntryTypeFilter;
|
[string]$EventLogFilter = Add-IcingaProviderEventlogFilterData -EventFilter $EventLogFilter -StringBuilderObject $EntryTypeFilter;
|
||||||
[string]$EventLogFilter = Add-IcingaProviderEventlogFilterData -EventFilter $EventLogFilter -StringBuilderObject $SourceFilter;
|
[string]$EventLogFilter = Add-IcingaProviderEventlogFilterData -EventFilter $EventLogFilter -StringBuilderObject $SourceFilter;
|
||||||
[string]$EventLogFilter = Add-IcingaProviderEventlogFilterData -EventFilter $EventLogFilter -StringBuilderObject $UserFilter;
|
[string]$EventLogFilter = Add-IcingaProviderEventlogFilterData -EventFilter $EventLogFilter -StringBuilderObject $UserFilter;
|
||||||
|
|
@ -198,6 +243,7 @@ function New-IcingaProviderFilterDataEventlog()
|
||||||
$EventLogQueryData = New-Object PSCustomObject;
|
$EventLogQueryData = New-Object PSCustomObject;
|
||||||
$EventLogQueryData | Add-Member -MemberType NoteProperty -Name 'List' -Value (New-Object PSCustomObject);
|
$EventLogQueryData | Add-Member -MemberType NoteProperty -Name 'List' -Value (New-Object PSCustomObject);
|
||||||
$EventLogQueryData | Add-Member -MemberType NoteProperty -Name 'Events' -Value (New-Object PSCustomObject);
|
$EventLogQueryData | Add-Member -MemberType NoteProperty -Name 'Events' -Value (New-Object PSCustomObject);
|
||||||
|
$EventLogQueryData | Add-Member -MemberType NoteProperty -Name 'Problems' -Value (New-Object PSCustomObject);
|
||||||
$EventLogQueryData | Add-Member -MemberType NoteProperty -Name 'HasEvents' -Value $FALSE;
|
$EventLogQueryData | Add-Member -MemberType NoteProperty -Name 'HasEvents' -Value $FALSE;
|
||||||
|
|
||||||
foreach ($event in $EventLogEntries) {
|
foreach ($event in $EventLogEntries) {
|
||||||
|
|
@ -206,6 +252,19 @@ function New-IcingaProviderFilterDataEventlog()
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ($ProblemList.ContainsKey([string]$event.Id)) {
|
||||||
|
if ([string]::IsNullOrEmpty($ProblemList[([string]$event.Id)].NewestEntry)) {
|
||||||
|
$ProblemList[([string]$event.Id)].NewestEntry = ([string]($event.TimeCreated));
|
||||||
|
$ProblemList[([string]$event.Id)].Message = [string]($event.Message);
|
||||||
|
}
|
||||||
|
$ProblemList[([string]$event.Id)].Count += 1;
|
||||||
|
}
|
||||||
|
if ($ResolveList.ContainsKey([string]$event.Id)) {
|
||||||
|
if ([string]::IsNullOrEmpty($ResolveList[([string]$event.Id)].NewestEntry)) {
|
||||||
|
$ResolveList[([string]$event.Id)].NewestEntry = ([string]($event.TimeCreated));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
$EventLogQueryData.HasEvents = $TRUE;
|
$EventLogQueryData.HasEvents = $TRUE;
|
||||||
|
|
||||||
[string]$EventIdentifier = [string]::Format('{0}-{1}',
|
[string]$EventIdentifier = [string]::Format('{0}-{1}',
|
||||||
|
|
@ -242,17 +301,45 @@ function New-IcingaProviderFilterDataEventlog()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ($ProblemId.Count -ne 0) {
|
||||||
|
foreach ($problem in $ProblemList.Keys) {
|
||||||
|
[string]$ressolvedId = $ProblemList[$problem].ResolvedId;
|
||||||
|
$LastProblem = $null;
|
||||||
|
$LastResolved = $null;
|
||||||
|
|
||||||
|
if ([string]::IsNullOrEmpty($ProblemList[$problem].NewestEntry) -eq $FALSE) {
|
||||||
|
$LastProblem = [DateTime]$ProblemList[$problem].NewestEntry;
|
||||||
|
}
|
||||||
|
if ([string]::IsNullOrEmpty($ResolveList[$ressolvedId].NewestEntry) -eq $FALSE) {
|
||||||
|
$LastResolved = [DateTime]$ResolveList[$ressolvedId].NewestEntry;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($ResolveList.ContainsKey($ressolvedId)) {
|
||||||
|
if ($null -ne $LastProblem -And $null -ne $LastResolved -And $LastProblem -le $LastResolved) {
|
||||||
|
$ProblemList[$problem].$IsProblem = $FALSE;
|
||||||
|
} else {
|
||||||
|
$EventLogQueryData.Problems | Add-Member -MemberType NoteProperty -Name $problem -Value (New-Object PSCustomObject);
|
||||||
|
$EventLogQueryData.Problems.$problem | Add-Member -MemberType NoteProperty -Name 'EventId' -Value $problem;
|
||||||
|
$EventLogQueryData.Problems.$problem | Add-Member -MemberType NoteProperty -Name 'Count' -Value $ProblemList[$problem].Count;
|
||||||
|
$EventLogQueryData.Problems.$problem | Add-Member -MemberType NoteProperty -Name 'Message' -Value $ProblemList[$problem].Message;
|
||||||
|
$EventLogQueryData.Problems.$problem | Add-Member -MemberType NoteProperty -Name 'NewestEntry' -Value $ProblemList[$problem].NewestEntry;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if ($null -ne $EventLogEntries) {
|
if ($null -ne $EventLogEntries) {
|
||||||
$EventLogEntries.Dispose();
|
$EventLogEntries.Dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
$EventLogEntries = $null;
|
$EventLogEntries = $null;
|
||||||
$EventLogFilter = $null;
|
$EventLogFilter = $null;
|
||||||
$EventIdFilter = $null;
|
$EventIdFilter = $null;
|
||||||
$EntryTypeFilter = $null;
|
$EventIdInternalFilter = $null;
|
||||||
$SourceFilter = $null;
|
$EntryTypeFilter = $null;
|
||||||
$UserFilter = $null;
|
$SourceFilter = $null;
|
||||||
$TimeFilter = $null;
|
$UserFilter = $null;
|
||||||
|
$TimeFilter = $null;
|
||||||
|
|
||||||
return $EventLogQueryData;
|
return $EventLogQueryData;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue