-
-
Notifications
You must be signed in to change notification settings - Fork 38
Dynamic Parameters
PRTG supports the creation of a wide variety of objects. While PrtgAPI natively supports many of these object types, for others (such as sensors) it is impractical to include native support for every single variant available within PRTG from now until forever.
In order to support as many parameter types as possible, PrtgAPI supports the creation of dynamic parameters, wherein PrtgAPI will interrogate PRTG to determine the components that are required by the API request that is used to create the object.
PrtgAPI theoretically supports retrieving sensor targets for all sensor types supported by PRTG, including those that require additional information to be provided before initiating a query (such as SNMP Library, IPMI Sensor and Oracle Tablespace).
PrtgAPI provides the ability to dynamically create sensor parameters via the GetDynamicSensorParameters
method
// Create a set of sensor parameters for creating a VMware Datastore sensor
var parameters = client.GetDynamicSensorParameters(1001, "vmwaredatastoreextern");
// Create a new sensor from the parameters without making any changes
var sensors = client.AddSensor(1001, parameters);
When creating a set of DynamicSensorParameters
, two pieces of information must be provided: the ID of a device that supports the specified sensor, and the raw sensor type name. A list of all sensor types currently supported by PRTG can be retrieved via the GetSensorTypes
method.
//Retrieve all sensor types whose Id (raw name) or display name contains "vmware"
var vmwareTypes = client.GetSensorTypes().Where(
t => t.Id.Contains("vmware") || t.Name.Contains("vmware")
);
DynamicSensorParameters
provide three ways to access the parameters stored within them
- CLR properties
- Indexing
- Dynamic properties
Parameters common to all sensor types (Name
, Tags
, Interval
, etc) are provided as well typed CLR properties
parameters.Name = "My Cool Sensor";
parameters.Interval = ScanningInterval.FiveMinutes;
Parameters that are specific to a particular sensor type can be accessed via an indexer, similar to how you would use a Dictionary
var parameters = client.GetDynamicSensorParameters(2002, "exchangepsdatabase");
parameters["remount"] = 1;
To identify the name of the parameter that corresponds with the setting seen in the Add Sensor page of the PRTG UI, you can press Ctrl+Shift+J to activate the selector of the Chrome Developer Tools, then select the input field on the page to inspect the underlying name
property.
<!-- SQL Server Version textbox of a WMI SQL Server 2016 sensor -->
<input class="text valid" type="text" name="sqlversion_" id="sqlversion_" autocomplete="off" value="2016">
Parameters are accessed from DynamicSensorParameters
case insensitively. In addition, trailing underscores that may be present on the parameter's internal name do not need to be included when accessing the parameter.
If a parameter is assigned an array of values, by default these values will be serialized as multiple instances of a given parameter
//Add the parameters trafficmode_=errors&trafficmode_=discards&trafficmode_standinfornoselection
parameters["trafficmode"] = new[]{"errors","discards","standinfornoselection"};
This can be modified by changing the ParameterType
of the desired CustomParameter
object returned in the list of items returned from parameters[Parameter.Custom]
.
DynamicSensorParameters
can also be used in conjunction with dynamic
dynamic parameters = client.GetDynamicSensorParameters(2002, "exchangepsdatabase");
parameters.remount = 1;
When stored as a dynamic
it is possible to access all custom parameters of the object as if they were native properties. It is important to note however that the dynamic
keyword is infectious; anything a dynamic
touches will also become dynamic
.
dynamic parameters = client.GetDynamicSensorParameters(2002, "exchangepsdatabase");
//AddSensor will return an object of type "dynamic"
var sensors = client.AddSensor(2002, parameters);
//Specifying the expected return type however will prevent the dynamic "infection" spreading
List<Sensor> sensors = client.AddSensor(2002, parameters);
In addition, extension methods (such as LINQ) cannot be used against dynamic
objects, since the true return type of the method cannot be known at compile time. This can be circumvented by either calling the extension method directly, or by accessing the desired object using an indexer.
//Will generate a runtime exception that List<Sensor> does not have a method First()
Sensor sensor = client.AddSensor(2002, parameters).First();
//No error
Sensor sensor = Enumerable.First(client.AddSensor(2002, parameters));
//No error
Sensor sensor = client.AddSensor(2002, parameters)[0];
When constructing a sensor type's DynamicSensorParameters
, any sensor targets that were identified will be cached in a dictionary on the parameters object. By default, any fields that represent sensor targets will store the first sensor target compatible with that field, so if you want to utilize all of your targets you will need to explicitly say so.
//Create a new set of parameters for adding one or more VMware Datastore sensors
var parameters = client.GetDynamicSensorParameters(1001, "vmwaredatastoreextern");
//Select all datastores supported by the device
parameters["datafieldlist__check"] = parameters.Targets["datafieldlist__check"];
//Create a sensor for each VMware Datastore
var sensors = client.AddSensor(1001, parameters);
Note that since most sensor types have at most one sensor target field, it can often be simpler to use LINQ to access the first entry in the dictionary, rather than specifying the key name explicitly.
parameters["datafieldlist__check"] = parameters.Targets.First();
If you believe that the Targets
list is incorrectly empty, consider whether the specified device actually supports the targets you are trying to retrieve (e.g. just because a device supports SNMP, doesn't guarantee that it supports monitoring SNMP Services). If you believe your device is configured correctly but targets are still not appearing properly, verify whether the targets appear when attempting to create the sensor in the PRTG UI.
For sensor types that require additional information be provided before initiating a query (such as SNMP Library, IPMI Sensor and Oracle Tablespace) PrtgAPI allows you to specify this information via a sensor query target.
//Retrieve dynamic sensor parameters for creating an SNMP Library sensor using the OIDLIB "APC UPS.oidlib"
var oidlib = client.GetSensorTypes(1001).First(t => t.Id == "snmplibrary").QueryTargets(t => t.Value.Contains("UPS"));
var parameters = client.GetDynamicSensorParameters(1001, "snmplibrary", queryParameters: oidlib)
var qp = new SensorQueryTargetParameters
{
["database"] = "XE",
["sid_type"] = 0,
["prefix"] = 0
}
var parameters = client.GetDynamicSensorParameters(1001, "oracletablespace", queryParameters: qp);
For more information on sensor query targets, please see Sensor Query Targets.
Unlike RawSensorParameters, DynamicSensorParameters
represent a complete "set" of values required to create a new sensor. As such, by default PrtgAPI will attempt to protect you by throwing an exception when attempting to set the value of a property that does not exist
parameters["remount"] = 1;
parameters["remoun"] = 2; //InvalidOperationException
In the event you really do wish to add a new parameter however (for example, you have determined PrtgAPI has not included a critical parameter required to create your desired sensor type) you may unlock your dynamic parameters object
parameters.Unlock();
parameters["remoun"] = 2 //Will add a new parameter
parameters.newParam = 3 //Will also add a new parameter
The current lock status of a set of dynamic parameters can be queried via the IsLocked
method. Parameters can be re-locked via the Lock
method.
When a new parameter is added, its internal representation is stored exactly how it was when it was first specified. As such, if the initial name was in uppercase, the name will be uppercase when sent to the PRTG server. If the name did not have a trailing underscore, PrtgAPI won't send it with a trailing underscore. It is not possible have a single parameter defined multiple times with differing cases, with and without underscores. Whenever a parameter is set, PrtgAPI will find the existing matching parameter and update its value accordingly.
parameters.Unlock();
parameters["NEWPARAM"] = "hello"; //Add a new parameter
parameters["newparam_"] = "goodbye"; //Set NEWPARAM to "goodbye"
The presence of a given parameter can be identified via the Contains
method, while parameters can be removed via the Remove
method. As removal is an explicit action, parameters can be removed regardless of whether the DynamicSensorParameters
object IsLocked
or not.
//Remove the "NEWPARAM" parameter (if it exists)
if (parameters.Contains("NEWPARAM"))
parameters.Remove("NEWPARAM");
DynamicSensorParameters
can be created within PowerShell via the New-SensorParameters
cmdlet. To create a set of DynamicSensorParameters
, you must specify a device to create the parameters from and the raw type name of the sensor parameters you wish to create
To identify the raw identifier of a sensor type, the Get-SensorType
cmdlet can be used
C:\> Get-SensorType *vmware*
Id Name Description
-- ---- -----------
vmwaredatastoreextern VMware Datastore (SOAP) Monitors disk usage and...
esxelementhealth VMware Host Hardware (WBEM) Monitors hardware infor...
esxserverhealthsensorextern VMware Host Hardware Status (SOAP) Monitors the hardware h...
esxserversensorextern VMware Host Performance (SOAP) Monitors the performanc...
vcenterserverextern VMware Virtual Machine (SOAP) Monitors virtual machin...
When you have identified the raw sensor type identifier, the New-SensorParameters
cmdlet can be used to construct a set of DynamicSensorParameters
from any device that supports the creation of the specified sensor type.
C:\> $params = Get-Device esxi-1 | New-SensorParameters -RawType vmwaredatastoreextern
C:\> $params
datafieldlist : 1
datafieldlist__check : Datastore1
datastoreid :
vmwarewriteresult : 0
Targets : {[datafieldlist__check, PrtgAPI.GenericSensorTarget[]]}
Source : esxi-1
SensorType : vmwaredatastoreextern
Priority : Three
InheritTriggers : True
InheritInterval : True
...
Finally, you can apply your parameters to any device you like within PRTG.
C:\> Get-Device esxi* | Add-Sensor $params
Native (and therefore type safe) properties can be identified as those containing uppercase letters, whereas those specific to a particular sensor type are all lowercase.
DynamicSensorParameters
can be added by passing them to the Add-Sensor
cmdlet. If the parameters are piped to the Add-Sensor
cmdlet, PrtgAPI will add the parameters to the device that was used to create the parameters in the first place (identified via the parameters Source
property).
# Add a new Exchange Database sensor to device exch-1
Get-Device exch-1 | New-SensorParameters -rt -exchangepsdatabase | Add-Sensor
Parameters can also be applied to multiple devices by piping multiple devices to Add-Sensor
and specifying the parameters as an argument instead
$params = Get-Device exch-1 | New-SensorParameters -rt exchangepsdatabase
Get-Device *exch* | Add-Sensor $params
DynamicSensorParameters
function as a hybrid PSObject
/ Dictionary
. Custom parameters can be accessed via properties on the object as if they were native parameters, or via an indexer as if the object is a dictionary
$params.mutex = "mutex1"
$params["mutex"] = "mutex1"
Trailing underscores on parameter names are treated as an "implementation detail", and as such
- A parameter name with and without an underscore (e.g.
mutex
andmutex_
) are treated as the same parameter - trailing underscores do not need to be specified when accessing parameters
Attempting to modify and retrieve a non-existent parameters via their property names will always generate an InvalidOperationException
.
$params.blah = 3 # InvalidOperationException
$val = $params.blah # InvalidOperationException
When using an indexer however, by default PowerShell will actually suppress any exception thrown when trying to retrieve a value and instead return null
$params["blah"] = 3 # InvalidOperationException
$val = $params["blah"] # $val will be $null
This behavior occurs due to default strict mode of the PowerShell engine, which allows accessing non-existent properties from Dictionary
like objects. In order to generate the expected exception, you must set the strict mode of your session to PowerShell 3 or higher
Set-StrictMode -Version 3
$params["blah"] = 3 # InvalidOperationException
$val = $params["blah"] # InvalidOperationException
If a parameter is assigned an array of values, by default these values will be serialized as multiple instances of a given parameter
# Add the parameters trafficmode_=errors&trafficmode_=discards&trafficmode_standinfornoselection
$params.trafficmode = "errors","discards","standinfornoselection"
This can be modified by changing the ParameterType
of the desired CustomParameter
object returned in the list of items returned from $params.GetParameters()["Custom"]
.
Sensor Targets identified for the specified sensor type are stored in a dictionary accessible via the Targets
property. Each dictionary key corresponds with the field its values belong to.
# Add specific VMware Datastores to the set of sensor parameters
$params.datafieldlist__check = $params.Targets["datafieldlist__check"] | where Name -like *primary*
By default, any fields that represent sensor targets will store the first sensor target compatible with that field. For scenarios in which a sensor type only has a single sensor target property, the -Target
parameter can be specified to New-SensorParameters
, specifying a wildcard expression used to identify the sensor targets to utilize.
# Create a new set of VMware Datastore parameters targeting all available datastores
C:\> Get-Device esxi-1 | New-SensorParameters -rt vmwaredatastoreextern -Target *
datafieldlist : 1
datafieldlist__check : {Datastore1, Datastore2, Datastore3}
datastoreid :
...
For sensor types that require additional information be provided before initiating a query (such as SNMP Library, IPMI Sensor and Oracle Tablespace) PrtgAPI allows you to specify this information via a sensor query target.
# Retrieve dynamic sensor parameters for creating an SNMP Library sensor using the OIDLIB "APC UPS.oidlib"
$params = Get-Device -Id 1001 | New-SensorParameters -rt snmplibrary -qt *ups*
# Retrieve dynamic sensor parameters for creating an Oracle Tablespace sensor using a set of
# sensor query target parameters that specify the database to connect to
$params = Get-Device -Id 1001 | New-SensorParameters -rt oracletablespace -qp @{
database = "XE"
sid_type = 0
prefix = 0
}
For more information on sensor query targets, please see Sensor Query Targets.
Unlike RawSensorParameters, DynamicSensorParameters
represent a complete "set" of values required to create a new sensor. As such, by default PrtgAPI will attempt to protect you by throwing an exception when attempting to set the value of a property that does not exist
$params.remount = 1
$params.remoun = 2 # InvalidOperationException
In the event you really do wish to add a new parameter however (for example, you have determined PrtgAPI has not included a critical parameter required to create your desired sensor type) you may unlock your dynamic parameters object
$params.Unlock();
$params["remoun"] = 2 # Will add a new parameter
$params.newParam = 3 # Will also add a new parameter
The current lock status of a set of dynamic parameters can be queried via the IsLocked
method. Parameters can be re-locked via the Lock
method.
When a new parameter is added, its internal representation is stored exactly how it was when it was first specified. As such, if the initial name was in uppercase, the name will be uppercase when sent to the PRTG server. If the name did not have a trailing underscore, PrtgAPI won't send it with a trailing underscore. It is not possible have a single parameter defined multiple times with differing cases, with and without underscores. Whenever a parameter is set, PrtgAPI will find the existing matching parameter and update its value accordingly.
$params.Unlock();
$params.NEWPARAM = "hello" # Add a new parameter
$params.newparam_ = "goodbye" # Set NEWPARAM to "goodbye"
The presence of a given parameter can be identified via the Contains
method, while parameters can be removed via the Remove
method. As removal is an explicit action, parameters can be removed regardless of whether the DynamicSensorParameters
object IsLocked
or not.
//Remove the "NEWPARAM" parameter (if it exists)
if ($params.Contains("NEWPARAM"))
{
$params.Remove("NEWPARAM")
}