From 2c96a60e6d06397beaf30ec73862f4d95399351f Mon Sep 17 00:00:00 2001 From: Lord Hepipud Date: Fri, 13 Sep 2019 20:44:15 +0200 Subject: [PATCH] Fixed and improved Perf Data handling * Added proper sorting for checks, packages and check results by name * Fixed perf data formating to be supported by Icinga 2 * Fixed label naming by removing all invalid characters * Fixed displaying of values by rounding to 2 digits on floats --- .../tools/Format-IcingaPerfDataLabel.psm1 | 9 ++++ .../tools/Format-IcingaPerfDataValue.psm1 | 14 ++++++ lib/icinga/plugin/New-IcingaCheck.psm1 | 30 ++++++----- lib/icinga/plugin/New-IcingaCheckPackage.psm1 | 50 ++++++++++++++++--- lib/icinga/plugin/New-IcingaCheckResult.psm1 | 2 +- 5 files changed, 86 insertions(+), 19 deletions(-) create mode 100644 lib/core/tools/Format-IcingaPerfDataLabel.psm1 create mode 100644 lib/core/tools/Format-IcingaPerfDataValue.psm1 diff --git a/lib/core/tools/Format-IcingaPerfDataLabel.psm1 b/lib/core/tools/Format-IcingaPerfDataLabel.psm1 new file mode 100644 index 0000000..d28aaf1 --- /dev/null +++ b/lib/core/tools/Format-IcingaPerfDataLabel.psm1 @@ -0,0 +1,9 @@ +function Format-IcingaPerfDataLabel() +{ + param( + $PerfData + ); + + # Remove all special characters and spaces on label names + return ((($PerfData) -Replace ' ', '_') -Replace '[\W]', ''); +} diff --git a/lib/core/tools/Format-IcingaPerfDataValue.psm1 b/lib/core/tools/Format-IcingaPerfDataValue.psm1 new file mode 100644 index 0000000..b91966a --- /dev/null +++ b/lib/core/tools/Format-IcingaPerfDataValue.psm1 @@ -0,0 +1,14 @@ +function Format-IcingaPerfDataValue() +{ + param( + $PerfValue + ); + + if ((Test-Numeric $PerfValue) -eq $FALSE) { + return $PerfValue; + } + + # Convert our value to a string and replace ',' with a '.' to allow Icinga to parse the output + # In addition, round every output to 2 digits + return (([string]([math]::round($PerfValue, 2))).Replace(',', '.')); +} diff --git a/lib/icinga/plugin/New-IcingaCheck.psm1 b/lib/icinga/plugin/New-IcingaCheck.psm1 index 09a1155..590ca32 100644 --- a/lib/icinga/plugin/New-IcingaCheck.psm1 +++ b/lib/icinga/plugin/New-IcingaCheck.psm1 @@ -408,6 +408,8 @@ function New-IcingaCheck() $Check | Add-Member -membertype ScriptMethod -name 'TranslateValue' -value { param($value); + $value = Format-IcingaPerfDataValue $value; + if ($null -eq $this.translation -Or $null -eq $value) { return $value; } @@ -633,7 +635,7 @@ function New-IcingaCheck() $Check | Add-Member -membertype ScriptMethod -name 'GetPerfData' -value { if ($this.completed -Or -Not $this.perfdata) { - return ''; + return $null; } $this.AutodiscoverMinMax(); @@ -645,18 +647,22 @@ function New-IcingaCheck() $this.maximum = [string]::Format(';{0}', $this.maximum); } - $this.completed = $TRUE; + $this.completed = $TRUE; + [string]$LabelName = (Format-IcingaPerfDataLabel $this.name); - return [string]::Format( - "'{0}'={1}{2};{3};{4}{5}{6} ", - $this.name, - $this.value, - $this.unit, - $this.warning, - $this.critical, - $this.minimum, - $this.maximum - ); + return @{ + 'label' = $LabelName; + 'perfdata' = [string]::Format( + "'{0}'={1}{2};{3};{4}{5}{6} ", + $LabelName, + (Format-IcingaPerfDataValue $this.value), + $this.unit, + (Format-IcingaPerfDataValue $this.warning), + (Format-IcingaPerfDataValue $this.critical), + (Format-IcingaPerfDataValue $this.minimum), + (Format-IcingaPerfDataValue $this.maximum) + ); + }; } $Check | Add-Member -membertype ScriptMethod -name 'AutodiscoverMinMax' -value { diff --git a/lib/icinga/plugin/New-IcingaCheckPackage.psm1 b/lib/icinga/plugin/New-IcingaCheckPackage.psm1 index 9c8ab0d..01204e9 100644 --- a/lib/icinga/plugin/New-IcingaCheckPackage.psm1 +++ b/lib/icinga/plugin/New-IcingaCheckPackage.psm1 @@ -207,8 +207,15 @@ function New-IcingaCheckPackage() } $Check | Add-Member -membertype ScriptMethod -name 'WriteAllOutput' -value { + [hashtable]$MessageOrdering = @{}; foreach ($check in $this.checks) { - $check.PrintAllMessages(); + $MessageOrdering.Add($check.name, $check); + } + + $SortedArray = $MessageOrdering.GetEnumerator() | Sort-Object name; + + foreach ($entry in $SortedArray) { + $entry.Value.PrintAllMessages(); } } @@ -218,11 +225,18 @@ function New-IcingaCheckPackage() } $Check | Add-Member -membertype ScriptMethod -name 'WriteCheckErrors' -value { + [hashtable]$MessageOrdering = @{}; foreach ($check in $this.checks) { if ([int]$check.exitcode -ne $IcingaEnums.IcingaExitCode.Ok) { - $check.PrintOutputMessages(); + $MessageOrdering.Add($check.name, $check); } } + + $SortedArray = $MessageOrdering.GetEnumerator() | Sort-Object name; + + foreach ($entry in $SortedArray) { + $entry.Value.PrintAllMessages(); + } } $Check | Add-Member -membertype ScriptMethod -name 'PrintNoChecksConfigured' -value { @@ -299,12 +313,36 @@ function New-IcingaCheckPackage() } $Check | Add-Member -membertype ScriptMethod -name 'GetPerfData' -value { - [string]$perfData = ''; + [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) { - $perfData += $check.GetPerfData(); + $data = $check.GetPerfData(); + + if ($null -eq $data -Or $null -eq $data.label) { + continue; + } + + if ($CollectedPerfData.ContainsKey($data.label)) { + continue; + } + + $CollectedPerfData.Add($data.label, $data.perfdata); + } + + # Now sort the label output by name + $SortedArray = $CollectedPerfData.GetEnumerator() | Sort-Object name; + + # Buold the performance data output based on the sorted result + foreach ($entry in $SortedArray) { + $perfData += $entry.Value; + } + + return @{ + 'label' = $this.name; + 'perfdata' = $perfData; } - - return $perfData; } $Check.Initialise(); diff --git a/lib/icinga/plugin/New-IcingaCheckResult.psm1 b/lib/icinga/plugin/New-IcingaCheckResult.psm1 index b7b07c6..5e07112 100644 --- a/lib/icinga/plugin/New-IcingaCheckResult.psm1 +++ b/lib/icinga/plugin/New-IcingaCheckResult.psm1 @@ -21,7 +21,7 @@ function New-IcingaCheckresult() $this.check.Compile($TRUE) | Out-Null; if ([int]$this.check.exitcode -ne [int]$IcingaEnums.IcingaExitCode.Unknown -And -Not $this.noperfdata) { - Write-Host ([string]::Format('| {0}', $this.check.GetPerfData())); + Write-Host ([string]::Format('| {0}', $this.check.GetPerfData().perfdata)); } return $this.check.exitcode;