2019-07-22 07:17:07 -04:00
<#
# This is the main function which is called from this script, constructing our counters
# and loading possible sub-instances from our Performance Counter.
2019-07-22 08:04:32 -04:00
# It will return either an New-IcingaPerformanceCounterObject or New-IcingaPerformanceCounterResult
2019-07-22 07:17:07 -04:00
# which both contain the same members, allowing us to dynamicly use the objects
# without having to worry about exception.
#>
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 splitted 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 automaticly fetch all
2019-07-22 08:04:32 -04:00
# instances for this counter. This will result in an New-IcingaPerformanceCounterResult
2019-07-22 07:17:07 -04:00
# 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
# TODO: Re-Implement caching for counters
<# if ($Icinga2 . Cache . PerformanceCounter . ContainsKey($Counter) -eq $TRUE) {
2019-07-22 08:04:32 -04:00
return ( New-IcingaPerformanceCounterResult -FullName $Counter -PerformanceCounters $Icinga2 . Cache . PerformanceCounter [ $Counter ] ) ;
2019-07-22 07:17:07 -04:00
} #>
# 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 ] $AllCountersIntances = @ ( ) ;
$CounterInstances = New-Object System . Diagnostics . PerformanceCounterCategory ( $UseCounterCategory ) ;
foreach ( $instance in $CounterInstances . GetInstanceNames ( ) ) {
[ string ] $NewCounterName = $Counter . Replace ( '*' , $instance ) ;
2019-07-22 08:35:35 -04:00
$NewCounter = New-IcingaPerformanceCounterObject -FullName $NewCounterName -Category $UseCounterCategory -Counter $UseCounterName -Instance $instance -SkipWait $TRUE ;
2019-07-22 07:17:07 -04:00
$AllCountersIntances + = $NewCounter ;
}
} catch {
return ( New-IcingaPerformanceCounterNullObject -FullName $Counter -ErrorMessage ( [ string ] :: Format ( 'Failed to deserialize instances for counter "{0}". Exception: "{1}".' , $Counter , $_ . Exception . Message ) ) ) ;
}
2019-07-22 08:35:35 -04:00
# 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 avaiable
if ( $SkipWait -eq $FALSE ) {
Start-Sleep -Milliseconds 500 ;
}
2019-07-22 07:17:07 -04:00
# Add the parent counter including the array of Performance Counters to our
2019-07-22 08:04:32 -04:00
# caching mechanism and return the New-IcingaPerformanceCounterResult object for usage
2019-07-22 07:17:07 -04:00
# within the monitoring modules
# TODO: Re-Implement caching for counters
# $Icinga2.Cache.PerformanceCounter.Add($Counter, $AllCountersIntances);
2019-07-22 08:04:32 -04:00
return ( New-IcingaPerformanceCounterResult -FullName $Counter -PerformanceCounters $AllCountersIntances ) ;
2019-07-22 07:17:07 -04:00
} else {
# This part will handle the counters without any instances as well as
# specificly assigned instances, like (_Total) CPU usage.
# In case we already have the counter within our cache, return the
# cached informations
# TODO: Re-Implement caching for counters
<# if ($Icinga2 . Cache . PerformanceCounter . ContainsKey($Counter) -eq $TRUE) {
return $Icinga2 . Cache . PerformanceCounter [ $Counter ] ;
} #>
# 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 ;
# TODO: Re-Implement caching for counters
#$Icinga2.Cache.PerformanceCounter.Add($Counter, $NewCounter);
return $NewCounter ; #TODO: Remove once caching is implemented
}
# This function will always return non-instance counters or
# specificly 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
# TODO: Re-Implement caching for counters, right now we return $NewCounter by default
#return $Icinga2.Cache.PerformanceCounter[$Counter];
}