Skip to content

Sensor Factories

lordmilko edited this page Aug 11, 2021 · 60 revisions

Contents

Create Sensor Factory Definitions

PrtgAPI can assist in the creation of complex sensor factories via the New-SensorFactoryDefinition cmdlet.

New-SensorFactoryDefinition can be used to automatically create channel definition records for a collection of PRTG Sensors. As a shorthand, the New-SensorFactoryDefinition cmdlet can be invoked via the fdef alias.

Basic Usage

At a minimum New-SensorFactoryDefinition requires one argument: a script block for determining the channel name

# Create a sensor factory for all CPU Load sensors using the "Total" channel (ID: 0)
C:\> Get-Sensor -Tags wmicpuloadsensor | fdef { $_.Device }

#1:dc1
channel(1001,0)
#2:exch1
channel(2003,0)
#3:dc2
channel(1004,0)
...

If no -ChannelId is specified, Channel ID 0 will be used by default.

You can also inject your definition straight into an existing sensor using Set-ObjectProperty

# Get the sensor factory sensor
$factory = Get-Sensor -Id 3045

# Create the sensor factory definition. If you need to execute New-SensorFactoryDefinition
# multiple times (see below), you can accumulate the results in an array
$definition = Get-Sensor -Tags wmicpuloadsensor | fdef { $_.Device } 0

# Update the channel definition
$factory | Set-ObjectProperty ChannelDefinition $definition

If you wish to update your definition manually, you can copy your definitions straight onto the clipboard by piping your output to clip, making it a lot easier to insert your definition into the PRTG web interface.

Get-Sensor -Tags wmicpuloadsensor | fdef { $_.Device } 0 | clip

When creating your sensor factory it is often ideal to sort your sensors before creating your definitions. When using the sensor's Device as the channel name, this can be done quite easily by piping into |sort Device

Get-Sensor -Tags wmicpuloadsensor | sort Device | fdef ...

If you wish to start at a channel record ID higher than 1 (for example if you have an aggregation channel definition you'll want to insert above) you can specify the -StartId parameter.

C:\> Get-Sensor -Tags wmicpuloadsensor | fdef { $_.Device} 0 -StartId 2

#2:dc1
channel(1001,0)
#3:exch1
channel(2001,0)
...

If you wish to specify a custom unit for each channel you can include this in the channel name

Get-Sensor -Tags wmicpu* | fdef { "$($_.Device) [bananas]" } 0

Horizontal lines can be generated by specifying the -Value the line should appear at and including the channel unit the line should apply to

C:\> fdef "Line at 40.2 [msec]" -Value 40.2 -StartId 3

#3:Line at 40.2 [msec]
40.2

Custom Expressions

For scenarios in which you may wish to change the the formula used by each channel definition (for example transforming a "percent remaining" value into "percent used") you can specify a custom -Expression

# Create a sensor factory displaying the amount of "used" memory
# by inverting the "Percent Available Memory" channel (ID: 0)
C:\> $sensors = Get-Sensor -Tags wmimemorysensor
C:\> $sensors | fdef { $_.Device } -Expression { "100 - $expr" }

#1:dc1
100 - channel(1001,0)
#2:exch1
100 - channel(2003,0)
#3:dc2(1004,0)
...

When specifying a custom expression, New-SensorFactoryDefinition defines two automatic variables that can be accessed inside of your script block

  • $_ - the current sensor in the pipeline
  • $expr - the default channel definition/expression

By default, PrtgAPI creates channel definitions in the format channel(<sensorId>, <channelID>). If you wish to create a sensor factory using sensors requiring different channel IDs (such as if your factory includes sensors of a different type, or the IDs of the channels in your sensors cannot be guaranteed) you can implement custom logic in the -Expression script block to determine the channel ID to use.

# Create a sensor factory for monitoring the CPU Ready of several VMware Virtual Machine (SOAP) sensors under the
# vCenter server "vcenter-1". Typically the CPU ready channel should be ID 10, but sometimes it is not!
$sensors = Get-Sensor -Type vcenterserverextern -Device vcenter-1 | where Message -notlike "*powered off*"|sort name
$sensors | fdef {$_.Name} -expr {"channel($($_.Id),$(($_ | Get-Channel "CPU ready (Percent)").Id))"} -ChannelId 10

Aggregation

To create a channel definition that involves performing mathematical operations across multiple sensor channels the -Aggregator parameter can be specified.

# Determine the total number of Active Sessions across all terminal servers
C:\> $sensors = Get-Sensor -Tags wmiterminalservice*
C:\> $sensors | fdef "Active Sessions" -Aggregator { "$acc + $expr" } 1

#1:Active Sessions
channel(1001,1) + channel(2002,1) + channel(3001,1) ...
# Determine the highest CPU Load of all CPU Load sensors
C:\> $sensors = Get-Sensor -Tags wmicpuloadsensor
C:\> $sensors | fdef "Highest CPU Load" -Aggregator { "max($expr,$acc)" }

#1:Highest CPU Load
max(channel(1001,0),max(channel(2001,0),max(channel(3001,0),channel(4001,0))))

When specifying an -Aggregator, either a custom ScriptBlock expression or well known aggregation function (Sum, Min, Max, Average) can be used.

$sensors | fdef "Highest CPU Load" -Aggregator Max

When specifying a custom aggregator, New-SensorFactoryDefinition defines three automatic variables that can be accessed inside of your script block

  • $_ - the current sensor in the pipeline
  • $expr - the default channel definition/expression of the current sensor
  • $acc - the accumulator, containing the entire channel definition so far.

When operating in aggregation mode, PrtgAPI will only create a single channel definition for all sensors piped into the cmdlet. To create an aggregation definition as well as definitions for each individual sensor, you can re-run New-SensorFactoryDefinition specifying the StartId parameter, or alternatively specify a collection of hashtable objects specifying the parameters of both New-SensorFactoryDefinition invocations as properties on each separate hashtable.

C:\> $sensors = Get-Sensor -Tags wmiterminalservice* 
C:\> $sensors | fdef { $_.Device } 1 -StartId 2

#2:ts1
channel(1001,1)
#3:ts2
channel(2002,1)
...

As specifying a custom -Expression allows you to override the channel ID for individual sensors, it should be generally unnecessary to refer to the raw pipeline input ($_) in the aggregation function. If you wish to redefine the expression used in the aggregation, please note that PrtgAPI automatically sets $acc to the first sensor's expression. As such, you will not be able to modify its channel ID without an amount of manual checking and intervention.

If you do wish to perform a second level expression modification (beyond the initial modifications in the -Expression function) you may wish to ensure that the -ChannelID passed to New-SensorFactoryDefinition is the right value for the first sensor you pipe in, allowing you to redefine the expression for all subsequent sensors without issue.

If you are trying to generate a sensor factory definition consisting of aggregation channels as well as the individual channels each aggregation consists of, this can be achieved either via multiple varying invocations of the New-SensorFactoryDefinition cmdlet or by specifying a collection of hashtables. For the most common case however of a leading aggregation channel followed by its constituents, this can be done in a single invocation via the Summary parameter set.

Finalizers

For scenarios requiring post processing actions be performed on accumulated results the -Finalizer parameter can be used. -Finalizer makes it possible to perform slightly more complex calculations, such as calculating an average

C:\> $sensors = Get-Sensor -Tags wmicpuloadsensor
C:\> $sensors | fdef "Average CPU Load" -Aggregator { "$expr + $acc" } -Finalizer { "($acc)/$($sensors.Count)" } 0

#1:Average CPU Load
(channel(1001,0) + channel(2001,0) + channel(3001,0) + channel(4001,0))/4

A -Finalizer can only be applied when -Aggregator is a ScriptBlock. If a well known aggregation function is specified in conjunction with a -Finalizer, an exception will be raised.

Summary

While it is possible to generate aggregated channels in addition to individual channels via multiple invocations of New-SensorFactoryDefinition or by specifying a collection of hashtables, this can be somewhat tedious for the common case of desiring a leading aggregation channel followed by its constituents.

To assist with this scenario, PrtgAPI allows specifying an optional -SummaryName / -SummaryExpression.

C:\> Get-Sensor -Tags wmicpu* | fdef { $_.Device } -SummaryName "Highest CPU Load" -SummaryExpression max

#1:Highest CPU Load
max(max(channel(2020,0), channel(2047,0)), channel(2059,0))
#2:dc-1
channel(2020,0)
#3:prtg-1
channel(2047,0)
#4:fs-1
channel(2059,0)

-SummaryExpression functions identically to the -Aggregator parameter. Either a well known aggregation function or a ScriptBlock can be specified to the -SummaryExpression. If a custom ScriptBlock expression is specified, an optional -SummaryFinalizer can be specified too.

For convenience, all summary parameters can be referred to via the following aliases

  • -SummaryName: -sn
  • -SummaryExpression: -se
  • -SummaryFinalizer: -sf
Get-Sensor -Tags wmicpu* | fdef { $_.Device } -sn "Highest CPU Load" -se max

HashTable

When trying to generate sensor factory definitions showing multiple channels of a given sensor, this can typically require multiple invocations of New-SensorFactoryDefinition to be performed, requiring you to keep track of what the -StartId should be for each successive invocation. This isn't very user friendly, can potentially require you to have to split your command up over multiple lines, or even have to open the PowerShell ISE to lay it all out in front of you.

The -HashTable parameter solves this problem, by allowing you to specify an array of hashtables, each containing the unique parameters that would be specified to an individual invocation of New-SensorFactoryDefinition. New-SensorFactoryDefinition will then iterate over these tables, storing the running channel record ID internally, spitting out all of the requested channel definitions as it goes

C:\> Get-Sensor -Tags wmimem* | fdef @{name={$_.Device}},@{name="Line at 40.2 [msec]";value=40.2}

#1:dc-1
channel(1001,0)
#2:dc-2
channel(1002,0)
#3:Line at 40.2 [msec]
40.2

PrtgAPI uses the PowerShell Engine to resolve the parameter names specified to the hashtables to the parameter names normally defined on the outer cmdlet; as such, you can treat the hashtables the same as you would if you were specifying parameters to the outer cmdlet normally.

By default, channels will begin incrementing the channel record ID from 1, which can be changed by specifying a value to the -StartId parameter on the outer cmdlet. If a StartId is specified as a value to an inner hashtable, this will effectively override the running count.

C:\> Get-Sensor | fdef @{name={$_.Device}; startid=3} -StartId 2

#3:dc-1
channel(1001,0)
#4:dc-2
channel(1002,0)

Sensor Creation

Brand new sensor factories can be created using New-SensorFactoryDefinition style syntax and immediately added to a specified device using the New-Sensor cmdlet

# Create a sensor factory called "CPU Overview" on the device with ID 1001
Get-Sensor -Tags wmicpu* | New-Sensor -Factory "CPU Overview" { $_.Device } -DestinationId 1001

The first three parameters to New-Sensor when creating a new sensor factory are always as follows

  1. -Factory SwitchParameter indicating we are creating a sensor factory
  2. -Name parameter specifying the name of the sensor to create, not the name to use in the sensor factory definition
  3. -ChannelName parameter specifying the normal name you would specify when invoking New-SensorFactoryDefinition manually

If you forget to specify parameter #2 and jump straight to specifying a ScriptBlock for the -ChannelName, you will get a ParameterBindingException and be very confused as to why it's not working.

# WRONG
Get-Sensor -Tags wmimem* | New-Sensor -Factory { $_.Device } -DestinationId 1001 -WhatIf

All of the techniques that apply to New-SensorFactoryDefinition can be used in conjunction with the New-Sensor cmdlet. Properties of the new sensor factory sensor itself can also be specified

# Create a CPU Overview sensor factory that includes a summary channel and
# displays a warning if any of the factory's channels enters an error state
$sensors | New-Sensor -Factory "CPU Overview" { $_.Device } -sn "Average Usage" -se Average -FactoryErrorMode WarnOnError -DestinationId 1001

To preview your sensor factory definition without actually creating your sensor, you can specify the -WhatIf parameter

C:\> Get-Sensor -Tags wmicpu* | New-Sensor -Factory "CPU Overview" { $_.Device } -sn "Average CPU" -se Average -DestinationId 1001 -WhatIf

What if: Performing the operation "New-Sensor: Name = 'CPU Overview', ChannelDefinition =

#1:Average CPU
avg(channel(2020,0), channel(2047,0), channel(2059,0))
#2:dc-1
channel(2020,0)
#3:prtg-1
channel(2047,0)
#4:fs-1
channel(2059,0)

" on target "Device ID: 1001".

If you want to create your sensor factory definition yourself (or utilize the output of an existing New-SensorFactoryDefinition invocation) this can be done using the -ChannelDefinition parameter of the appropriate parameter set. For more information on the available parameter sets, see Get-Help New-Sensor.

Examples

Create a sensor factory for displaying the total number of sessions on all servers in a terminal services cluster. Factory will contain four channel types

  • Total Sessions - displays total number of sessions across all servers
  • TSxx Total Sessions - displays total number of sessions on each server
  • Total Active Sessions - displays total number of active sessions across all servers
  • TSxx Active Sessions - displays number of active sessions on each server

Requirements

WMI Terminal Services (Win2008+) sensor on each terminal server

Assumptions

Servers are named in the format <client>-ts-xx

# Get all the sensors
$sensors = Get-Device contoso-ts* | sort Device | Get-Sensor -Tags wmiterm*

# Create the "Total Sessions" channels
$sensors | fdef { "TS$($_.Device -replace "(.+)(\d\d)",'$2') Total Sessions" } 0 -sn "Total Sessions" -se Sum

# Create the "Active Sessions" channels
$sensors | fdef { "TS$($_.Device -replace "(.+)(\d\d)",'$2') Active Sessions" } 1 -sn "Active Sessions" -se Sum -Start ($sensors.Count + 2)

Alternatively, you could create the whole thing in a one-liner. By specifying a collection of hashtables, New-SensorFactoryDefinition keeps track of the running -StartId for you, so you don't need to worry about this, as you would in the example above. For readability, you may wish to split each individual hashtable up into a separate variable. Most of the complexity in this example is the logic of formatting the channel display name.

Get-Device contoso-ts* | sort Device | Get-Sensor -Tags wmiterm* |
    fdef @{name={"TS$($_.Device -replace "(.+)(\d\d)",'$2') Total Sessions"}; sn="Total Sessions"; se="Sum"},
    @{name={"TS$($_.Device -replace "(.+)(\d\d)",'$2') Active Sessions"}; channelid=1; sn="Active Sessions"; se="Sum"}
#1:Total Sessions
channel(1001,0)+channel(1002,0)+channel(1003,0)
#2:TS02 Total Sessions
channel(1001,0)
#3:TS01 Total Sessions
channel(1002,0)
#4:TS03 Total Sessions
channel(1003,0)
#5:Total Active Sessions
channel(1001,1)+channel(1002,1)+channel(1003,1)
#6:TS02 Total Sessions
channel(1001,1)
#7:TS01 Total Sessions
channel(1002,1)
#8:TS03 Total Sessions
channel(1003,1)

Get Sensor Factory Sources

The sensors and channels that comprise a sensor factory can be retrieved using the Get-SensorFactorySource cmdlet.

C:\> Get-Sensor -Type "sensorfactory" -Count 1 | Get-SensorFactorySource

Name               Id      Device      Group           Probe           Status
----               --      ------      -----           -----           ------
Memory             2010    dc-1        Servers         Local Probe     Up
Memory             2011    sql-1       Servers         Local Probe     Down
Memory             2012    exch-1      Servers         Remote Probe    DownAcknowledged

If a sensor that is not a sensor factory is passed to Get-SensorFactorySource, an exception will be thrown.

By default Get-SensorFactorySource will retrieve the sensors that comprise a sensor factory. To retrieve the source channels instead, the -Channels parameter can be specified

C:\> Get-Sensor -Type "sensorfactory" -Count 1 | Get-SensorFactorySource -Channels

Name                SensorId    Id    LastValue LimitsEnabled UpperErrorLimit LowerErrorLimit ErrorLimitMessage
----                --------    --    --------- ------------- --------------- --------------- -----------------
Available Memory    2010         0    100 MByte          True              95                 PANIC!! PANIC!!!
Available Memory    2011         0    235 MByte         False
Available Memory    2012         0    312 MByte         False

See Also

Clone this wiki locally