mirror of
https://github.com/Icinga/icinga-powershell-framework.git
synced 2025-12-21 07:10:15 -05:00
Disabling UseConsistentIndentation because it is not properly working for multi-line commands with arguments and array/hashtable objects
144 lines
7.6 KiB
PowerShell
144 lines
7.6 KiB
PowerShell
<#
|
|
.SYNOPSIS
|
|
Creates counter objects and sub-instances from a given Performance Counter
|
|
Will return either a New-IcingaPerformanceCounterObject or New-IcingaPerformanceCounterResult
|
|
which both contain the same members, allowing for dynamically use of objects
|
|
.DESCRIPTION
|
|
Creates counter objects and sub-instances from a given Performance Counter
|
|
Will return either a New-IcingaPerformanceCounterObject or New-IcingaPerformanceCounterResult
|
|
which both contain the same members, allowing for dynamically use of objects
|
|
.FUNCTIONALITY
|
|
Creates counter objects and sub-instances from a given Performance Counter
|
|
Will return either a New-IcingaPerformanceCounterObject or New-IcingaPerformanceCounterResult
|
|
which both contain the same members, allowing for dynamically use of objects
|
|
.EXAMPLE
|
|
PS>New-IcingaPerformanceCounter -Counter '\Processor(*)\% processor time';
|
|
|
|
FullName Counters
|
|
-------- --------
|
|
\Processor(*)\% processor time {@{FullName=\Processor(2)\% processor time; Category=Processor; Instance=2; Counter=%...
|
|
.EXAMPLE
|
|
PS>New-IcingaPerformanceCounter -Counter '\Processor(*)\% processor time' -SkipWait;
|
|
.PARAMETER Counter
|
|
The path to the Performance Counter to fetch data for
|
|
.PARAMETER SkipWait
|
|
Set this if no sleep is intended for initialising the counter. This can be useful
|
|
if multiple counters are fetched during one call with this function if the sleep
|
|
is done afterwards manually. A sleep is set to 500ms to ensure counter data is
|
|
valid and contains an offset from previous/current values
|
|
.INPUTS
|
|
System.String
|
|
.LINK
|
|
https://github.com/Icinga/icinga-powershell-framework
|
|
#>
|
|
|
|
function New-IcingaPerformanceCounter()
|
|
{
|
|
param(
|
|
[string]$Counter = '',
|
|
[boolean]$SkipWait = $FALSE
|
|
);
|
|
|
|
# Simply use the counter name, like
|
|
# \Paging File(_total)\% Usage
|
|
if ([string]::IsNullOrEmpty($Counter) -eq $TRUE) {
|
|
return (New-IcingaPerformanceCounterNullObject -FullName $Counter -ErrorMessage 'Failed to initialise counter, as no counter was specified.');
|
|
}
|
|
|
|
[array]$CounterArray = $Counter.Split('\');
|
|
[string]$UseCounterCategory = '';
|
|
[string]$UseCounterName = '';
|
|
[string]$UseCounterInstance = '';
|
|
|
|
# If we add the counter as it should be
|
|
# \Paging File(_total)\% Usage
|
|
# the first array element will be an empty string we can skip
|
|
# Otherwise the name was wrong and we should not continue
|
|
if (-Not [string]::IsNullOrEmpty($CounterArray[0])) {
|
|
return (New-IcingaPerformanceCounterNullObject -FullName $Counter -ErrorMessage ([string]::Format('Failed to deserialize counter "{0}". It seems the leading "\" is missing.', $Counter)));
|
|
}
|
|
|
|
# In case our Performance Counter is containing instances, we should split
|
|
# The content and read the instance and counter category out
|
|
if ($CounterArray[1].Contains('(')) {
|
|
[array]$TmpCounter = $CounterArray[1].Split('(');
|
|
$UseCounterCategory = $TmpCounter[0];
|
|
$UseCounterInstance = $TmpCounter[1].Replace(')', '');
|
|
} else {
|
|
# Otherwise we only require the category
|
|
$UseCounterCategory = $CounterArray[1];
|
|
}
|
|
|
|
# At last get the actual counter containing our values
|
|
$UseCounterName = $CounterArray[2];
|
|
|
|
# Now as we know how the counter path is constructed and has been split into
|
|
# the different values, we need to know how to handle the instances of the counter
|
|
|
|
# If we specify a instance with (*) we want the module to automatically fetch all
|
|
# instances for this counter. This will result in an New-IcingaPerformanceCounterResult
|
|
# which contains the parent name including counters for all instances that
|
|
# have been found
|
|
if ($UseCounterInstance -eq '*') {
|
|
# In case we already loaded the counters once, return the finished array
|
|
$CachedCounter = Get-IcingaPerformanceCounterCacheItem -Counter $Counter;
|
|
|
|
if ($null -ne $CachedCounter) {
|
|
return (New-IcingaPerformanceCounterResult -FullName $Counter -PerformanceCounters $CachedCounter);
|
|
}
|
|
|
|
# If we need to build the array, load all instances from the counters and
|
|
# create single performance counters and add them to a custom array and
|
|
# later to a custom object
|
|
try {
|
|
[array]$AllCountersInstances = @();
|
|
$CounterInstances = New-Object System.Diagnostics.PerformanceCounterCategory($UseCounterCategory);
|
|
foreach ($instance in $CounterInstances.GetInstanceNames()) {
|
|
[string]$NewCounterName = $Counter.Replace('*', $instance);
|
|
$NewCounter = New-IcingaPerformanceCounterObject -FullName $NewCounterName -Category $UseCounterCategory -Counter $UseCounterName -Instance $instance -SkipWait $TRUE;
|
|
$AllCountersInstances += $NewCounter;
|
|
}
|
|
} catch {
|
|
# Throw an exception in case our permissions are not enough to fetch performance counter
|
|
Exit-IcingaThrowException -InputString $_.Exception -StringPattern 'System.UnauthorizedAccessException' -ExceptionType 'Permission' -ExceptionThrown $IcingaExceptions.Permission.PerformanceCounter;
|
|
Exit-IcingaThrowException -InputString $_.Exception -StringPattern 'System.InvalidOperationException' -ExceptionType 'Input' -CustomMessage $Counter -ExceptionThrown $IcingaExceptions.Inputs.PerformanceCounter;
|
|
Exit-IcingaThrowException -InputString $_.Exception -StringPattern '' -ExceptionType 'Unhandled';
|
|
# Shouldn't actually get down here anyways
|
|
return (New-IcingaPerformanceCounterNullObject -FullName $Counter -ErrorMessage ([string]::Format('Failed to deserialize instances for counter "{0}". Exception: "{1}".', $Counter, $_.Exception.Message)));
|
|
}
|
|
|
|
# If we load multiple instances, we should add a global wait here instead of a wait for each single instance
|
|
# This will speed up CPU loading for example with plenty of cores available
|
|
if ($SkipWait -eq $FALSE) {
|
|
Start-Sleep -Milliseconds 500;
|
|
}
|
|
|
|
# Add the parent counter including the array of Performance Counters to our
|
|
# caching mechanism and return the New-IcingaPerformanceCounterResult object for usage
|
|
# within the monitoring modules
|
|
Add-IcingaPerformanceCounterCache -Counter $Counter -Instances $AllCountersInstances;
|
|
return (New-IcingaPerformanceCounterResult -FullName $Counter -PerformanceCounters $AllCountersInstances);
|
|
} else {
|
|
# This part will handle the counters without any instances as well as
|
|
# specifically assigned instances, like (_Total) CPU usage.
|
|
|
|
# In case we already have the counter within our cache, return the
|
|
# cached informations
|
|
$CachedCounter = Get-IcingaPerformanceCounterCacheItem -Counter $Counter;
|
|
|
|
if ($null -ne $CachedCounter) {
|
|
return $CachedCounter;
|
|
}
|
|
|
|
# If the cache is not present yet, create the Performance Counter object,
|
|
# and add it to our cache
|
|
$NewCounter = New-IcingaPerformanceCounterObject -FullName $Counter -Category $UseCounterCategory -Counter $UseCounterName -Instance $UseCounterInstance -SkipWait $SkipWait;
|
|
Add-IcingaPerformanceCounterCache -Counter $Counter -Instances $NewCounter;
|
|
}
|
|
|
|
# This function will always return non-instance counters or
|
|
# specifically defined instance counters. Performance Counter Arrays
|
|
# are returned within their function. This is just to ensure that the
|
|
# function looks finished from developer point of view
|
|
return (Get-IcingaPerformanceCounterCacheItem -Counter $Counter);
|
|
}
|