Reworks handling on how plugin thresholds are interpreted

This commit is contained in:
Lord Hepipud 2024-08-19 16:13:24 +02:00
parent 5bbba96215
commit 295fa00b12
16 changed files with 796 additions and 677 deletions

View file

@ -7,10 +7,14 @@ documentation before upgrading to a new release.
Released closed milestones can be found on [GitHub](https://github.com/Icinga/icinga-powershell-framework/milestones?state=closed).
## 1.13.0 (tbd)
## 1.13.0 Beta-1 (2024-08-30)
[Issues and PRs](https://github.com/Icinga/icinga-powershell-framework/milestone/32)
### Notes
This beta release has reworked the entire handling on how thresholds and the checker core operate. For that reason, the `Beta-1` release will **not** include the `Metrics over Time` feature. The goal of this beta is to get an idea if the threshold handling is working as expected and evaluate the performance gains for the new check handling. The `Metrics over Time` feature will be re-implemented with an entire new background task and configurations in `Beta-2`.
### Bugfixes
* [#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
@ -27,6 +31,7 @@ Released closed milestones can be found on [GitHub](https://github.com/Icinga/ic
* [#739](https://github.com/Icinga/icinga-powershell-framework/pull/739) Adds support to check the encoding of files to ensure we can properly load them and throw errors for unsupported encoding
* [#740](https://github.com/Icinga/icinga-powershell-framework/pull/740) Adds new command `Invoke-IcingaForWindowsRESTApi` for easier API communication
* [#742](https://github.com/Icinga/icinga-powershell-framework/pull/742) Adds support for the CPU provider to limit the CPU usage to 100% for each thread
* [#750](https://github.com/Icinga/icinga-powershell-framework/pull/750) Reworks the internal handling on how plugin thresholds are evaluated and the internal checker core, including on how performance metrics are generated
## 1.12.3 (2024-04-24)

View file

@ -10,15 +10,19 @@
Returns the last performance data output for executed plugins while the
Framework is running as daemon
.OUTPUTS
System.Object
System.String
.LINK
https://github.com/Icinga/icinga-powershell-framework
#>
function Get-IcingaCheckSchedulerPerfData()
{
$PerfData = $Global:Icinga.Private.Scheduler.PerformanceData;
[array]$Global:Icinga.Private.Scheduler.PerformanceData = @();
[string]$PerfData = $Global:Icinga.Private.Scheduler.PerformanceData;
[string]$Global:Icinga.Private.Scheduler.PerformanceData = '';
# Ensure we clear our PerfDataWriter cache and storage to have a clean base state for the next plugin execution
$Global:Icinga.Private.Scheduler.PerfDataWriter.Cache.Clear() | Out-Null;
$Global:Icinga.Private.Scheduler.PerfDataWriter.Storage.Clear() | Out-Null;
return $PerfData;
}

View file

@ -88,7 +88,7 @@ function Invoke-IcingaInternalServiceCall()
$IcingaCR = ($IcingaResult.$Command.checkresult.Replace("`r`n", "`n"));
if ($IcingaResult.$Command.perfdata.Count -ne 0) {
$IcingaCR = [string]::Format('{0}{1}| {2}', $IcingaCR, "`r`n", ([string]::Join(' ', $IcingaResult.$Command.perfdata)));
$IcingaCR = [string]::Format('{0}{1}| {2}', $IcingaCR, "`r`n", ([string]::Join('', $IcingaResult.$Command.perfdata)));
}
if ($NoExit) {

View file

@ -40,9 +40,13 @@ function New-IcingaEnvironmentVariable()
'CheckData' = @{ };
'ThresholdCache' = @{ };
'CheckResults' = @();
'PerformanceData' = @();
'PerformanceData' = '';
'PluginException' = $null;
'ExitCode' = $null;
'PerfDataWriter' = @{
'Cache' = @{};
'Storage' = (New-Object System.Text.StringBuilder);
}
}
);

View file

@ -14,6 +14,13 @@
to the lowest base of the unit. It does support the Icinga
plugin language, like ~:30, @10:40, 15:30, ...
You can also provide date time values in the format of "yyyy/MM/dd HH:mm:ss"
and use Icinga for Windows plugin thresholds in combination. You have to escape
the ':' inside the date time value with a '`' to ensure the correct conversion.
Example:
2024/08/19 12`:42`:00
The conversion does currently support the following units:
Size: B, KB, MB, GB, TB, PT, KiB, MiB, GiB, TiB, PiB
@ -26,43 +33,90 @@
Name Value
---- -----
Value 1728000
EndRange
Unit s
StartRange
Threshold 1728000
Mode 0
Raw 20d
IsDateTime False
Value 1728000
.EXAMPLE
PS>Convert-IcingaPluginThresholds -Threshold '5GB';
Name Value
---- -----
Value 5000000000
EndRange
Unit B
StartRange
Threshold 5000000000
Mode 0
Raw 5GB
IsDateTime False
Value 5000000000
.EXAMPLE
PS>Convert-IcingaPluginThresholds -Threshold '10MB:20MB';
Name Value
---- -----
Value 10000000:20000000
EndRange 20000000
Unit B
StartRange 10000000
Threshold 10000000:20000000
Mode 3
Raw 10MB:20MB
IsDateTime False
Value
.EXAMPLE
PS>Convert-IcingaPluginThresholds -Threshold '10m:1h';
Name Value
---- -----
Value 600:3600
EndRange 3600
Unit s
StartRange 600
Threshold 600:3600
Mode 3
Raw 10m:1h
Value
.EXAMPLE
PS>Convert-IcingaPluginThresholds -Threshold '@10m:1h';
Name Value
---- -----
Value @600:3600
EndRange 3600
Unit s
StartRange 600
Threshold @600:3600
Mode 4
Raw @10m:1h
IsDateTime False
Value
.EXAMPLE
Convert-IcingaPluginThresholds -Threshold '~:1M';
PS>Convert-IcingaPluginThresholds -Threshold '~:1M';
Name Value
---- -----
Value ~:2592000
EndRange
Unit s
StartRange
Threshold ~:2592000
Mode 2
Raw ~:1M
IsDateTime False
Value 2592000
.EXAMPLE
PS>Convert-IcingaPluginThresholds -Threshold '@2024/08/19 12`:42`:00:2024/08/19 12`:42`:00';
Name Value
---- -----
EndRange 133685377200000000
Unit s
StartRange 133685377200000000
Threshold @133685377200000000:133685377200000000
Mode 4
Raw @2024/08/19 12`:42`:00:2024/08/19 12`:42`:00
IsDateTime True
Value
.INPUTS
System.String
.OUTPUTS
@ -78,35 +132,80 @@ function Convert-IcingaPluginThresholds()
);
[hashtable]$RetValue = @{
'Unit' = '';
'Value' = $null;
'Raw' = $Threshold;
'Unit' = '';
'Threshold' = $null;
'Value' = $null;
'StartRange' = $null;
'EndRange' = $null;
'Mode' = $IcingaEnums.IcingaThresholdMethod.Default;
'IsDateTime' = $FALSE;
};
if ($null -eq $Threshold) {
if ([string]::IsNullOrEmpty($Threshold)) {
return $RetValue;
}
# Always ensure we are using correct digits
$Threshold = $Threshold.Replace(',', '.');
[array]$Content = @();
$Threshold = $Threshold.Replace(',', '.');
[array]$Content = @();
if ($Threshold.Contains(':')) {
# If we have more than one ':' inside our string, lets check if this is a date time value
# In case it is convert it properly to a FileTime we can work with later on
if ([Regex]::Matches($Threshold, ":").Count -gt 1) {
try {
$DateTimeValue = [DateTime]::ParseExact($Threshold, 'yyyy\/MM\/dd HH:mm:ss', $null);
$RetValue.Value = $DateTimeValue.ToFileTime();
$RetValue.Unit = 's';
} catch {
$RetValue.Value = $Threshold;
if ([Regex]::Matches($Threshold, '`:').Count -gt 1) {
[bool]$HasTilde = $FALSE;
[bool]$HasAt = $FALSE;
if ($Threshold.Contains('@')) {
$HasAt = $TRUE;
} elseif ($Threshold.Contains('~')) {
$HasTilde = $TRUE;
}
return $RetValue;
$Threshold = $Threshold.Replace('`:', '!').Replace('~', '').Replace('@', '');
[array]$DatimeValueArray = $Threshold.Split(':');
try {
[array]$DateTimeValue = @();
if ([string]::IsNullOrEmpty($DatimeValueArray[0]) -eq $FALSE) {
[array]$DateTimeValue += ([DateTime]::ParseExact($DatimeValueArray[0].Replace('!', ':'), 'yyyy\/MM\/dd HH:mm:ss', $null)).ToFileTime();
}
if ([string]::IsNullOrEmpty($DatimeValueArray[1]) -eq $FALSE) {
[array]$DateTimeValue += ([DateTime]::ParseExact($DatimeValueArray[1].Replace('!', ':'), 'yyyy\/MM\/dd HH:mm:ss', $null)).ToFileTime();
}
if ($DateTimeValue.Count -gt 1) {
$Threshold = [string]::Join(':', $DateTimeValue);
$RetValue.Mode = $IcingaEnums.IcingaThresholdMethod.Between;
if ($HasAt) {
$Threshold = [string]::Format('@{0}', $Threshold);
}
} elseif ($DatimeValueArray.Count -gt 1) {
if ($HasTilde) {
$Threshold = [string]::Format('~:{0}', $DateTimeValue[0]);
} else {
$Threshold = [string]::Format('{0}:', $DateTimeValue[0]);
}
} else {
$Threshold = $DateTimeValue[0];
}
$RetValue.Unit = 's';
$RetValue.IsDateTime = $TRUE;
} catch {
$RetValue.Threshold = $Threshold.Replace('!', '`:');
Exit-IcingaThrowException -CustomMessage ([string]::Format('Could not convert the provided threshold value {0} to a valid Icinga for Windows range', $RetValue.Raw)) -ExceptionType 'Input' -ExceptionThrown $IcingaExceptions.Inputs.InvalidThresholdValue -Force;
return $RetValue;
}
} else {
$RetValue.Mode = $IcingaEnums.IcingaThresholdMethod.Between;
}
$Content = $Threshold.Split(':');
if ($Content.Count -eq 2 -And ([string]::IsNullOrEmpty($Content[1]))) {
$RetValue.Mode = $IcingaEnums.IcingaThresholdMethod.Lower;
}
} else {
$Content += $Threshold;
}
@ -123,10 +222,12 @@ function Convert-IcingaPluginThresholds()
if ($ThresholdValue.Contains('~')) {
$ThresholdValue = $ThresholdValue.Replace('~', '');
$HasTilde = $TRUE;
$HasTilde = $TRUE;
$RetValue.Mode = $IcingaEnums.IcingaThresholdMethod.Greater;
} elseif ($ThresholdValue.Contains('@')) {
$HasAt = $TRUE;
$HasAt = $TRUE;
$ThresholdValue = $ThresholdValue.Replace('@', '');
$RetValue.Mode = $IcingaEnums.IcingaThresholdMethod.Outside;
}
if ($ThresholdValue[0] -eq '-' -And $ThresholdValue.Length -ge 1) {
@ -201,16 +302,67 @@ function Convert-IcingaPluginThresholds()
[string]$Value = [string]::Join(':', $ConvertedValue);
switch ($RetValue.Mode) {
$IcingaEnums.IcingaThresholdMethod.Default {
$RetValue.Value = $ConvertedValue[0];
if ([string]::IsNullOrEmpty($RetValue.Value)) {
Exit-IcingaThrowException -CustomMessage ([string]::Format('Could not convert the provided threshold value {0} to a valid Icinga for Windows range', $RetValue.Raw)) -ExceptionType 'Input' -ExceptionThrown $IcingaExceptions.Inputs.InvalidThresholdValue -Force;
return $RetValue;
}
break;
};
$IcingaEnums.IcingaThresholdMethod.Lower {
$RetValue.Value = $ConvertedValue[0];
if ([string]::IsNullOrEmpty($RetValue.Value)) {
Exit-IcingaThrowException -CustomMessage ([string]::Format('Could not convert the provided threshold value {0} to a valid Icinga for Windows range', $RetValue.Raw)) -ExceptionType 'Input' -ExceptionThrown $IcingaExceptions.Inputs.InvalidThresholdValue -Force;
return $RetValue;
}
break;
};
$IcingaEnums.IcingaThresholdMethod.Greater {
$RetValue.Value = $ConvertedValue[1];
if ([string]::IsNullOrEmpty($RetValue.Value)) {
Exit-IcingaThrowException -CustomMessage ([string]::Format('Could not convert the provided threshold value {0} to a valid Icinga for Windows range', $RetValue.Raw)) -ExceptionType 'Input' -ExceptionThrown $IcingaExceptions.Inputs.InvalidThresholdValue -Force;
return $RetValue;
}
break;
};
$IcingaEnums.IcingaThresholdMethod.Between {
$RetValue.StartRange = [decimal]$ConvertedValue[0];
$RetValue.EndRange = [decimal]$ConvertedValue[1];
if ([string]::IsNullOrEmpty($RetValue.StartRange) -Or [string]::IsNullOrEmpty($RetValue.EndRange)) {
Exit-IcingaThrowException -CustomMessage ([string]::Format('Could not convert the provided threshold value {0} to a valid Icinga for Windows range', $RetValue.Raw)) -ExceptionType 'Input' -ExceptionThrown $IcingaExceptions.Inputs.InvalidThresholdValue -Force;
return $RetValue;
}
break;
};
$IcingaEnums.IcingaThresholdMethod.Outside {
$RetValue.StartRange = [decimal]($ConvertedValue[0].Replace('@', ''));
$RetValue.EndRange = [decimal]$ConvertedValue[1];
if ([string]::IsNullOrEmpty($RetValue.StartRange) -Or [string]::IsNullOrEmpty($RetValue.EndRange)) {
Exit-IcingaThrowException -CustomMessage ([string]::Format('Could not convert the provided threshold value {0} to a valid Icinga for Windows range', ($RetValue.Raw))) -ExceptionType 'Input' -ExceptionThrown $IcingaExceptions.Inputs.InvalidThresholdValue -Force;
return $RetValue;
}
break;
};
}
if ([string]::IsNullOrEmpty($Value) -eq $FALSE -And $Value.Contains(':') -eq $FALSE) {
if ((Test-Numeric $Value)) {
$RetValue.Value = [decimal]$Value;
$RetValue.Threshold = [decimal]$Value;
$RetValue.Value = [decimal]$Value;
return $RetValue;
}
}
# Always ensure we are using correct digits
$Value = ([string]$Value).Replace(',', '.');
$RetValue.Value = $Value;
$Value = ([string]$Value).Replace(',', '.');
$RetValue.Threshold = $Value;
return $RetValue;
}

View file

@ -1,12 +1,57 @@
<#
.SYNOPSIS
Converts an Icinga plugin value to a human-readable string.
.DESCRIPTION
The Convert-IcingaPluginValueToString function is used to convert an Icinga plugin value to a human-readable string. It supports various units and can handle percentage values.
.PARAMETER Value
The value to be converted.
.PARAMETER BaseValue
The base value used for percentage calculations.
.PARAMETER Unit
The unit of the value.
.PARAMETER OriginalUnit
The original unit of the value.
.PARAMETER UsePercent
Specifies whether to treat the value as a percentage.
.PARAMETER IsThreshold
Specifies whether the value is a threshold.
.OUTPUTS
System.String
Returns the converted value as a human-readable string.
.EXAMPLE
Convert-IcingaPluginValueToString -Value 1024 -Unit 'KiB'
Converts the value 1024 with the unit 'KiB' to a human-readable string.
.EXAMPLE
Convert-IcingaPluginValueToString -Value 50 -BaseValue 100 -UsePercent
Converts the value 50 as a percentage of the base value 100 to a human-readable string.
.NOTES
This function is part of the Icinga PowerShell Framework module.
#>
function Convert-IcingaPluginValueToString()
{
param (
$Value,
$Value = $null,
$BaseValue = $null,
[string]$Unit = '',
[string]$OriginalUnit = ''
[string]$OriginalUnit = '',
[switch]$UsePercent = $FALSE,
[switch]$IsThreshold = $FALSE
);
$AdjustedValue = $Value;
$AdjustedValue = $Value;
$PercentValue = $null;
$HumanReadableValue = $null;
if ([string]::IsNullOrEmpty($OriginalUnit)) {
$OriginalUnit = $Unit;
@ -18,25 +63,46 @@ function Convert-IcingaPluginValueToString()
$AdjustedValue = $Value;
}
if ($Unit -eq '%' -Or [string]::IsNullOrEmpty($Unit)) {
if ($UsePercent -And ($null -eq $BaseValue -Or $BaseValue -eq 0)) {
return ([string]::Format('{0}{1}', ([string]$AdjustedValue).Replace(',', '.'), $Unit));
} elseif ($UsePercent) {
$Unit = $OriginalUnit;
if ($IsThreshold) {
$PercentValue = [math]::Round($Value, 2);
$AdjustedValue = [math]::Round(($BaseValue / 100) * $Value, 2);
} else {
$PercentValue = [math]::Round(($Value / $BaseValue) * 100, 2);
}
}
switch ($OriginalUnit) {
{ ($_ -eq "Kbit") -or ($_ -eq "Mbit") -or ($_ -eq "Gbit") -or ($_ -eq "Tbit") -or ($_ -eq "Pbit") -or ($_ -eq "Ebit") -or ($_ -eq "Zbit") -or ($_ -eq "Ybit") } {
$TransferSpeed = Get-IcingaNetworkInterfaceUnits -Value $Value -Unit $Unit;
return ([string]::Format('{0}{1}', $TransferSpeed.LinkSpeed, $TransferSpeed.Unit)).Replace(',', '.');
$TransferSpeed = Get-IcingaNetworkInterfaceUnits -Value $AdjustedValue -Unit $Unit;
$HumanReadableValue = ([string]::Format('{0}{1}', $TransferSpeed.LinkSpeed, $TransferSpeed.Unit)).Replace(',', '.');
break;
};
{ ($_ -eq "B") -or ($_ -eq "KiB") -or ($_ -eq "MiB") -or ($_ -eq "GiB") -or ($_ -eq "TiB") -or ($_ -eq "PiB") -or ($_ -eq "EiB") -or ($_ -eq "ZiB") -or ($_ -eq "YiB") } {
return (ConvertTo-BytesNextUnit -Value $Value -Unit $Unit -Units @('B', 'KiB', 'MiB', 'GiB', 'TiB', 'PiB', 'EiB', 'ZiB', 'YiB')).Replace(',', '.');
$HumanReadableValue = (ConvertTo-BytesNextUnit -Value $AdjustedValue -Unit $Unit -Units @('B', 'KiB', 'MiB', 'GiB', 'TiB', 'PiB', 'EiB', 'ZiB', 'YiB')).Replace(',', '.');
break;
};
{ ($_ -eq "KB") -or ($_ -eq "MB") -or ($_ -eq "GB") -or ($_ -eq "TB") -or ($_ -eq "PB") -or ($_ -eq "EB") -or ($_ -eq "ZB") -or ($_ -eq "YB") } {
return (ConvertTo-BytesNextUnit -Value $Value -Unit $Unit -Units @('B', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB')).Replace(',', '.');
$HumanReadableValue = (ConvertTo-BytesNextUnit -Value $AdjustedValue -Unit $Unit -Units @('B', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB')).Replace(',', '.');
break;
};
's' {
return (ConvertFrom-TimeSpan -Seconds $AdjustedValue).Replace(',', '.')
$HumanReadableValue = (ConvertFrom-TimeSpan -Seconds $AdjustedValue).Replace(',', '.');
break;
};
}
return ([string]::Format('{0}{1}', ([string]$AdjustedValue).Replace(',', '.'), $Unit));
if ($null -eq $HumanReadableValue) {
$HumanReadableValue = ([string]::Format('{0}{1}', ([string]$AdjustedValue).Replace(',', '.'), $Unit));
}
# In case the value provided is a percentage value, we need to adjust the output so it doesn't make sense to add the percentage value again for this case
if ($UsePercent -And $Unit -ne '%') {
$HumanReadableValue = [string]::Format('{0} ({1}%)', $HumanReadableValue, $PercentValue);
}
return $HumanReadableValue;
}

View file

@ -25,6 +25,18 @@
3 = 'Magenta';
};
[hashtable]$IcingaThresholdMethod = @{
Default = 0; # 20
Lower = 1; # 20:
LowerEqual = 2;
Greater = 3; # ~:20
GreaterEqual = 4;
Between = 5; # 30:40
Outside = 6; # @20:30
Matches = 7;
NotMatches = 8;
};
[hashtable]$IcingaMeasurementUnits = @{
's' = 'seconds';
'ms' = 'milliseconds';
@ -79,6 +91,7 @@ if ($null -eq $IcingaEnums) {
[hashtable]$IcingaEnums = @{
IcingaExitCode = $IcingaExitCode;
IcingaExitCodeText = $IcingaExitCodeText;
IcingaThresholdMethod = $IcingaThresholdMethod;
IcingaExitCodeColor = $IcingaExitCodeColor;
IcingaMeasurementUnits = $IcingaMeasurementUnits;
#services

View file

@ -33,6 +33,7 @@
MSSQLCredentialHandling = 'The connection to MSSQL was not possible because your login credential was not correct.';
MSSQLCommandMissing = 'Failed to build a SQL query';
RegexError = 'A request was not handled properly because a provided regex could not be interpreted. Please validate your regex and try again. In case you are trying to access a ressource containing [], you will have to escape each symbol by using `. Example: myservice`[`]';
InvalidThresholdValue = 'A treshold value provided for the plugin was invalid and did not follow the Icinga for Windows threshold guidelines. Available formatting examples are: "20", "20:", "~:20", "20:30", "@20:30".';
};
[hashtable]$Configuration = @{

View file

@ -1,3 +1,83 @@
<#
.SYNOPSIS
Compares a value against specified thresholds and returns the result.
.DESCRIPTION
The Compare-IcingaPluginThresholds function compares a given value against specified thresholds and returns an object containing the comparison result. It supports various comparison methods such as Matches, NotMatches, Between, LowerEqual, and GreaterEqual. If an error occurs during the comparison, the function returns an object with the error details.
.PARAMETER Threshold
Specifies the threshold value or range to compare against. This can be a single value or a range specified in the format "min:max". If not provided, the function assumes no threshold.
.PARAMETER InputValue
Specifies the value to compare against the threshold.
.PARAMETER BaseValue
Specifies the base value for percentage calculations. If the unit is set to '%', the base value is used to calculate the percentage. If not provided, the function assumes no base value.
.PARAMETER Matches
Indicates that the comparison should use the Matches method. This method checks if the input value matches the threshold.
.PARAMETER NotMatches
Indicates that the comparison should use the NotMatches method. This method checks if the input value does not match the threshold.
.PARAMETER DateTime
Specifies whether the input value is a DateTime object. If set to $true, the input value is treated as a DateTime object.
.PARAMETER Unit
Specifies the unit of measurement for the values. This is used for percentage calculations. If not provided, the function assumes no unit.
.PARAMETER ThresholdCache
Specifies a cache object to store threshold values for reuse.
.PARAMETER CheckName
Specifies the name of the check being performed.
.PARAMETER PerfDataLabel
Specifies the label for the performance data.
.PARAMETER Translation
Specifies a hashtable for translating threshold values.
.PARAMETER Minium
Specifies the minimum threshold value for comparison. This is used when the IsBetween method is used.
.PARAMETER Maximum
Specifies the maximum threshold value for comparison. This is used when the IsBetween method is used.
.PARAMETER IsBetween
Indicates that the comparison should use the IsBetween method. This method checks if the input value is between the minimum and maximum thresholds.
.PARAMETER IsLowerEqual
Indicates that the comparison should use the IsLowerEqual method. This method checks if the input value is lower than or equal to the threshold.
.PARAMETER IsGreaterEqual
Indicates that the comparison should use the IsGreaterEqual method. This method checks if the input value is greater than or equal to the threshold.
.PARAMETER TimeInterval
Specifies the time interval for the comparison. This is used when the input value is a DateTime object.
.OUTPUTS
The function returns an object containing the comparison result. The object has the following properties:
- Value: The input value.
- Unit: The unit of measurement.
- Message: The result message of the comparison.
- IsOK: Indicates whether the comparison result is OK.
- HasError: Indicates whether an error occurred during the comparison.
- Threshold: The threshold value or range used for comparison.
- Minimum: The minimum threshold value used for comparison.
- Maximum: The maximum threshold value used for comparison.
.EXAMPLE
$threshold = "10:20"
$inputValue = 15
$baseValue = 100
$result = Compare-IcingaPluginThresholds -Threshold $threshold -InputValue $inputValue -BaseValue $baseValue
$result.IsOK
# Returns $true
.NOTES
This function is part of the Icinga PowerShell Framework module.
#>
function Compare-IcingaPluginThresholds()
{
param (
@ -20,489 +100,69 @@ function Compare-IcingaPluginThresholds()
[string]$TimeInterval = $null
);
# Fix possible numeric value comparison issues
$TestInput = Test-IcingaDecimal $InputValue;
$BaseInput = Test-IcingaDecimal $BaseValue;
try {
# Fix possible numeric value comparison issues
$TestInput = Test-IcingaDecimal $InputValue;
$BaseInput = Test-IcingaDecimal $BaseValue;
if ($TestInput.Decimal) {
[decimal]$InputValue = [decimal]$TestInput.Value;
}
if ($BaseInput.Decimal) {
[decimal]$BaseValue = [decimal]$BaseInput.Value;
}
$IcingaThresholds = New-Object -TypeName PSObject;
$IcingaThresholds | Add-Member -MemberType NoteProperty -Name 'Value' -Value $InputValue;
$IcingaThresholds | Add-Member -MemberType NoteProperty -Name 'BaseValue' -Value $BaseValue;
$IcingaThresholds | Add-Member -MemberType NoteProperty -Name 'RawValue' -Value $InputValue;
$IcingaThresholds | Add-Member -MemberType NoteProperty -Name 'Unit' -Value $Unit;
$IcingaThresholds | Add-Member -MemberType NoteProperty -Name 'OriginalUnit' -Value $Unit;
$IcingaThresholds | Add-Member -MemberType NoteProperty -Name 'PerfUnit' -Value $Unit;
$IcingaThresholds | Add-Member -MemberType NoteProperty -Name 'IcingaThreshold' -Value $Threshold;
$IcingaThresholds | Add-Member -MemberType NoteProperty -Name 'RawThreshold' -Value $Threshold;
$IcingaThresholds | Add-Member -MemberType NoteProperty -Name 'CompareValue' -Value $null;
$IcingaThresholds | Add-Member -MemberType NoteProperty -Name 'MinRangeValue' -Value $null;
$IcingaThresholds | Add-Member -MemberType NoteProperty -Name 'MaxRangeValue' -Value $null;
$IcingaThresholds | Add-Member -MemberType NoteProperty -Name 'PercentValue' -Value '';
$IcingaThresholds | Add-Member -MemberType NoteProperty -Name 'TimeSpan' -Value '';
$IcingaThresholds | Add-Member -MemberType NoteProperty -Name 'TimeSpanOutput' -Value '';
$IcingaThresholds | Add-Member -MemberType NoteProperty -Name 'InRange' -Value $TRUE;
$IcingaThresholds | Add-Member -MemberType NoteProperty -Name 'Message' -Value '';
$IcingaThresholds | Add-Member -MemberType NoteProperty -Name 'Range' -Value '';
$IcingaThresholds | Add-Member -MemberType NoteProperty -Name 'FullMessage' -Value (
[string]::Format('{0}', (ConvertTo-IcingaPluginOutputTranslation -Translation $Translation -Value (Convert-IcingaPluginValueToString -Unit $Unit -Value $InputValue)))
);
$IcingaThresholds | Add-Member -MemberType NoteProperty -Name 'HeaderValue' -Value $IcingaThresholds.FullMessage;
$IcingaThresholds | Add-Member -MemberType NoteProperty -Name 'ErrorMessage' -Value '';
$IcingaThresholds | Add-Member -MemberType NoteProperty -Name 'HasError' -Value $FALSE;
# In case we are using % values, we should set the BaseValue always to 100
if ($Unit -eq '%' -And $null -eq $BaseValue) {
$BaseValue = 100;
}
if ([string]::IsNullOrEmpty($TimeInterval) -eq $FALSE -And $null -ne $ThresholdCache) {
$TimeSeconds = ConvertTo-Seconds $TimeInterval;
$IntervalLabelName = (Format-IcingaPerfDataLabel -PerfData $CheckName);
$IntervalMultiLabelName = (Format-IcingaPerfDataLabel -PerfData $CheckName -MultiOutput);
if ([string]::IsNullOrEmpty($PerfDataLabel) -eq $FALSE) {
$IntervalLabelName = $PerfDataLabel;
$IntervalMultiLabelName = $PerfDataLabel;
if ($TestInput.Decimal) {
[decimal]$InputValue = [decimal]$TestInput.Value;
}
if ($BaseInput.Decimal) {
[decimal]$BaseValue = [decimal]$BaseInput.Value;
}
$MinuteInterval = [math]::round(([TimeSpan]::FromSeconds($TimeSeconds)).TotalMinutes, 0);
$CheckPerfDataLabel = [string]::Format('{0}_{1}', $IntervalLabelName, $MinuteInterval);
$MultiPerfDataLabel = [string]::Format('::{0}::Interval{1}', $IntervalMultiLabelName, $TimeSeconds);
[bool]$FoundInterval = $FALSE;
$IcingaThresholds = New-Object -TypeName PSObject;
$IcingaThresholds | Add-Member -MemberType NoteProperty -Name 'Value' -Value $InputValue;
$IcingaThresholds | Add-Member -MemberType NoteProperty -Name 'Unit' -Value $Unit;
$IcingaThresholds | Add-Member -MemberType NoteProperty -Name 'Message' -Value '';
$IcingaThresholds | Add-Member -MemberType NoteProperty -Name 'IsOK' -Value $FALSE;
$IcingaThresholds | Add-Member -MemberType NoteProperty -Name 'HasError' -Value $FALSE;
$IcingaThresholds | Add-Member -MemberType NoteProperty -Name 'Threshold' -Value (Convert-IcingaPluginThresholds -Threshold $Threshold);
$IcingaThresholds | Add-Member -MemberType NoteProperty -Name 'Minimum' -Value (Convert-IcingaPluginThresholds -Threshold $Minium);
$IcingaThresholds | Add-Member -MemberType NoteProperty -Name 'Maximum' -Value (Convert-IcingaPluginThresholds -Threshold $Maximum);
if ($null -ne $ThresholdCache.$CheckPerfDataLabel) {
$InputValue = $ThresholdCache.$CheckPerfDataLabel;
$InputValue = [math]::round([decimal]$InputValue, 6);
$IcingaThresholds.TimeSpanOutput = $MinuteInterval;
$IcingaThresholds.TimeSpan = $MinuteInterval;
$FoundInterval = $TRUE;
# In case we are using % values, we should set the BaseValue always to 100
if ($Unit -eq '%' -And $null -eq $BaseValue) {
$IcingaThresholds | Add-Member -MemberType NoteProperty -Name 'BaseValue' -Value 100;
} else {
$IcingaThresholds | Add-Member -MemberType NoteProperty -Name 'BaseValue' -Value $BaseValue;
}
if ($null -ne $ThresholdCache.$MultiPerfDataLabel) {
$InputValue = $ThresholdCache.$MultiPerfDataLabel;
$InputValue = [math]::round([decimal]$InputValue, 6);
$IcingaThresholds.TimeSpanOutput = $MinuteInterval;
$IcingaThresholds.TimeSpan = $TimeSeconds;
$FoundInterval = $TRUE;
$CheckResult = $null;
if ($Matches) {
$CheckResult = Compare-IcingaPluginValueToThreshold -Value $InputValue -BaseValue $IcingaThresholds.BaseValue -Threshold $IcingaThresholds.Threshold -Unit $Unit -Translation $Translation -OverrideMode $IcingaEnums.IcingaThresholdMethod.Matches;
} elseif ($NotMatches) {
$CheckResult = Compare-IcingaPluginValueToThreshold -Value $InputValue -BaseValue $IcingaThresholds.BaseValue -Threshold $IcingaThresholds.Threshold -Unit $Unit -Translation $Translation -OverrideMode $IcingaEnums.IcingaThresholdMethod.NotMatches;
} elseif ($IsBetween) {
$CheckResult = Compare-IcingaPluginValueToThreshold -Value $InputValue -BaseValue $IcingaThresholds.BaseValue -Threshold $IcingaThresholds.Threshold -Unit $Unit -Translation $Translation -OverrideMode $IcingaEnums.IcingaThresholdMethod.Between;
} elseif ($IsLowerEqual) {
$CheckResult = Compare-IcingaPluginValueToThreshold -Value $InputValue -BaseValue $IcingaThresholds.BaseValue -Threshold $IcingaThresholds.Threshold -Unit $Unit -Translation $Translation -OverrideMode $IcingaEnums.IcingaThresholdMethod.LowerEqual;
} elseif ($IsGreaterEqual) {
$CheckResult = Compare-IcingaPluginValueToThreshold -Value $InputValue -BaseValue $IcingaThresholds.BaseValue -Threshold $IcingaThresholds.Threshold -Unit $Unit -Translation $Translation -OverrideMode $IcingaEnums.IcingaThresholdMethod.GreaterEqual;
} else {
$CheckResult = Compare-IcingaPluginValueToThreshold -Value $InputValue -BaseValue $IcingaThresholds.BaseValue -Threshold $IcingaThresholds.Threshold -Unit $Unit -Translation $Translation;
}
if ($FoundInterval -eq $FALSE) {
$IcingaThresholds.HasError = $TRUE;
$IcingaThresholds.ErrorMessage = [string]::Format(
'The provided time interval "{0}" which translates to "{1}m" in your "-ThresholdInterval" argument does not exist',
$TimeInterval,
$MinuteInterval
);
return $IcingaThresholds;
}
} <#else {
# The symbol splitting our threshold from the time index value
# Examples:
# @20:40#15m
# ~:40#15m
# 40#15m
$TimeIndexSeparator = '#';
$IcingaThresholds.Message = $CheckResult.Message;
$IcingaThresholds.IsOK = $CheckResult.IsOK;
$IcingaThresholds.HasError = $CheckResult.HasError;
# In case we found a ~ not starting at the beginning, we should load the
# time index values created by our background daemon
# Allows us to specify something like "40:50#15"
if ($Threshold.Contains($TimeIndexSeparator) -And $null -ne $ThresholdCache) {
[int]$LastIndex = $Threshold.LastIndexOf($TimeIndexSeparator);
if ($LastIndex -ne 0) {
$TmpValue = $Threshold;
$Threshold = $TmpValue.Substring(0, $LastIndex);
$TimeIndex = $TmpValue.Substring($LastIndex + 1, $TmpValue.Length - $LastIndex - 1);
$TimeSeconds = ConvertTo-Seconds $TimeIndex;
$MinuteInterval = [math]::round(([TimeSpan]::FromSeconds($TimeSeconds)).TotalMinutes, 0);
$CheckPerfDataLabel = [string]::Format('{0}_{1}', (Format-IcingaPerfDataLabel $CheckName), $MinuteInterval);
if ($null -ne $ThresholdCache.$CheckPerfDataLabel) {
$InputValue = $ThresholdCache.$CheckPerfDataLabel;
$InputValue = [math]::round([decimal]$InputValue, 6);
$IcingaThresholds.TimeSpan = $MinuteInterval;
} else {
$IcingaThresholds.HasError = $TRUE;
$IcingaThresholds.ErrorMessage = [string]::Format(
'The provided time interval "{0}{1}" which translates to "{2}m" in your "-ThresholdInterval" argument does not exist',
$TimeIndexSeparator,
$TimeIndex,
$MinuteInterval
);
}
}
}
}#>
[bool]$UseDynamicPercentage = $FALSE;
[hashtable]$ConvertedThreshold = Convert-IcingaPluginThresholds -Threshold $Threshold;
$Minimum = (Convert-IcingaPluginThresholds -Threshold $Minimum).Value;
$Maximum = (Convert-IcingaPluginThresholds -Threshold $Maximum).Value;
[string]$ThresholdValue = $ConvertedThreshold.Value;
$IcingaThresholds.Unit = $ConvertedThreshold.Unit;
$IcingaThresholds.IcingaThreshold = $ThresholdValue;
$TempValue = (Convert-IcingaPluginThresholds -Threshold ([string]::Format('{0}{1}', $InputValue, $Unit)));
$InputValue = $TempValue.Value;
$TmpUnit = $TempValue.Unit;
$TestInput = Test-IcingaDecimal $InputValue;
if ($TestInput.Decimal) {
[decimal]$InputValue = [decimal]$TestInput.Value;
}
$IcingaThresholds.RawValue = $InputValue;
$TempValue = (Convert-IcingaPluginThresholds -Threshold ([string]::Format('{0}{1}', $BaseValue, $Unit)));
$BaseValue = $TempValue.Value;
$Unit = $TmpUnit;
$IcingaThresholds.PerfUnit = $Unit;
$IcingaThresholds.BaseValue = $BaseValue;
if ([string]::IsNullOrEmpty($IcingaThresholds.Unit)) {
$IcingaThresholds.Unit = $Unit;
}
# Calculate % value from base value of set
if ([string]::IsNullOrEmpty($BaseValue) -eq $FALSE -And $BaseValue -ne 0 -And $IcingaThresholds.Unit -eq '%') {
$InputValue = $InputValue / $BaseValue * 100;
$UseDynamicPercentage = $TRUE;
} elseif ([string]::IsNullOrEmpty($BaseValue) -eq $TRUE -And $IcingaThresholds.Unit -eq '%') {
$IcingaThresholds.HasError = $TRUE;
$IcingaThresholds.ErrorMessage = 'This argument does not support the % unit';
return $IcingaThresholds;
} catch {
$IcingaThresholds = New-Object -TypeName PSObject;
$IcingaThresholds | Add-Member -MemberType NoteProperty -Name 'Value' -Value $InputValue;
$IcingaThresholds | Add-Member -MemberType NoteProperty -Name 'Unit' -Value $Unit;
$IcingaThresholds | Add-Member -MemberType NoteProperty -Name 'Message' -Value $_.Exception.Message;
$IcingaThresholds | Add-Member -MemberType NoteProperty -Name 'IsOK' -Value $FALSE;
$IcingaThresholds | Add-Member -MemberType NoteProperty -Name 'HasError' -Value $TRUE;
$IcingaThresholds | Add-Member -MemberType NoteProperty -Name 'Threshold' -Value $Threshold;
$IcingaThresholds | Add-Member -MemberType NoteProperty -Name 'Minimum' -Value $Minium;
$IcingaThresholds | Add-Member -MemberType NoteProperty -Name 'Maximum' -Value $Maximum;
return $IcingaThresholds;
}
# Always override our InputValue, case we might have change it
$IcingaThresholds.Value = $InputValue;
# If we simply provide a numeric number, we always check Value > Threshold or Value < 0
if ($Matches) {
# Checks if the InputValue Matches the Threshold
if ($InputValue -Like $ThresholdValue) {
$IcingaThresholds.InRange = $FALSE;
$IcingaThresholds.Message = 'is matching threshold';
$IcingaThresholds.Range = [string]::Format(
'{0}',
(ConvertTo-IcingaPluginOutputTranslation -Translation $Translation -Value (Convert-IcingaPluginValueToString -Unit $IcingaThresholds.Unit -Value $ThresholdValue -OriginalUnit $IcingaThresholds.OriginalUnit))
);
}
} elseif ($NotMatches) {
# Checks if the InputValue not Matches the Threshold
if ($InputValue -NotLike $ThresholdValue) {
$IcingaThresholds.InRange = $FALSE;
$IcingaThresholds.Message = 'is not matching threshold';
$IcingaThresholds.Range = [string]::Format(
'{0}',
(ConvertTo-IcingaPluginOutputTranslation -Translation $Translation -Value (Convert-IcingaPluginValueToString -Unit $IcingaThresholds.Unit -Value $ThresholdValue -OriginalUnit $IcingaThresholds.OriginalUnit))
);
}
} elseif ($DateTime) {
# Checks if the InputValue Is Inside our time value
try {
$DateTimeValue = 0;
[decimal]$TimeThreshold = 0;
$CurrentDate = $global:Icinga.CurrentDate;
$IcingaThresholds.Unit = '';
if ([string]::IsNullOrEmpty($InputValue) -eq $FALSE) {
$DateTimeValue = [DateTime]::FromFileTime($InputValue);
$IcingaThresholds.Value = $DateTimeValue.ToString('yyyy\/MM\/dd HH:mm:ss');
}
if ([string]::IsNullOrEmpty($ThresholdValue) -eq $FALSE) {
$TimeThreshold = (ConvertTo-Seconds -Value $Threshold);
$CurrentDate = $CurrentDate.AddSeconds($TimeThreshold);
$IcingaThresholds.IcingaThreshold = $CurrentDate.ToFileTimeUtc();
}
if ([string]::IsNullOrEmpty($ThresholdValue) -eq $FALSE -And ($DateTimeValue -eq 0 -Or $DateTimeValue -lt $CurrentDate)) {
$IcingaThresholds.InRange = $FALSE;
$IcingaThresholds.Message = 'is lower than';
$IcingaThresholds.Range = [string]::Format(
'{0} ({1}{2})',
((Get-Date).ToString('yyyy\/MM\/dd HH:mm:ss')),
( $( if ($TimeThreshold -ge 0) { '+'; } else { ''; } )),
$Threshold
);
}
} catch {
$IcingaThresholds.ErrorMessage = [string]::Format(
'Invalid date time specified. Your InputValue "{0}" seems not be a valid date time or your provided Threshold "{1}" cannot be converted to seconds. Exception: {2}',
$InputValue,
$ThresholdValue,
$_.Exception.Message
);
$IcingaThresholds.HasError = $TRUE;
return $IcingaThresholds;
}
} elseif ($IsBetween) {
if ($InputValue -gt $Minium -And $InputValue -lt $Maximum) {
$IcingaThresholds.InRange = $FALSE;
$IcingaThresholds.Message = 'is inside range';
$IcingaThresholds.Range = [string]::Format(
'{0} and {1}',
(ConvertTo-IcingaPluginOutputTranslation -Translation $Translation -Value (Convert-IcingaPluginValueToString -Unit $IcingaThresholds.Unit -Value $Minium -OriginalUnit $IcingaThresholds.OriginalUnit)),
(ConvertTo-IcingaPluginOutputTranslation -Translation $Translation -Value (Convert-IcingaPluginValueToString -Unit $IcingaThresholds.Unit -Value $Maximum -OriginalUnit $IcingaThresholds.OriginalUnit))
);
}
if ($IcingaThresholds.Unit -eq '%') {
$IcingaThresholds.RawThreshold = [string]::Format(
'{0}% ({2}) {1}% ({3})',
(ConvertFrom-Percent -Value $BaseValue -Percent $Minium),
(ConvertFrom-Percent -Value $BaseValue -Percent $Maximum),
(Convert-IcingaPluginValueToString -Unit $Unit -Value $Minium -OriginalUnit $IcingaThresholds.OriginalUnit),
(Convert-IcingaPluginValueToString -Unit $Unit -Value $Maximum -OriginalUnit $IcingaThresholds.OriginalUnit)
);
$IcingaThresholds.PercentValue = [string]::Format(
'@{0}:{1}',
(ConvertFrom-Percent -Value $BaseValue -Percent $Minium),
(ConvertFrom-Percent -Value $BaseValue -Percent $Maximum)
);
}
} elseif ($IsLowerEqual) {
if ($InputValue -le $ThresholdValue) {
$IcingaThresholds.InRange = $FALSE;
$IcingaThresholds.Message = 'is lower equal than threshold';
$IcingaThresholds.Range = [string]::Format(
'{0}',
(ConvertTo-IcingaPluginOutputTranslation -Translation $Translation -Value (Convert-IcingaPluginValueToString -Unit $IcingaThresholds.Unit -Value $ThresholdValue -OriginalUnit $IcingaThresholds.OriginalUnit))
);
}
if ($IcingaThresholds.Unit -eq '%') {
$IcingaThresholds.RawThreshold = [string]::Format(
'{0}% ({1})',
(ConvertFrom-Percent -Value $BaseValue -Percent $ThresholdValue),
(Convert-IcingaPluginValueToString -Unit $Unit -Value $ThresholdValue -OriginalUnit $IcingaThresholds.OriginalUnit)
);
$IcingaThresholds.PercentValue = [string]::Format(
'{0}:',
(ConvertFrom-Percent -Value $BaseValue -Percent $ThresholdValue)
);
}
} elseif ($IsGreaterEqual) {
if ($InputValue -ge $ThresholdValue) {
$IcingaThresholds.InRange = $FALSE;
$IcingaThresholds.Message = 'is greater equal than threshold';
$IcingaThresholds.Range = [string]::Format(
'{0}',
(ConvertTo-IcingaPluginOutputTranslation -Translation $Translation -Value (Convert-IcingaPluginValueToString -Unit $IcingaThresholds.Unit -Value $ThresholdValue -OriginalUnit $IcingaThresholds.OriginalUnit))
);
}
if ($IcingaThresholds.Unit -eq '%') {
$IcingaThresholds.RawThreshold = [string]::Format(
'{0}% ({1})',
(ConvertFrom-Percent -Value $BaseValue -Percent $ThresholdValue),
(Convert-IcingaPluginValueToString -Unit $Unit -Value $ThresholdValue -OriginalUnit $IcingaThresholds.OriginalUnit)
);
$IcingaThresholds.PercentValue = [string]::Format(
'~:{0}',
(ConvertFrom-Percent -Value $BaseValue -Percent $ThresholdValue)
);
}
} else {
if ((Test-Numeric $ThresholdValue)) {
if ($InputValue -gt $ThresholdValue -Or $InputValue -lt 0) {
$IcingaThresholds.InRange = $FALSE;
$IcingaThresholds.Message = 'is greater than threshold';
$IcingaThresholds.Range = [string]::Format('{0}', (Convert-IcingaPluginValueToString -Unit $Unit -Value $ThresholdValue -OriginalUnit $IcingaThresholds.OriginalUnit));
}
$IcingaThresholds.CompareValue = [decimal]$ThresholdValue;
if ($IcingaThresholds.Unit -eq '%') {
$IcingaThresholds.RawThreshold = [string]::Format('{0}% ({1})', $ThresholdValue, (Convert-IcingaPluginValueToString -Unit $Unit -Value (ConvertFrom-Percent -Value $BaseValue -Percent $ThresholdValue) -OriginalUnit $IcingaThresholds.OriginalUnit));
$IcingaThresholds.PercentValue = [string]::Format(
'{0}',
(ConvertFrom-Percent -Value $BaseValue -Percent $ThresholdValue)
);
}
} else {
# Transform our provided thresholds to split everything into single objects
[array]$thresholds = $ThresholdValue.Split(':');
[string]$rangeMin = $thresholds[0];
[string]$rangeMax = $thresholds[1];
[bool]$IsNegating = $rangeMin.Contains('@');
[string]$rangeMin = $rangeMin.Replace('@', '');
if ((Test-Numeric ($rangeMin.Replace('@', '').Replace('~', '')))) {
$IcingaThresholds.MinRangeValue = [decimal]($rangeMin.Replace('@', '').Replace('~', ''));
[decimal]$rangeMin = [decimal]$rangeMin;
}
if ((Test-Numeric $rangeMax)) {
$IcingaThresholds.MaxRangeValue = [decimal]$rangeMax;
[decimal]$rangeMax = [decimal]$rangeMax;
}
if ($IsNegating -eq $FALSE -And (Test-Numeric $rangeMin) -And (Test-Numeric $rangeMax)) {
# Handles: 30:40
# Error on: < 30 or > 40
# Ok on: between {30 .. 40}
if ($InputValue -lt $rangeMin -Or $InputValue -gt $rangeMax) {
$IcingaThresholds.InRange = $FALSE;
$IcingaThresholds.Message = 'is outside range';
$IcingaThresholds.Range = [string]::Format(
'{0} and {1}',
(ConvertTo-IcingaPluginOutputTranslation -Translation $Translation -Value (Convert-IcingaPluginValueToString -Unit $IcingaThresholds.Unit -Value $rangeMin -OriginalUnit $IcingaThresholds.OriginalUnit)),
(ConvertTo-IcingaPluginOutputTranslation -Translation $Translation -Value (Convert-IcingaPluginValueToString -Unit $IcingaThresholds.Unit -Value $rangeMax -OriginalUnit $IcingaThresholds.OriginalUnit))
);
}
if ($IcingaThresholds.Unit -eq '%') {
$IcingaThresholds.RawThreshold = [string]::Format(
'{0}% ({2}) and {1}% ({3})',
$rangeMin,
$rangeMax,
(Convert-IcingaPluginValueToString -Unit $Unit -Value (ConvertFrom-Percent -Value $BaseValue -Percent $rangeMin -OriginalUnit $IcingaThresholds.OriginalUnit)),
(Convert-IcingaPluginValueToString -Unit $Unit -Value (ConvertFrom-Percent -Value $BaseValue -Percent $rangeMax -OriginalUnit $IcingaThresholds.OriginalUnit))
);
$IcingaThresholds.PercentValue = [string]::Format(
'{0}:{1}',
(ConvertFrom-Percent -Value $BaseValue -Percent $rangeMin),
(ConvertFrom-Percent -Value $BaseValue -Percent $rangeMax)
);
}
} elseif ((Test-Numeric $rangeMin) -And [string]::IsNullOrEmpty($rangeMax) -eq $TRUE) {
# Handles: 20:
# Error on: 20:
# Ok on: between 20 .. ∞
if ($InputValue -lt $rangeMin) {
$IcingaThresholds.InRange = $FALSE;
$IcingaThresholds.Message = 'is lower than threshold';
$IcingaThresholds.Range = [string]::Format(
'{0}',
(ConvertTo-IcingaPluginOutputTranslation -Translation $Translation -Value (Convert-IcingaPluginValueToString -Unit $IcingaThresholds.Unit -Value $rangeMin -OriginalUnit $IcingaThresholds.OriginalUnit))
);
}
if ($IcingaThresholds.Unit -eq '%') {
$IcingaThresholds.RawThreshold = [string]::Format(
'{0}% ({1})',
$rangeMin,
(Convert-IcingaPluginValueToString -Unit $Unit -Value (ConvertFrom-Percent -Value $BaseValue -Percent $rangeMin -OriginalUnit $IcingaThresholds.OriginalUnit))
);
$IcingaThresholds.PercentValue = [string]::Format(
'{0}:',
(ConvertFrom-Percent -Value $BaseValue -Percent $rangeMin)
);
}
} elseif ($rangeMin -eq '~' -And (Test-Numeric $rangeMax)) {
# Handles: ~:20
# Error on: > 20
# Ok on: between -∞ .. 20
if ($InputValue -gt $rangeMax) {
$IcingaThresholds.InRange = $FALSE;
$IcingaThresholds.Message = 'is greater than threshold';
$IcingaThresholds.Range = [string]::Format(
'{0}',
(ConvertTo-IcingaPluginOutputTranslation -Translation $Translation -Value (Convert-IcingaPluginValueToString -Unit $IcingaThresholds.Unit -Value $rangeMax -OriginalUnit $IcingaThresholds.OriginalUnit))
);
}
if ($IcingaThresholds.Unit -eq '%') {
$IcingaThresholds.RawThreshold = [string]::Format(
'{0}% ({1})',
$rangeMax,
(Convert-IcingaPluginValueToString -Unit $Unit -Value (ConvertFrom-Percent -Value $BaseValue -Percent $rangeMax -OriginalUnit $IcingaThresholds.OriginalUnit))
);
$IcingaThresholds.PercentValue = [string]::Format(
'~:{0}',
(ConvertFrom-Percent -Value $BaseValue -Percent $rangeMax)
);
}
} elseif ($IsNegating -And (Test-Numeric $rangeMin) -And (Test-Numeric $rangeMax)) {
# Handles: @30:40
# Error on: ≥ 30 and ≤ 40
# Ok on: -∞ .. 29 and 41 .. ∞
if ($InputValue -ge $rangeMin -And $InputValue -le $rangeMax) {
$IcingaThresholds.InRange = $FALSE;
$IcingaThresholds.Message = 'is inside range';
$IcingaThresholds.Range = [string]::Format(
'{0} and {1}',
(ConvertTo-IcingaPluginOutputTranslation -Translation $Translation -Value (Convert-IcingaPluginValueToString -Unit $IcingaThresholds.Unit -Value $rangeMin -OriginalUnit $IcingaThresholds.OriginalUnit)),
(ConvertTo-IcingaPluginOutputTranslation -Translation $Translation -Value (Convert-IcingaPluginValueToString -Unit $IcingaThresholds.Unit -Value $rangeMax -OriginalUnit $IcingaThresholds.OriginalUnit))
);
}
if ($IcingaThresholds.Unit -eq '%') {
$IcingaThresholds.RawThreshold = [string]::Format(
'{0}% ({2}) {1}% ({3})',
$rangeMin,
$rangeMax,
(Convert-IcingaPluginValueToString -Unit $Unit -Value (ConvertFrom-Percent -Value $BaseValue -Percent $rangeMin -OriginalUnit $IcingaThresholds.OriginalUnit)),
(Convert-IcingaPluginValueToString -Unit $Unit -Value (ConvertFrom-Percent -Value $BaseValue -Percent $rangeMax -OriginalUnit $IcingaThresholds.OriginalUnit))
);
$IcingaThresholds.PercentValue = [string]::Format(
'@{0}:{1}',
(ConvertFrom-Percent -Value $BaseValue -Percent $rangeMin),
(ConvertFrom-Percent -Value $BaseValue -Percent $rangeMax)
);
}
} else {
if ([string]::IsNullOrEmpty($Threshold) -eq $FALSE) {
# Unhandled
$IcingaThresholds.ErrorMessage = [string]::Format(
'Invalid range specified for threshold: InputValue "{0}" and Threshold {1}',
$InputValue,
$Threshold
);
$IcingaThresholds.HasError = $TRUE;
return $IcingaThresholds;
}
}
}
}
$PluginOutputMessage = New-Object -TypeName 'System.Text.StringBuilder';
[string]$PluginCurrentValue = [string]::Format(
'{0}',
(ConvertTo-IcingaPluginOutputTranslation -Translation $Translation -Value (Convert-IcingaPluginValueToString -Unit $IcingaThresholds.Unit -Value $IcingaThresholds.Value -OriginalUnit $IcingaThresholds.OriginalUnit))
);
[string]$PluginThresholdValue = $IcingaThresholds.Range;
if ($UseDynamicPercentage -And $Unit -ne '%') {
$IcingaThresholds.IcingaThreshold = $IcingaThresholds.PercentValue;
$PluginCurrentValue = [string]::Format('{0}% ({1})', ([string]([math]::Round($IcingaThresholds.Value, 2))).Replace(',', '.'), (Convert-IcingaPluginValueToString -Unit $Unit -Value $IcingaThresholds.RawValue -OriginalUnit $IcingaThresholds.OriginalUnit));
$PluginThresholdValue = $IcingaThresholds.RawThreshold;
}
$IcingaThresholds.HeaderValue = $PluginCurrentValue;
$PluginOutputMessage.Append($PluginCurrentValue) | Out-Null;
if ([string]::IsNullOrEmpty($IcingaThresholds.Message) -eq $FALSE) {
$PluginOutputMessage.Append(' ') | Out-Null;
$PluginOutputMessage.Append($IcingaThresholds.Message.Replace(',', '.')) | Out-Null;
if ([string]::IsNullOrEmpty($PluginThresholdValue) -eq $FALSE) {
$PluginOutputMessage.Append(' ') | Out-Null;
$PluginOutputMessage.Append(([string]$PluginThresholdValue).Replace(',', '.')) | Out-Null;
}
}
# Lets build our full message for adding on the value
$IcingaThresholds.FullMessage = $PluginOutputMessage.ToString();
return $IcingaThresholds;
return $null;
}

View file

@ -0,0 +1,190 @@
<#
.SYNOPSIS
Compares a value to a threshold and returns a result.
.DESCRIPTION
The Compare-IcingaPluginValueToThreshold function compares a value to a threshold and returns a result indicating whether the value meets the threshold criteria. It supports various threshold methods such as default, lower, lower equal, greater, greater equal, between, outside, matches, and not matches. The function also handles percentage values and provides human-readable output.
.PARAMETER Value
The value to compare against the threshold.
.PARAMETER BaseValue
The base value used for percentage calculations.
.PARAMETER Unit
The unit of measurement for the value.
.PARAMETER Translation
The translation table for converting values to human-readable format.
.PARAMETER Threshold
The threshold object containing the threshold criteria.
.PARAMETER OverrideMode
The override mode for the threshold.
.OUTPUTS
A hashtable containing the following properties:
- Message: The result message indicating whether the value meets the threshold criteria.
- IsOk: A boolean value indicating whether the value meets the threshold criteria.
- HasError: A boolean value indicating whether an error occurred during the comparison.
.EXAMPLE
$threshold = @{
EndRange = $null;
Unit = 'B';
StartRange = $null;
Threshold = '30000000MB';
Mode = 0;
Raw = '30MB';
IsDateTime = $FALSE;
Value = 30000000;
}
Compare-IcingaPluginValueToThreshold -Value 450000000 -Unit 'B' -Threshold $threshold
This example compares the value 15 to the threshold criteria specified in the $threshold object. The function returns a hashtable with the result message, IsOk, and HasError properties.
.NOTES
This function is part of the Icinga PowerShell Framework module.
.LINK
https://github.com/icinga/icinga-powershell-framework
#>
function Compare-IcingaPluginValueToThreshold()
{
param (
$Value = $null,
$BaseValue = $null,
$Unit = $null,
$Translation = $null,
$Threshold = $null,
$OverrideMode = $null
);
[hashtable]$RetValue = @{
'Message' = '';
'IsOk' = $FALSE;
'HasError' = $FALSE;
}
$HumanReadableValue = $Value;
$PercentValue = $null;
$TranslatedValue = $Value;
[bool]$UsePercent = $FALSE;
# Otherwise just convert the values to human readble values
$HumanReadableValue = ConvertTo-IcingaPluginOutputTranslation -Translation $Translation -Value $HumanReadableValue;
$HumanReadableValue = Convert-IcingaPluginValueToString -Value $HumanReadableValue -Unit $Unit;
if ($null -eq $Value -Or $null -eq $Threshold -Or [string]::IsNullOrEmpty($Threshold.Raw)) {
$RetValue.Message = $HumanReadableValue;
$RetValue.IsOk = $TRUE;
return $RetValue;
}
if (Test-Numeric $Value) {
[decimal]$Value = $Value;
}
if ($null -eq $OverrideMode) {
$OverrideMode = $Threshold.Mode;
}
if ($Threshold.Unit -eq '%' -And $null -eq $BaseValue) {
$RetValue.Message = 'This plugin threshold does not support percentage units';
$RetValue.HasError = $TRUE;
return $RetValue;
}
# In case we have a percentage value, we need to adjust the value
if ($Threshold.Unit -eq '%' -And $null -ne $BaseValue -And $BaseValue -ne 0) {
$UsePercent = $TRUE;
$HumanReadableValue = Convert-IcingaPluginValueToString -Value $Value -BaseValue $BaseValue -Unit $Threshold.Unit -OriginalUnit $Unit -UsePercent:$UsePercent;
$Value = [math]::Round(($Value / $BaseValue) * 100, 2);
# Ensure that we properly set the threshold range or metrics we defined from percent to acutal values based on the BaseValue
# Otherwise performance metrics will not be properly reported, causing later issues for visualiation tools like Grafana
$Threshold = Convert-IcingaPluginThresholdsFromPercent -BaseValue $BaseValue -Threshold $Threshold;
} else {
$TranslatedValue = ConvertTo-IcingaPluginOutputTranslation -Translation $Translation -Value $Value;
}
switch ($OverrideMode) {
$IcingaEnums.IcingaThresholdMethod.Default {
if ($Value -lt 0 -Or $Value -gt $Threshold.Value) {
if ($Value -lt 0) {
$RetValue.Message = [string]::Format('Value {0} is lower than 0', $HumanReadableValue);
return $RetValue;
}
if ($Value -gt $Threshold.Value) {
$RetValue.Message = [string]::Format('Value {0} is greater than threshold {1}', $HumanReadableValue, (Convert-IcingaPluginValueToString -Value $Threshold.Value -BaseValue $BaseValue -Unit $Threshold.Unit -OriginalUnit $Unit -UsePercent:$UsePercent -IsThreshold));
return $RetValue;
}
}
break;
};
$IcingaEnums.IcingaThresholdMethod.Lower {
if ($Value -lt $Threshold.Value) {
$RetValue.Message = [string]::Format('Value {0} is lower than threshold {1}', $HumanReadableValue, (Convert-IcingaPluginValueToString -Value $Threshold.Value -BaseValue $BaseValue -Unit $Threshold.Unit -OriginalUnit $Unit -UsePercent:$UsePercent -IsThreshold));
return $RetValue;
}
break;
};
$IcingaEnums.IcingaThresholdMethod.LowerEqual {
if ($Value -le $Threshold.Value) {
$RetValue.Message = [string]::Format('Value {0} is lower or equal than threshold {1}', $HumanReadableValue, (Convert-IcingaPluginValueToString -Value $Threshold.Value -BaseValue $BaseValue -Unit $Threshold.Unit -OriginalUnit $Unit -UsePercent:$UsePercent -IsThreshold));
return $RetValue;
}
break;
};
$IcingaEnums.IcingaThresholdMethod.Greater {
if ($Value -gt $Threshold.Value) {
$RetValue.Message = [string]::Format('Value {0} is greater than threshold {1}', $HumanReadableValue, (Convert-IcingaPluginValueToString -Value $Threshold.Value -BaseValue $BaseValue -Unit $Threshold.Unit -OriginalUnit $Unit -UsePercent:$UsePercent -IsThreshold));
return $RetValue;
}
break;
};
$IcingaEnums.IcingaThresholdMethod.GreaterEqual {
if ($Value -gt $Threshold.Value) {
$RetValue.Message = [string]::Format('Value {0} is greater or equal than threshold {1}', $HumanReadableValue, (Convert-IcingaPluginValueToString -Value $Threshold.Value -BaseValue $BaseValue -Unit $Threshold.Unit -OriginalUnit $Unit -UsePercent:$UsePercent -IsThreshold));
return $RetValue;
}
break;
};
$IcingaEnums.IcingaThresholdMethod.Between {
if ($Value -lt $Threshold.StartRange -Or $Value -gt $Threshold.EndRange) {
$RetValue.Message = [string]::Format('Value {0} is not between thresholds <{1} or >{2}', $HumanReadableValue, (Convert-IcingaPluginValueToString -Value $Threshold.StartRange -BaseValue $BaseValue -Unit $Threshold.Unit -OriginalUnit $Unit -UsePercent:$UsePercent -IsThreshold), (Convert-IcingaPluginValueToString -Value $Threshold.EndRange -BaseValue $BaseValue -Unit $Threshold.Unit -OriginalUnit $Unit -UsePercent:$UsePercent -IsThreshold));
return $RetValue;
}
break;
};
$IcingaEnums.IcingaThresholdMethod.Outside {
if ($Value -ge $Threshold.StartRange -And $Value -le $Threshold.EndRange) {
$RetValue.Message = [string]::Format('Value {0} is between thresholds >={1} and <={2}', $HumanReadableValue, (Convert-IcingaPluginValueToString -Value $Threshold.StartRange -BaseValue $BaseValue -Unit $Threshold.Unit -OriginalUnit $Unit -UsePercent:$UsePercent -IsThreshold), (Convert-IcingaPluginValueToString -Value $Threshold.EndRange -BaseValue $BaseValue -Unit $Threshold.Unit -OriginalUnit $Unit -UsePercent:$UsePercent -IsThreshold));
return $RetValue;
}
break;
};
$IcingaEnums.IcingaThresholdMethod.Matches {
if ($Value -Like $Threshold.Value ) {
$RetValue.Message = [string]::Format('Value {0} is matching threshold {1}', $TranslatedValue, (ConvertTo-IcingaPluginOutputTranslation -Translation $Translation -Value $Threshold.Value));
return $RetValue;
}
break;
};
$IcingaEnums.IcingaThresholdMethod.NotMatches {
if ($Value -NotLike $Threshold.Value ) {
$RetValue.Message = [string]::Format('Value {0} is not matching threshold {1}', $TranslatedValue, (ConvertTo-IcingaPluginOutputTranslation -Translation $Translation -Value $Threshold.Value));
return $RetValue;
}
break;
};
}
$RetValue.Message = $HumanReadableValue;
$RetValue.IsOk = $TRUE;
return $RetValue;
}

View file

@ -0,0 +1,92 @@
<#
.SYNOPSIS
Converts Icinga plugin thresholds from percentage to actual values.
.DESCRIPTION
The Convert-IcingaPluginThresholdsFromPercent function takes a base value and a threshold object and converts the threshold values from percentage to actual values. It supports various threshold modes such as Default, Lower, LowerEqual, Greater, GreaterEqual, Between, Outside, Matches, and NotMatches.
.PARAMETER BaseValue
The base value used for calculating the threshold values.
.PARAMETER Threshold
The threshold object containing the threshold mode and value.
.OUTPUTS
The modified threshold object with the converted threshold values.
.EXAMPLE
$baseValue = 274112400000
$threshold = @{
EndRange = 90;
Unit = '%';
StartRange = 30;
Threshold = '@30:90';
Mode = 6;
Raw = '@30%:90%';
IsDateTime = $FALSE;
Value = $null;
}
Convert-IcingaPluginThresholdsFromPercent -BaseValue $baseValue -Threshold $threshold
This example converts the threshold value of 50% to the actual value based on the provided base value of 100.
.NOTES
#>
function Convert-IcingaPluginThresholdsFromPercent()
{
param (
$BaseValue = $null,
$Threshold = $null
);
if ($null -eq $Threshold -Or $null -eq $BaseValue -Or $BaseValue -eq 0) {
return $Threshold;
}
switch ($Threshold.Mode) {
$IcingaEnums.IcingaThresholdMethod.Default {
$Threshold.Threshold = [math]::Round($BaseValue / 100 * $Threshold.Value, 0);
break;
};
$IcingaEnums.IcingaThresholdMethod.Lower {
$Threshold.Threshold = [math]::Round($BaseValue / 100 * $Threshold.Value, 0);
break;
};
$IcingaEnums.IcingaThresholdMethod.LowerEqual {
$Threshold.Threshold = [math]::Round($BaseValue / 100 * $Threshold.Value, 0);
break;
};
$IcingaEnums.IcingaThresholdMethod.Greater {
$Threshold.Threshold = [math]::Round($BaseValue / 100 * $Threshold.Value, 0);
break;
};
$IcingaEnums.IcingaThresholdMethod.GreaterEqual {
$Threshold.Threshold = [math]::Round($BaseValue / 100 * $Threshold.Value, 0);
break;
};
$IcingaEnums.IcingaThresholdMethod.Between {
$StartRange = [math]::Round($BaseValue / 100 * $Threshold.StartRange, 0);
$EndRange = [math]::Round($BaseValue / 100 * $Threshold.EndRange, 0);
$Threshold.Threshold = [string]::Format('{0}:{1}', $StartRange, $EndRange);
break;
};
$IcingaEnums.IcingaThresholdMethod.Outside {
$StartRange = [math]::Round($BaseValue / 100 * $Threshold.StartRange, 0);
$EndRange = [math]::Round($BaseValue / 100 * $Threshold.EndRange, 0);
$Threshold.Threshold = [string]::Format('@{0}:{1}', $StartRange, $EndRange);
break;
};
$IcingaEnums.IcingaThresholdMethod.Matches {
break;
};
$IcingaEnums.IcingaThresholdMethod.NotMatches {
break;
};
}
return $Threshold;
}

View file

@ -119,19 +119,19 @@ function New-IcingaCheck()
$PluginThresholds = '';
$TimeSpan = '';
$PluginThresholds = $this.__ThresholdObject.FullMessage;
$PluginThresholds = $this.__ThresholdObject.Message;
if ([string]::IsNullOrEmpty($PluginOutput) -eq $FALSE) {
$PluginThresholds = $PluginOutput;
}
if ($null -ne $this.__ThresholdObject -And [string]::IsNullOrEmpty($this.__ThresholdObject.TimeSpan) -eq $FALSE) {
<#if ($null -ne $this.__ThresholdObject -And [string]::IsNullOrEmpty($this.__ThresholdObject.TimeSpan) -eq $FALSE) {
$TimeSpan = [string]::Format(
'{0}({1}m avg.)',
(&{ if ([string]::IsNullOrEmpty($PluginThresholds)) { return ''; } else { return ' ' } }),
$this.__ThresholdObject.TimeSpanOutput
);
}
}#>
[bool]$AddColon = $TRUE;
@ -173,10 +173,10 @@ function New-IcingaCheck()
$TimeSpan = $TimeSpanLabel.Replace($Label, '').Replace('_', '').Replace('::Interval', '').Replace('::', '');
if ($null -ne $this.__WarningValue -And [string]::IsNullOrEmpty($this.__WarningValue.TimeSpan) -eq $FALSE -And $this.__WarningValue.TimeSpan -eq $TimeSpan) {
$TimeSpans.Warning = $this.__WarningValue.IcingaThreshold;
$TimeSpans.Warning = $this.__WarningValue.Threshold.Threshold;
}
if ($null -ne $this.__CriticalValue -And [string]::IsNullOrEmpty($this.__CriticalValue.TimeSpan) -eq $FALSE -And $this.__CriticalValue.TimeSpan -eq $TimeSpan) {
$TimeSpans.Critical = $this.__CriticalValue.IcingaThreshold;
$TimeSpans.Critical = $this.__CriticalValue.Threshold.Threshold;
}
$TimeSpans.Interval = $TimeSpan;
@ -198,17 +198,17 @@ function New-IcingaCheck()
[string]$LabelName = (Format-IcingaPerfDataLabel -PerfData $this.Name);
[string]$MultiLabelName = (Format-IcingaPerfDataLabel -PerfData $this.Name -MultiOutput);
$value = ConvertTo-Integer -Value $this.__ThresholdObject.RawValue -NullAsEmpty;
$value = ConvertTo-Integer -Value $this.__ThresholdObject.Value -NullAsEmpty;
$warning = '';
$critical = '';
# Set our threshold to nothing if we use time spans, as it would cause performance metrics to
# contain warning/critical values for everything, which is not correct
if ([string]::IsNullOrEmpty($this.__WarningValue.TimeSpan)) {
$warning = ConvertTo-Integer -Value $this.__WarningValue.IcingaThreshold -NullAsEmpty;
$warning = ConvertTo-Integer -Value $this.__WarningValue.Threshold.Threshold -NullAsEmpty;
}
if ([string]::IsNullOrEmpty($this.__CriticalValue.TimeSpan)) {
$critical = ConvertTo-Integer -Value $this.__CriticalValue.IcingaThreshold -NullAsEmpty;
$critical = ConvertTo-Integer -Value $this.__CriticalValue.Threshold.Threshold -NullAsEmpty;
}
if ([string]::IsNullOrEmpty($this.LabelName) -eq $FALSE) {
@ -226,7 +226,7 @@ function New-IcingaCheck()
}
if ([string]::IsNullOrEmpty($this.Maximum) -eq $FALSE -And (Test-Numeric $this.Maximum) -And (Test-Numeric $this.Value) -And $this.Value -gt $this.Maximum) {
$this.Maximum = $this.__ThresholdObject.RawValue;
$this.Maximum = $this.__ThresholdObject.Value;
}
}
@ -236,21 +236,37 @@ function New-IcingaCheck()
$PerfDataTemplate = $this.MetricTemplate;
}
$this.__CheckPerfData = @{
'index' = $this.MetricIndex;
'name' = $this.MetricName;
'template' = $PerfDataTemplate;
'label' = $LabelName;
'multilabel' = $MultiLabelName;
'perfdata' = '';
'unit' = $this.__ThresholdObject.PerfUnit;
'value' = (Format-IcingaPerfDataValue $value);
'warning' = (Format-IcingaPerfDataValue $warning);
'critical' = (Format-IcingaPerfDataValue $critical);
'minimum' = (Format-IcingaPerfDataValue $this.Minimum);
'maximum' = (Format-IcingaPerfDataValue $this.Maximum);
'package' = $FALSE;
};
[string]$PerfDataName = [string]::Format(
'{0}::ifw_{1}::{2}',
$this.MetricIndex,
$PerfDataTemplate.ToLower(),
$this.MetricName
);
# Ensure we only add a label with identical name once
if ($Global:Icinga.Private.Scheduler.PerfDataWriter.Cache.ContainsKey($PerfDataName) -eq $FALSE) {
$Global:Icinga.Private.Scheduler.PerfDataWriter.Cache.Add($PerfDataName, $TRUE);
} else {
return;
}
[string]$PerfDataLabel = [string]::Format(
'{0}={1}{2};{3};{4};{5};{6}',
$PerfDataName,
(Format-IcingaPerfDataValue $value),
$this.__ThresholdObject.PerfUnit,
(Format-IcingaPerfDataValue $warning),
(Format-IcingaPerfDataValue $critical),
(Format-IcingaPerfDataValue $this.Minimum),
(Format-IcingaPerfDataValue $this.Maximum)
);
# Add a space before adding another metric
if ($Global:Icinga.Private.Scheduler.PerfDataWriter.Storage.Length -ne 0) {
$Global:Icinga.Private.Scheduler.PerfDataWriter.Storage.Append(' ') | Out-Null;
}
$Global:Icinga.Private.Scheduler.PerfDataWriter.Storage.Append($PerfDataLabel.ToLower()) | Out-Null;
}
$IcingaCheck | Add-Member -MemberType ScriptMethod -Name '__ValidateObject' -Value {
@ -417,7 +433,7 @@ function New-IcingaCheck()
if ($ThresholdObject.HasError) {
$this.SetUnknown() | Out-Null;
$this.__ThresholdObject = $ThresholdObject;
$this.__SetCheckOutput($this.__ThresholdObject.ErrorMessage);
$this.__SetCheckOutput($this.__ThresholdObject.Message);
$this.__LockState();
return;
}
@ -431,7 +447,7 @@ function New-IcingaCheck()
$this.__ThresholdObject = $ThresholdObject;
}
if ($ThresholdObject.InRange -eq $FALSE) {
if ($ThresholdObject.IsOk -eq $FALSE) {
if ($this.__CheckState -lt $State) {
$this.__CheckState = $State;
$this.__ThresholdObject = $ThresholdObject;
@ -951,35 +967,53 @@ function New-IcingaCheck()
[bool]$OutOfRange = $FALSE;
#Handles 20
if ($null -ne $this.__WarningValue.CompareValue -And $null -ne $this.__CriticalValue.CompareValue) {
if ($this.__WarningValue.CompareValue -gt $this.__CriticalValue.CompareValue) {
$OutOfRange = $TRUE;
}
}
# Both thresholds use the mode
if ($this.__WarningValue.Threshold.Mode -eq $this.__CriticalValue.Threshold.Mode) {
# Handles: @30:40 and 30:40
# Never throw an "error" here, as these ranges can be dynamic
if ($null -ne $this.__WarningValue.MinRangeValue -And $null -ne $this.__CriticalValue.MinRangeValue -And $null -ne $this.__WarningValue.MaxRangeValue -And $null -ne $this.__CriticalValue.MaxRangeValue) {
return;
}
# Handles: 20:
if ($null -ne $this.__WarningValue.MinRangeValue -And $null -ne $this.__CriticalValue.MinRangeValue -And $null -eq $this.__WarningValue.MaxRangeValue -And $null -eq $this.__CriticalValue.MaxRangeValue) {
if ($this.__WarningValue.MinRangeValue -lt $this.__CriticalValue.MinRangeValue) {
$OutOfRange = $TRUE;
#Handles 20
if ($this.__WarningValue.Threshold.Mode -eq $IcingaEnums.IcingaThresholdMethod.Default -And $null -ne $this.__WarningValue.Threshold.Value -And $null -ne $this.__CriticalValue.Threshold.Value) {
if ($this.__WarningValue.Threshold.Value -gt $this.__CriticalValue.Threshold.Value) {
$OutOfRange = $TRUE;
}
}
}
# Handles: ~:20
if ($null -eq $this.__WarningValue.MinRangeValue -And $null -eq $this.__CriticalValue.MinRangeValue -And $null -ne $this.__WarningValue.MaxRangeValue -And $null -ne $this.__CriticalValue.MaxRangeValue) {
if ($this.__WarningValue.MaxRangeValue -gt $this.__CriticalValue.MaxRangeValue) {
$OutOfRange = $TRUE;
# Handles: 30:40
if ($this.__WarningValue.Threshold.Mode -eq $IcingaEnums.IcingaThresholdMethod.Between) {
if ($this.__WarningValue.Threshold.StartRange -lt $this.__CriticalValue.Threshold.StartRange) {
$OutOfRange = $TRUE;
}
if ($this.__WarningValue.Threshold.EndRange -gt $this.__CriticalValue.Threshold.EndRange) {
$OutOfRange = $TRUE;
}
# Handles: @30:40
} elseif ($this.__WarningValue.Threshold.Mode -eq $IcingaEnums.IcingaThresholdMethod.Outside) {
if ($this.__WarningValue.Threshold.StartRange -ge $this.__CriticalValue.Threshold.StartRange) {
$OutOfRange = $TRUE;
}
if ($this.__WarningValue.Threshold.EndRange -le $this.__CriticalValue.Threshold.EndRange) {
$OutOfRange = $TRUE;
}
}
# Handles: 20:
if ($this.__WarningValue.Threshold.Mode -eq $IcingaEnums.IcingaThresholdMethod.Lower -And $null -ne $this.__WarningValue.Threshold.Value -And $null -ne $this.__CriticalValue.Threshold.Value) {
if ($this.__WarningValue.Threshold.Value -lt $this.__CriticalValue.Threshold.Value) {
$OutOfRange = $TRUE;
}
}
# Handles: ~:20
if ($this.__WarningValue.Threshold.Mode -eq $IcingaEnums.IcingaThresholdMethod.Greater -And $null -ne $this.__WarningValue.Threshold.Value -And $null -ne $this.__CriticalValue.Threshold.Value) {
if ($this.__WarningValue.Threshold.Value -gt $this.__CriticalValue.Threshold.Value) {
$OutOfRange = $TRUE;
}
}
} else {
# Todo: Implement handling for mixed modes
}
if ($OutOfRange) {
$this.SetUnknown([string]::Format('Warning threshold range "{0}" is greater than Critical threshold range "{1}"', $this.__WarningValue.RawThreshold, $this.__CriticalValue.RawThreshold), $TRUE) | Out-Null;
$this.SetUnknown([string]::Format('Warning threshold range "{0}" is greater than Critical threshold range "{1}"', $this.__WarningValue.Threshold.Threshold, $this.__CriticalValue.Threshold.Threshold), $TRUE) | Out-Null;
}
}

View file

@ -4,7 +4,6 @@ function New-IcingaCheckBaseObject()
$IcingaCheckBaseObject | Add-Member -MemberType NoteProperty -Name 'Name' -Value '';
$IcingaCheckBaseObject | Add-Member -MemberType NoteProperty -Name 'Verbose' -Value 0;
$IcingaCheckBaseObject | Add-Member -MemberType NoteProperty -Name '__CheckPerfData' -Value @{ };
$IcingaCheckBaseObject | Add-Member -MemberType NoteProperty -Name '__Hidden' -Value $FALSE;
$IcingaCheckBaseObject | Add-Member -MemberType NoteProperty -Name '__SkipSummary' -Value $FALSE;
$IcingaCheckBaseObject | Add-Member -MemberType NoteProperty -Name '__Parent' -Value $IcingaCheckBaseObject;
@ -183,10 +182,6 @@ function New-IcingaCheckBaseObject()
return $TRUE;
}
$IcingaCheckBaseObject | Add-Member -MemberType ScriptMethod -Name '__GetPerformanceData' -Value {
return $this.__CheckPerfData;
}
$IcingaCheckBaseObject | Add-Member -MemberType ScriptMethod -Name '__ValidateThresholdInput' -Value {
# Shared function
}

View file

@ -333,33 +333,6 @@ function New-IcingaCheckPackage()
return '';
}
# Override default behaviour from shared function
$IcingaCheckPackage | Add-Member -MemberType ScriptMethod -Force -Name '__GetPerformanceData' -Value {
[string]$perfData = '';
[hashtable]$CollectedPerfData = @{ };
# At first lets collect all perf data, but ensure we only add possible label duplication only once
foreach ($check in $this.__Checks) {
$data = $check.__GetPerformanceData();
if ($null -eq $data -Or $null -eq $data.label) {
continue;
}
if ($CollectedPerfData.ContainsKey($data.label)) {
continue;
}
$CollectedPerfData.Add($data.label, $data);
}
return @{
'label' = $this.Name;
'perfdata' = $CollectedPerfData;
'package' = $TRUE;
}
}
# __GetTimeSpanThreshold(0, 'Core_30_20', 'Core_30')
$IcingaCheckPackage | Add-Member -MemberType ScriptMethod -Force -Name '__GetTimeSpanThreshold' -Value {
param ($TimeSpanLabel, $Label, $MultiOutput);

View file

@ -1,84 +1,14 @@
function Write-IcingaPluginPerfData()
{
param (
$IcingaCheck = $null
);
if ($null -eq $IcingaCheck) {
return;
}
$PerformanceData = $IcingaCheck.__GetPerformanceData();
$CheckCommand = $IcingaCheck.__GetCheckCommand();
if ($PerformanceData.package -eq $FALSE) {
$PerformanceData = @{
$PerformanceData.label = $PerformanceData;
}
} else {
$PerformanceData = $PerformanceData.perfdata;
}
if ([string]::IsNullOrEmpty($CheckCommand) -eq $FALSE -And $Global:Icinga.Private.Scheduler.ThresholdCache.ContainsKey($CheckCommand)) {
$CheckResultCache = $Global:Icinga.Private.Scheduler.ThresholdCache[$CheckCommand];
} else {
$CheckResultCache = New-Object PSCustomObject;
}
Get-IcingaPluginPerfDataContent -PerfData $PerformanceData -CheckResultCache $CheckResultCache -IcingaCheck $IcingaCheck;
if ($Global:Icinga.Protected.RunAsDaemon -eq $FALSE -And $Global:Icinga.Protected.JEAContext -eq $FALSE) {
if ($Global:Icinga.Private.Scheduler.PerformanceData.Count -ne 0) {
Write-IcingaConsolePlain ([string]::Format('| {0}', ([string]::Join(' ', $Global:Icinga.Private.Scheduler.PerformanceData))));
if ($Global:Icinga.Private.Scheduler.PerfDataWriter.Storage.Length -ne 0) {
Write-IcingaConsolePlain ([string]::Format('| {0}', ($Global:Icinga.Private.Scheduler.PerfDataWriter.Storage.ToString())));
}
} else {
$Global:Icinga.Private.Scheduler.PerformanceData = $Global:Icinga.Private.Scheduler.PerfDataWriter.Storage.ToString();
}
# Ensure we clear our cache after writing the data
$Global:Icinga.Private.Scheduler.PerfDataWriter.Cache.Clear() | Out-Null;
$Global:Icinga.Private.Scheduler.PerfDataWriter.Storage.Clear() | Out-Null;
}
function Get-IcingaPluginPerfDataContent()
{
param (
$PerfData,
$CheckResultCache,
$IcingaCheck = $null
);
[hashtable]$CompiledPerfData = @{ };
foreach ($package in $PerfData.Keys) {
$data = $PerfData[$package];
if ($data.package) {
(Get-IcingaPluginPerfDataContent -PerfData $data.perfdata -CheckResultCache $CheckResultCache -IcingaCheck $IcingaCheck);
} else {
$CompiledPerfData = New-IcingaPerformanceDataEntry -PerfDataObject $data -PerfData $CompiledPerfData;
foreach ($checkresult in $CheckResultCache.PSobject.Properties) {
$SearchPattern = [string]::Format('{0}_', $data.label);
$SearchPatternMulti = [string]::Format('::{0}::Interval', $data.multilabel);
$SearchEntry = $checkresult.Name;
if ($SearchEntry -like "$SearchPatternMulti*") {
$TimeSpan = $IcingaCheck.__GetTimeSpanThreshold($SearchEntry, $data.multilabel, $TRUE);
$CompiledPerfData = New-IcingaPerformanceDataEntry -PerfDataObject $data -Label $SearchEntry -Value $checkresult.Value -Warning $TimeSpan.Warning -Critical $TimeSpan.Critical -Interval $TimeSpan.Interval -PerfData $CompiledPerfData;
}
}
}
}
foreach ($entry in $CompiledPerfData.Keys) {
$entryValue = $CompiledPerfData[$entry];
[string]$PerfDataLabel = $entryValue.Index;
if ($entryValue.Values.Count -ne 0) {
[string]$PerfDataLabel = [string]::Format('{0} {1}', $entryValue.Index, ([string]::Join(' ', ($entryValue.Values | Sort-Object))));
}
[array]$global:Icinga.Private.Scheduler.PerformanceData += $PerfDataLabel;
}
[array]$global:Icinga.Private.Scheduler.PerformanceData = $Global:Icinga.Private.Scheduler.PerformanceData | Sort-Object @{
expression = { $_.Substring(1, $_.IndexOf('::') - 1) -As [int] }
};
}
Export-ModuleMember -Function @( 'Write-IcingaPluginPerfData' );

View file

@ -1,14 +1,14 @@
function Write-IcingaPluginResult()
{
param (
[string]$PluginOutput = '',
[array]$PluginPerfData = @()
[string]$PluginOutput = '',
[string]$PluginPerfData = ''
);
[string]$CheckResult = $PluginOutput;
if ($PluginPerfData.Count -ne 0) {
$CheckResult = [string]::Format('{0}{1}| {2}', $CheckResult, "`r`n", ([string]::Join(' ', $PluginPerfData)));
if ([string]::IsNullOrEmpty($PluginPerfData) -eq $FALSE) {
$CheckResult = [string]::Format('{0}{1}| {2}', $CheckResult, "`r`n", $PluginPerfData);
}
Write-IcingaConsolePlain $CheckResult;