lib/daemons/ServiceCheckDaemon/Add-IcingaServiceCheckTask.psm1
function Add-IcingaServiceCheckTask() { param ( $IcingaDaemonData, $CheckCommand, $Arguments, $Interval, $TimeIndexes, $CheckId ); Use-Icinga -LibOnly -Daemon; $PassedTime = 0; $SortedResult = $null; $PerfCache = @{ }; $AverageCalc = @{ }; [int]$MaxTime = 0; # Initialise some global variables we use to actually store check result data from # plugins properly. This is doable from each thread instance as this part isn't # shared between daemons New-IcingaCheckSchedulerEnvironment; foreach ($index in $TimeIndexes) { # Only allow numeric index values if ((Test-Numeric $index) -eq $FALSE) { continue; } if ($AverageCalc.ContainsKey([string]$index) -eq $FALSE) { $AverageCalc.Add( [string]$index, @{ 'Interval' = ([int]$index); 'Time' = ([int]$index * 60); 'Sum' = 0; 'Count' = 0; } ); } if ($MaxTime -le [int]$index) { $MaxTime = [int]$index; } } [int]$MaxTimeInSeconds = $MaxTime * 60; if (-Not ($global:Icinga.CheckData.ContainsKey($CheckCommand))) { $global:Icinga.CheckData.Add($CheckCommand, @{ }); $global:Icinga.CheckData[$CheckCommand].Add('results', @{ }); $global:Icinga.CheckData[$CheckCommand].Add('average', @{ }); } $LoadedCacheData = Get-IcingaCacheData -Space 'sc_daemon' -CacheStore 'checkresult_store' -KeyName $CheckCommand; if ($null -ne $LoadedCacheData) { foreach ($entry in $LoadedCacheData.PSObject.Properties) { $global:Icinga.CheckData[$CheckCommand]['results'].Add( $entry.name, @{ } ); foreach ($item in $entry.Value.PSObject.Properties) { $global:Icinga.CheckData[$CheckCommand]['results'][$entry.name].Add( $item.Name, $item.Value ); } } } while ($TRUE) { if ($PassedTime -ge $Interval) { try { & $CheckCommand @Arguments | Out-Null; } catch { # Just for debugging. Not required in production or usable at all $ErrMsg = $_.Exception.Message; Write-IcingaConsoleError $ErrMsg; } try { $UnixTime = Get-IcingaUnixTime; foreach ($result in $global:Icinga.CheckData[$CheckCommand]['results'].Keys) { [string]$HashIndex = $result; $SortedResult = $global:Icinga.CheckData[$CheckCommand]['results'][$HashIndex].GetEnumerator() | Sort-Object name -Descending; Add-IcingaHashtableItem -Hashtable $PerfCache -Key $HashIndex -Value @{ } | Out-Null; foreach ($timeEntry in $SortedResult) { if ((Test-Numeric $timeEntry.Value) -eq $FALSE) { continue; } foreach ($calc in $AverageCalc.Keys) { if (($UnixTime - $AverageCalc[$calc].Time) -le [int]$timeEntry.Key) { $AverageCalc[$calc].Sum += $timeEntry.Value; $AverageCalc[$calc].Count += 1; } } if (($UnixTime - $MaxTimeInSeconds) -le [int]$timeEntry.Key) { Add-IcingaHashtableItem -Hashtable $PerfCache[$HashIndex] -Key ([string]$timeEntry.Key) -Value ([string]$timeEntry.Value) | Out-Null; } } foreach ($calc in $AverageCalc.Keys) { if ($AverageCalc[$calc].Count -ne 0) { $AverageValue = ($AverageCalc[$calc].Sum / $AverageCalc[$calc].Count); [string]$MetricName = Format-IcingaPerfDataLabel ( [string]::Format('{0}_{1}', $HashIndex, $AverageCalc[$calc].Interval) ); Add-IcingaHashtableItem ` -Hashtable $global:Icinga.CheckData[$CheckCommand]['average'] ` -Key $MetricName -Value $AverageValue -Override | Out-Null; } $AverageCalc[$calc].Sum = 0; $AverageCalc[$calc].Count = 0; } } # Flush data we no longer require in our cache to free memory [array]$CheckStores = $global:Icinga.CheckData[$CheckCommand]['results'].Keys; foreach ($CheckStore in $CheckStores) { [string]$CheckKey = $CheckStore; [array]$CheckTimeStamps = $global:Icinga.CheckData[$CheckCommand]['results'][$CheckKey].Keys; foreach ($TimeSample in $CheckTimeStamps) { if (($UnixTime - $MaxTimeInSeconds) -gt [int]$TimeSample) { Remove-IcingaHashtableItem -Hashtable $global:Icinga.CheckData[$CheckCommand]['results'][$CheckKey] -Key ([string]$TimeSample); } } } Set-IcingaCacheData -Space 'sc_daemon' -CacheStore 'checkresult' -KeyName $CheckCommand -Value $global:Icinga.CheckData[$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 { # Just for debugging. Not required in production or usable at all $ErrMsg = $_.Exception.Message; Write-IcingaConsoleError 'Failed to handle check result processing: {0}' -Objects $ErrMsg; } # Cleanup the error stack and remove not required data $Error.Clear(); # Always ensure our check data is cleared regardless of possible # exceptions which might occur Get-IcingaCheckSchedulerPerfData | Out-Null; Get-IcingaCheckSchedulerPluginOutput | Out-Null; $PassedTime = 0; $SortedResult.Clear(); $PerfCache.Clear(); } $PassedTime += 1; Start-Sleep -Seconds 1; # Force PowerShell to call the garbage collector to free memory [System.GC]::Collect(); } } |