function Start-IcingaServiceCheckDaemon() { $ScriptBlock = { param($IcingaDaemonData); Use-Icinga -LibOnly -Daemon; $IcingaDaemonData.BackgroundDaemon.Add('ServiceCheckScheduler', [hashtable]::Synchronized(@{})); $IcingaDaemonData.IcingaThreadPool.Add('ServiceCheckPool', (New-IcingaThreadPool -MaxInstances (Get-IcingaConfigTreeCount -Path 'BackgroundDaemon.RegisteredServices'))); while ($TRUE) { $RegisteredServices = Get-IcingaRegisteredServiceChecks; foreach ($service in $RegisteredServices.Keys) { [string]$ThreadName = [string]::Format('Icinga_Background_Service_Check_{0}', $service); if ((Test-IcingaThread $ThreadName)) { continue; } Start-IcingaServiceCheckTask -CheckId $service -CheckCommand $RegisteredServices[$service].CheckCommand -Arguments $RegisteredServices[$service].Arguments -Interval $RegisteredServices[$service].Interval -TimeIndexes $RegisteredServices[$service].TimeIndexes; } Start-Sleep -Seconds 1; } }; New-IcingaThreadInstance -Name "Icinga_PowerShell_ServiceCheck_Scheduler" -ThreadPool $IcingaDaemonData.IcingaThreadPool.BackgroundPool -ScriptBlock $ScriptBlock -Arguments @( $global:IcingaDaemonData ) -Start; } function Start-IcingaServiceCheckTask() { param( $CheckId, $CheckCommand, $Arguments, $Interval, $TimeIndexes ); [string]$ThreadName = [string]::Format('Icinga_Background_Service_Check_{0}', $CheckId); $ScriptBlock = { param($IcingaDaemonData, $CheckCommand, $Arguments, $Interval, $TimeIndexes, $CheckId); Use-Icinga -LibOnly -Daemon; $PassedTime = 0; $SortedResult = $null; $OldData = @{}; $PerfCache = @{}; if (-Not ($IcingaDaemonData.BackgroundDaemon.ServiceCheckScheduler.ContainsKey($CheckCommand))) { $IcingaDaemonData.BackgroundDaemon.ServiceCheckScheduler.Add($CheckCommand, [hashtable]::Synchronized(@{})); $IcingaDaemonData.BackgroundDaemon.ServiceCheckScheduler[$CheckCommand].Add('results', [hashtable]::Synchronized(@{})); $IcingaDaemonData.BackgroundDaemon.ServiceCheckScheduler[$CheckCommand].Add('average', [hashtable]::Synchronized(@{})); } $LoadedCacheData = Get-IcingaCacheData -Space 'sc_daemon' -CacheStore 'checkresult_store' -KeyName $CheckCommand; if ($null -ne $LoadedCacheData) { foreach ($entry in $LoadedCacheData.PSObject.Properties) { $IcingaDaemonData.BackgroundDaemon.ServiceCheckScheduler[$CheckCommand]['results'].Add( $entry.name, [hashtable]::Synchronized(@{}) ); foreach ($item in $entry.Value.PSObject.Properties) { $IcingaDaemonData.BackgroundDaemon.ServiceCheckScheduler[$CheckCommand]['results'][$entry.name].Add( $item.Name, $item.Value ); } } } while ($TRUE) { if ($PassedTime -ge $Interval) { try { & $CheckCommand @Arguments | Out-Null; $UnixTime = Get-IcingaUnixTime; foreach ($result in $IcingaDaemonData.BackgroundDaemon.ServiceCheckScheduler[$CheckCommand]['results'].Keys) { $SortedResult = $IcingaDaemonData.BackgroundDaemon.ServiceCheckScheduler[$CheckCommand]['results'][$result].GetEnumerator() | Sort-Object name -Descending; Add-IcingaHashtableItem -Hashtable $OldData -Key $result -Value @{}; Add-IcingaHashtableItem -Hashtable $PerfCache -Key ([string]$result) -Value @{}; foreach ($index in $TimeIndexes) { $ObjectCount = 0; $ObjectValue = 0; $TimeInSeconds = $index * 60; foreach ($timeEntry in $SortedResult) { if (($UnixTime - $TimeInSeconds) -le [int]$timeEntry.Key) { $ObjectCount += 1; $ObjectValue += $timeEntry.Value; Remove-IcingaHashtableItem -Hashtable $OldData[$result] -Key $timeEntry; Add-IcingaHashtableItem -Hashtable $PerfCache[$result] -Key ([string]$timeEntry.Key) -Value ([string]$timeEntry.Value); } else { Add-IcingaHashtableItem -Hashtable $OldData[$result] -Key $timeEntry -Value $null; } } $AvarageValue = ($ObjectValue / $ObjectCount); $MetricName = [string]::Format('{0}_{1}', $result, $index); Add-IcingaHashtableItem ` -Hashtable $IcingaDaemonData.BackgroundDaemon.ServiceCheckScheduler[$CheckCommand]['average'] ` -Key (Format-IcingaPerfDataLabel $MetricName) -Value $AvarageValue -Override; } } # Flush data we no longer require in our cache to free memory foreach ($entry in $OldData.Keys) { foreach ($key in $OldData[$entry].Keys) { Remove-IcingaHashtableItem -Hashtable $IcingaDaemonData.BackgroundDaemon.ServiceCheckScheduler[$CheckCommand]['results'][$entry] -Key $key.Name } } Set-IcingaCacheData -Space 'sc_daemon' -CacheStore 'checkresult' -KeyName $CheckCommand -Value $IcingaDaemonData.BackgroundDaemon.ServiceCheckScheduler[$CheckCommand]['average']; # Write collected metrics to disk in case we reload the daemon. We will load them back into the module after reload then Set-IcingaCacheData -Space 'sc_daemon' -CacheStore 'checkresult_store' -KeyName $CheckCommand -Value $PerfCache; } catch { # Todo: Add error reporting / handling } $PassedTime = 0; $SortedResult = $null; $OldData = @{}; $PerfCache = @{}; } $PassedTime += 1; Start-Sleep -Seconds 1; } }; New-IcingaThreadInstance -Name $ThreadName -ThreadPool $IcingaDaemonData.IcingaThreadPool.ServiceCheckPool -ScriptBlock $ScriptBlock -Arguments @( $global:IcingaDaemonData, $CheckCommand, $Arguments, $Interval, $TimeIndexes, $CheckId ) -Start; }