Skip to content

Commit

Permalink
Improves memory plugin; adds pagefile checks
Browse files Browse the repository at this point in the history
  • Loading branch information
LordHepipud committed May 28, 2021
1 parent c96e41b commit bd42057
Show file tree
Hide file tree
Showing 3 changed files with 197 additions and 103 deletions.
1 change: 1 addition & 0 deletions doc/31-Changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ Released closed milestones can be found on [GitHub](https://github.com/Icinga/ic

### Enhancements

* [#14](https://github.com/Icinga/icinga-powershell-plugins/issues/14) Rework of `Invoke-IcingaCheckMemory` to use new features from 1.5.0 for % handling and added page file check content including arguments. Please have a look on the [upgrading docs](30-Upgrading-Plugins.md)
* [#71](https://github.com/Icinga/icinga-powershell-plugins/pull/71) Rework `Invoke-IcingaCheckUsedPartitionSpace` to properly use Framework v1.5.0 functionality and resolve upper/lower case drive filtering
* [#156](https://github.com/Icinga/icinga-powershell-plugins/issues/156) Adds feature to modify the output status of `Invoke-IcingaCheckCertificate` from `UNKNOWN` to `OK` in case no certificate was found by setting the new argument `-IgnoreEmpty`
* [#159](https://github.com/Icinga/icinga-powershell-plugins/issues/159) Replaces the deprecated function `Get-EventLog` with `Get-WinEvent`. In addition, the plugin received a new argument `-MaxEntries` to allow additional filtering for the number of events fetched to improve performance in addition. The EventLog now also supports an array with list items, allowing easier filtering for severities which are allowed inside the EventLog.
Expand Down
191 changes: 98 additions & 93 deletions plugins/Invoke-IcingaCheckMemory.psm1
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
<#
.SYNOPSIS
Checks on memory usage
Checks on memory usage
.DESCRIPTION
Invoke-IcingaCheckMemory returns either 'OK', 'WARNING' or 'CRITICAL', based on the thresholds set.
e.g memory is currently at 60% usage, WARNING is set to 50, CRITICAL is set to 90. In this case the check will return WARNING.
Invoke-IcingaCheckMemory returns either 'OK', 'WARNING' or 'CRITICAL', based on the thresholds set.
e.g memory is currently at 60% usage, WARNING is set to 50, CRITICAL is set to 90. In this case the check will return WARNING.
More Information on https://github.com/Icinga/icinga-powershell-plugins
More Information on https://github.com/Icinga/icinga-powershell-plugins
.FUNCTIONALITY
This module is intended to be used to check on memory usage.
Based on the thresholds set the status will change between 'OK', 'WARNING' or 'CRITICAL'. The function will return one of these given codes.
This module is intended to be used to check on memory usage.
Based on the thresholds set the status will change between 'OK', 'WARNING' or 'CRITICAL'. The function will return one of these given codes.
.ROLE
### Performance Counter
Expand All @@ -20,119 +20,124 @@
* Performance Monitor Users
.EXAMPLE
PS>Invoke-IcingaCheckMemory -Verbosity 3 -Warning 60 -Critical 80
[WARNING]: % Memory Check 78.74 is greater than 60
PS>Invoke-IcingaCheckMemory -Verbosity 3 -Warning 60 -Critical 80
[WARNING]: % Memory Check 78.74 is greater than 60
.EXAMPLE
PS> Invoke-IcingaCheckMemory -WarningPercent 30 -CriticalPercent 50
[WARNING] Check package "Memory Usage" - [WARNING] Memory Percent Used
\_ [WARNING] Memory Percent Used: Value "48.07%" is greater than threshold "30%"
| 'memory_percent_used'=48.07%;0:30;0:50;0;100 'used_bytes'=3.85GB;;;0;8
1
PS> Invoke-IcingaCheckMemory -WarningPercent 30 -CriticalPercent 50
[WARNING] Check package "Memory Usage" - [WARNING] Memory Percent Used
\_ [WARNING] Memory Percent Used: Value "48.07%" is greater than threshold "30%"
| 'memory_percent_used'=48.07%;0:30;0:50;0;100 'used_bytes'=3.85GB;;;0;8
1
.PARAMETER Warning
Used to specify a Warning threshold. In this case an string value.
The string has to be like, "20B", "20KB", "20MB", "20GB", "20TB", "20PB"
This is using the default Icinga threshold handling.
Used to specify a Warning threshold. In this case an string value.
The string has to be like, "20B", "20KB", "20MB", "20GB", "20TB", "20PB"
This is using the default Icinga threshold handling.
It is possible to enter e.g. 10% as threshold value if you want a percentage comparison.
.PARAMETER Critical
Used to specify a Critical threshold. In this case an string value.
The string has to be like, "20B", "20KB", "20MB", "20GB", "20TB", "20PB"
This is using the default Icinga threshold handling.
.PARAMETER Pagefile
Switch which determines whether the pagefile should be used instead.
If not set memory will be checked.
.PARAMETER WarningPercent
Used to specify a Warning threshold for the memory usage in percent, like 30 for 30%.
This is using the default Icinga threshold handling.
.PARAMETER CriticalPercent
Used to specify a Critical threshold for the memory usage in percent, like 30 for 30%.
This is using the default Icinga threshold handling.
Used to specify a Critical threshold. In this case an string value.
The string has to be like, "20B", "20KB", "20MB", "20GB", "20TB", "20PB"
This is using the default Icinga threshold handling.
It is possible to enter e.g. 10% as threshold value if you want a percentage comparison.
.PARAMETER PageFileWarning
Allows to check the used page file and compare it against a size value, like "200MB"
This is using the default Icinga threshold handling.
It is possible to enter e.g. 10% as threshold value if you want a percentage comparison.
.PARAMETER PageFileCritical
Allows to check the used page file and compare it against a size value, like "200MB"
This is using the default Icinga threshold handling.
It is possible to enter e.g. 10% as threshold value if you want a percentage comparison.
.PARAMETER IncludePageFile
Allows to filter for page files being included for the check
.PARAMETER ExcludePageFile
Allows to filter for page files being excluded for the check
.INPUTS
System.String
System.String
.OUTPUTS
System.String
System.String
.LINK
https://github.com/Icinga/icinga-powershell-plugins
https://github.com/Icinga/icinga-powershell-plugins
.NOTES
#>

function Invoke-IcingaCheckMemory()
{
param(
[string]$Critical = $null,
[string]$Warning = $null,
$CriticalPercent = $null,
$WarningPercent = $null,
$Warning = $null,
$Critical = $null,
$PageFileWarning = $null,
$PageFileCritical = $null,
[array]$IncludePageFile = @(),
[array]$ExcludePageFile = @(),
[ValidateSet(0, 1, 2, 3)]
[int]$Verbosity = 0,
[int]$Verbosity = 0,
[switch]$NoPerfData
);

$MemoryPackage = New-IcingaCheckPackage -Name 'Memory Usage' -OperatorAnd -Verbose $Verbosity;
$MemoryData = (Get-IcingaMemoryPerformanceCounter);
$MemoryPackage = New-IcingaCheckPackage -Name 'Memory Usage' -OperatorAnd -Verbose $Verbosity;
$PageFilePackage = New-IcingaCheckPackage -Name 'PageFile Usage' -OperatorAnd -Verbose $Verbosity -IgnoreEmptyPackage;
$MemoryData = Get-IcingaMemoryPerformanceCounter;

# Auto-Detect?
If (($MemoryData['Memory Total Bytes'] / [math]::Pow(2, 50)) -ge 1) {
[string]$CalcUnit = 'PiB';
[string]$Unit = "PB";
} elseif (($MemoryData['Memory Total Bytes'] / [math]::Pow(2, 40)) -ge 1) {
[string]$CalcUnit = 'TiB';
[string]$Unit = "TB";
} elseif (($MemoryData['Memory Total Bytes'] / [math]::Pow(2, 30)) -ge 1) {
[string]$CalcUnit = 'GiB';
[string]$Unit = "GB";
} elseif (($MemoryData['Memory Total Bytes'] / [math]::Pow(2, 20)) -ge 1) {
[string]$CalcUnit = 'MiB';
[string]$Unit = "MB";
} elseif (($MemoryData['Memory Total Bytes'] / [math]::Pow(2, 10)) -ge 1) {
[string]$CalcUnit = 'KiB';
[string]$Unit = "KB";
} else {
[string]$CalcUnit = 'B';
[string]$Unit = "B";
}
$MemoryPackage.AddCheck(
(
New-IcingaCheck `
-Name 'Used Memory' `
-Value $MemoryData['Memory Used Bytes'] `
-BaseValue $MemoryData['Memory Total Bytes'] `
-Minimum 0 `
-Maximum $MemoryData['Memory Total Bytes'] `
-Unit 'B'
).WarnOutOfRange(
$Warning
).CritOutOfRange(
$Critical
)
);

If ([string]::IsNullOrEmpty($Critical) -eq $FALSE) {
$CriticalConvertedAll = Convert-Bytes $Critical -Unit $Unit;
[decimal]$CriticalConverted = $CriticalConvertedAll.value;
if ($null -eq $CriticalPercent) {
$CriticalPercent = $Critical / $MemoryData['Memory Total Bytes'] * 100
}
}
foreach ($PageFile in $MemoryData.PageFile.Keys) {
$PageFile = $MemoryData.PageFile[$PageFile];
$AddPageFile = $FALSE;

If ([string]::IsNullOrEmpty($Warning) -eq $FALSE) {
$WarningConvertedAll = Convert-Bytes $Warning -Unit $Unit;
[decimal]$WarningConverted = $WarningConvertedAll.value;
if ($null -eq $WarningPercent) {
$WarningPercent = $Warning / $MemoryData['Memory Total Bytes'] * 100
if ($IncludePageFile.Count -ne 0) {
foreach ($entry in $IncludePageFile) {
if ($PageFile.Name -Like $entry) {
$AddPageFile = $TRUE;
break;
}
}
} else {
$AddPageFile = $TRUE;
}
}

If ($null -ne $CriticalPercent) {
if ([string]::IsNullOrEmpty($Critical)) {
[string]$Value = ([string]::Format('{0}B', ($MemoryData['Memory Total Bytes'] / 100 * $CriticalPercent)));
$Value = $Value.Replace(',', '.');
$CriticalConverted = (Convert-Bytes $Value -Unit $CalcUnit).Value;
foreach ($entry in $ExcludePageFile) {
if ($PageFile.Name -Like $entry) {
$AddPageFile = $FALSE;
break;
}
}
}

If ($null -ne $WarningPercent) {
if ([string]::IsNullOrEmpty($Warning)) {
[string]$Value = ([string]::Format('{0}B', ($MemoryData['Memory Total Bytes'] / 100 * $WarningPercent)));
$Value = $Value.Replace(',', '.');
$WarningConverted = (Convert-Bytes $Value -Unit $CalcUnit).Value;
if ($AddPageFile -eq $FALSE) {
continue;
}
}

$UsedMemory = Convert-Bytes ([string]::Format('{0}B', $MemoryData['Memory Used Bytes'])) -Unit $CalcUnit;
$TotalMemory = Convert-Bytes ([string]::Format('{0}B', $MemoryData['Memory Total Bytes'])) -Unit $CalcUnit;
$MemoryPerc = New-IcingaCheck -Name 'Memory Percent Used' -Value $MemoryData['Memory Used %'] -Unit '%';
$MemoryByteUsed = New-IcingaCheck -Name "Used Bytes" -Value $UsedMemory.value -Unit $Unit -Minimum 0 -Maximum $TotalMemory.value;

# PageFile To-Do
$MemoryByteUsed.WarnOutOfRange($WarningConverted).CritOutOfRange($CriticalConverted) | Out-Null;
$MemoryPerc.WarnOutOfRange($WarningPercent).CritOutOfRange($CriticalPercent) | Out-Null;
$PageFilePackage.AddCheck(
(
New-IcingaCheck `
-Name $PageFile.Name `
-Value $PageFile.Usage `
-BaseValue $PageFile.TotalSize `
-Minimum 0 `
-Maximum $PageFile.TotalSize `
-Unit 'MB' `
-LabelName ([string]::Format('pagefile_{0}', (Format-IcingaPerfDataLabel $PageFile.Name)))
).WarnOutOfRange(
$PageFileWarning
).CritOutOfRange(
$PageFileCritical
)
);
}

$MemoryPackage.AddCheck($MemoryPerc);
$MemoryPackage.AddCheck($MemoryByteUsed);
$MemoryPackage.AddCheck($PageFilePackage);

return (New-IcingaCheckResult -Check $MemoryPackage -NoPerfData $NoPerfData -Compile);
}
108 changes: 98 additions & 10 deletions provider/memory/Get-IcingaMemoryPerformanceCounter.psm1
Original file line number Diff line number Diff line change
Expand Up @@ -5,19 +5,107 @@ function Get-IcingaMemoryPerformanceCounter()
Exit-IcingaThrowException -ExceptionType 'Configuration' -ExceptionThrown $IcingaExceptions.Configuration.PerfCounterCategoryMissing -CustomMessage 'Category "Memory" not found' -Force;
}

$MemoryPercent = New-IcingaPerformanceCounterArray -Counter "\Memory\% committed bytes in use","\Memory\Available Bytes","\Paging File(_Total)\% usage"
[hashtable]$Initial = @{};
[hashtable]$MemoryData = @{};
$PerfCounters = New-IcingaPerformanceCounterArray -Counter "\Memory\% committed bytes in use", "\Memory\Available Bytes", "\Paging File(*)\% usage";
[hashtable]$Initial = @{ };
[hashtable]$MemoryData = @{
'PageFile' = @{ }
};

foreach ($item in $MemoryPercent.Keys) {
$Initial.Add($item, $MemoryPercent[$item]);
foreach ($item in $PerfCounters.Keys) {
$Initial.Add($item, $PerfCounters[$item]);
}

$MemoryData.Add('Memory Available Bytes', [decimal]($Initial.'\Memory\Available Bytes'.value));
$MemoryData.Add('Memory Total Bytes', (Get-IcingaWindowsInformation Win32_ComputerSystem).TotalPhysicalMemory);
$MemoryData.Add('Memory Used Bytes', $MemoryData.'Memory Total Bytes' - $MemoryData.'Memory Available Bytes');
$MemoryData.Add('Memory Used %', 100 - ($MemoryData.'Memory Available Bytes' / $MemoryData.'Memory Total Bytes' * 100));
$MemoryData.Add('PageFile %', $Initial.'\Paging File(_Total)\% usage'.value);
$MemoryData.Add(
'Memory Available Bytes',
[decimal]($Initial['\Memory\Available Bytes'].value)
);
$MemoryData.Add(
'Memory Total Bytes',
(Get-IcingaWindowsInformation Win32_ComputerSystem).TotalPhysicalMemory
);
$MemoryData.Add(
'Memory Used Bytes',
($MemoryData['Memory Total Bytes'] - $MemoryData['Memory Available Bytes'])
);
$MemoryData.Add(
'Memory Used %',
(100 - [Math]::Round(($MemoryData['Memory Available Bytes'] / $MemoryData['Memory Total Bytes']) * 100, 2))
);
$MemoryData.Add(
'Committed Bytes %',
$Initial.'\Memory\% committed bytes in use'.value
);

if ((Get-IcingaWindowsInformation Win32_ComputerSystem).AutomaticManagedPagefile -eq $FALSE) {
# Page File is managed by User
$PageFileSettings = Get-IcingaWindowsInformation Win32_PageFileSetting;

foreach ($entry in $PageFileSettings) {
if ($MemoryData.PageFile.ContainsKey($entry.Name)) {
continue;
}

$MemoryData.PageFile.Add(
$entry.Name,
@{
'InitialSize' = $entry.InitialSize;
'Managed' = $TRUE;
'Name' = $entry.Name;
'TotalSize' = $entry.MaximumSize;
}
)
}
}

# Page File is managed by Windows
$PageFileUsage = Get-IcingaWindowsInformation Win32_PageFileUsage;

foreach ($entry in $PageFileUsage) {
if ($MemoryData.PageFile.ContainsKey($entry.Name)) {
$MemoryData.PageFile[$entry.Name].Add(
'Allocated', $entry.AllocatedBaseSize
);
$MemoryData.PageFile[$entry.Name].Add(
'Usage', $entry.CurrentUsage
);
$MemoryData.PageFile[$entry.Name].Add(
'PeakUsage', $entry.PeakUsage
);
$MemoryData.PageFile[$entry.Name].Add(
'TempPageFile', $entry.TempPageFile
);
continue;
}

$MemoryData.PageFile.Add(
$entry.Name,
@{
'InitialSize' = 0;
'MaximumSize' = 0;
'TotalSize' = $entry.AllocatedBaseSize;
'Allocated' = $entry.AllocatedBaseSize;
'Usage' = $entry.CurrentUsage;
'PeakUsage' = $entry.PeakUsage;
'TempPageFile' = $entry.TempPageFile;
'Managed' = $FALSE;
'Name' = $entry.Name;
}
)
}

foreach ($entry in $PerfCounters['\Paging File(*)\% usage'].Keys) {

$AvailablePageFiles = $MemoryData.PageFile.Keys;

foreach ($PageFile in $AvailablePageFiles) {
if ($entry -Like ([string]::Format('*{0}*', $PageFile))) {
$MemoryData.PageFile[$PageFile].Add(
'PercentUsed', $PerfCounters['\Paging File(*)\% usage'][$entry].value
);
break;
}
}
}

return $MemoryData;
}

0 comments on commit bd42057

Please sign in to comment.