Skip to content

Dynamic Parameters

lordmilko edited this page Sep 19, 2023 · 57 revisions

Contents

Overview

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).

C#

Introduction

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")
);

Accessing Parameters

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];

Targets

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.

Query Targets

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.

Adding Parameters

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");

PowerShell

Introduction

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

Accessing Parameters

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 and mutex_) 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"].

Targets

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          :
...

Query Targets

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.

Adding Parameters

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")
}

See Also

Clone this wiki locally