Skip to content

Custom Parameters

lordmilko edited this page Aug 21, 2019 · 36 revisions

Contents

Overview

PrtgAPI supports the creation of a variety different object types, through cloning existing objects, or creating new objects from scratch with well typed or dynamically generated request parameters. For scenarios in which PrtgAPI's built-in facilities do not yet support the object you wish to create, a set of custom parameters may be used to specify the properties to include in the object creation request.

C#

Sensor Parameters

Sensor parameter types that are not yet supported by PrtgAPI can still be added to PRTG via the RawSensorParameters type. RawSensorParameters provides a wide level of versatility, ranging from flinging together a collection of parameters for creating a sensor in a fairly specific way to defining whole new sensor parameter types specific to your desired sensor.

When defining sensor parameters for a new sensor type, the first thing you must know is the parameters required to create the sensor. This can be determined by tracing your computer with Fiddler, adding the specified sensor via the PRTG UI and inspecting the parameters under TextView or WebForms of the URL addsensors5.htm. For example, when an EXE/Script Advanced sensor is added, the sensor parameters are as follows:

name_=XML+Custom+EXE%2FScript+Sensor&parenttags_=C_OS_VMware+parenttag&tags_=xmlexesensor&
priority_=3&exefile_=test.ps1%7Ctest.ps1%7C%7C&exefilelabel=&exeparams_=&environment_=0&
usewindowsauthentication_=0&mutexname_=&timeout_=60&writeresult_=0&intervalgroup=0&
intervalgroup=1&interval_=60%7C60+seconds&errorintervalsdown_=1&inherittriggers=1&
id=2136&sensortype=exexml

Spaces are encoded as plus signs (+), whereas other symbols are encoded as %__. Before beginning, it is recommended to split up and decode your parameters to see what symbols are used in your parameters in case any fields require their values to be written in a certain way. The decoded response can be found on the WebForms page of the Inspectors tab within Fiddler.

After completing these steps, it can be seen EXE/Script Advanced sensors contain the following parameters

Name Value Description
name_ XML Custom EXE/Script Sensor Sensor Name
parenttags_ C_OS_VMware parenttag Parent Tags
tags_ xmlexesensor Tags
priority_ 3 Priority
exefile_ test.ps1|test.ps1|| EXE/Script
exefilelabel_ N/A
exeparams_ Parameters
environment_ Environment
usewindowsauthentication_ 0 Security Context
mutexname_ Mutex Name
timeout_ 60 Timeout
writeresult_ 0 EXE Result
intervalgroup 0 Inherit Interval
intervalgroup 1 Inherit Interval
interval_ 60|60 seconds Scanning Interval
errorintervalsdown_ 1 If a Sensor Query Fails
inherittriggers 1 Inherit Triggers (Notifications Tab)
id 2136 Device ID
sensortype exexml Sensor Type

Not all parameters necessarily need to be included in your sensor parameters. id never needs to be defined, as this is determined via the deviceId passed to the AddSensor method. Other parameters such as name_ and inherittriggers are also unnecessary, being defined under the NewSensorParameters base type. You may also find that certain parameters are also unnecessary (parenttags_) or even redundant (multiple intervalgroup instances). Based on how sophisticated you wish to make your custom parameter wrappers, it is up to you to determine that specifying the value of a parameter actually has the desired effect.

It is also worth noting that while it is good practice to specify all values required by a sensor, it is not absolutely required. For any fields not required to create the sensor, PRTG will assign these their default values; as such, while fields like the name, sensor type and EXE file of an EXE/Script Advanced sensor must be specified, the timeout and Windows Authentication mode can probably be ignored if you don't care about them.

Quick And Dirty

The easiest way to create an unsupported sensor is to instantiate a new RawSensorParamaters object, adding the required parameters via the parameters object's indexer.

var parameters = new RawSensorParameters("raw c# sensor", "exexml")
{
    Tags = new[] { "xmlexesensor" },
    Priority = Priority.Four,
    InheritInterval = false,
    Interval = ScanningInterval.ThirtySeconds,
    IntervalErrorMode = IntervalErrorMode.TwoWarningsThenDown,
    InheritTriggers = false,
    ["exefile_"] = "test.ps1|test.ps1||",
    ["exeparams_"] = "arg1 arg2 arg3",
    ["environment_"] = 1,
    ["usewindowsauthentication_"] = 1,
    ["mutexname_"] = "testMutex",
    ["timeout_"] = 70,
    ["writeresult_"] = 1
};

client.AddSensor(1001, parameters);

Parameters common to all objects (such as Priority and Interval) are defined on the base NewSensorParameters type. As such, you can assign type safe values to these properties, without having to worry about the complexities of raw parameter names and values. The presence of parameters can be validated via the Contains method, while parameters can be removed via the Remove method.

Based on your requirements, you can wrap the creation of the custom parameters up in a method accepting just the properties you need to configure as arguments, or even derive a new sensor parameters type that performs all this work in the constructor. If you want to get really crazy however you can add create a whole new type whose property members implement type safety for you.

Well Typed

If you are serious about adding new sensors in a production grade system and believe your custom parameters will be used a lot, in addition to housing your parameters in a type deriving from RawSensorParameters, it is recommended to encapsulate the underlying parameter set via a collection of properties that automatically serialize and deserialize values based on the expected type you would normally use the property with.

PrtgAPI defines the following methods for safely storing and retrieving values from the underlying parameter set

  • GetCustomParameter / SetCustomParameter
  • GetCustomParameterInternal / SetCustomParameterInternal
  • GetCustomParameterEnumXml / SetCustomParameterEnumXml
  • GetCustomParameterBool / SetCustomParameterBool
  • GetCustomParameterArray / SetCustomParameterArray

Each method typically contains two overloads, allowing the parameter name to be specified via an ObjectProperty known to PrtgAPI, or via the raw parameter name (where the property is currently unsupported).

The following example shows a custom parameter type for adding EXE/Script Advanced sensors, demonstrating how string, bool, enum and array types can be safely stored and retrieved from the underlying parameter set. To avoid any well known dependent properties being modified in the constructor (such as InheritInterval upon setting the Interval) these items are wrapped in a ConstructorScope. A secondary custom class is also defined to encapsulate the logic needed to serialize the exefile_ parameter value into the form expected by PRTG. The ExeFile property is also marked with the RequireValue attribute, which will cause the AddSensor method to throw an exception if it determines the specified property has either been assigned null or string.Empty.

Note that while these parameters choose to represent the ExeFile as a string, one could also use a GenericSensorTarget, eliminating the need for the ScriptName wrapper type.

public class ExeXmlRawSensorParameters : RawSensorParameters
{
    public ExeXmlRawSensorParameters(string sensorName, string sensorType, string exeFile)
        : base(sensorName, sensorType)
    {
        using (ConstructorScope)
        {
            ExeFile = exeFile;

            Tags = new[] {"xmlexesensor"};

            //Assign the other properties...
        }
    }

    public string[] Tags
    {
        get { return GetCustomParameterArray("tags_", ' '); }
        set { SetCustomParameterArray("tags_", value, ' '); }
    }

    [RequireValue(true)]
    public string ExeFile
    {
        get { return ((ScriptName)GetCustomParameterInternal("exefile_")).Name; }
        set { SetCustomParameterInternal("exefile_", new ScriptName(value)); }
    }

    //Define the other properties...
}

internal class ScriptName
{
    public string Name { get; set; }

    internal ScriptName(string name)
    {
        Name = name;
    }

    public override string ToString()
    {
        return $"{Name}|{Name}||";
    }
}

For complete examples on defining sensor parameter types, see ExeXmlSensorParameters and ExeXmlRawSensorParameters.

PowerShell

Sensor Parameters

PrtgAPI provides two ways to create a set of RawSensorParameters within PowerShell:

  • Import a hashtable
  • Add dictionary entries

Hashtables can be used to instantiate new sensor parameter objects via the -RawParameters parameter of New-SensorParameters. When defining sensor parameters for a new sensor type, the first thing you must know is the parameters required to create the sensor. For information on how to determine this, please see the introduction of the C# section for creating unsupported sensor parameters.

Once you have determined the parameters required to create the specified sensor type, simply define a hashtable mapping each parameter name to its corresponding value.

$table = @{
    "name_" = "my raw sensor"
    "tags_" = "xmlexesensor"
    "priority_" = 4
    "exefile_" = "test.ps1|test.ps1||"
    "exeparams_" = "arg1 arg2 arg3"
    "environment_" = 1
    "usewindowsauthentication_" = 1
    "mutexname_" = "testMutex"
    "timeout_" = 70
    "writeresult_" = 1
    "intervalgroup" = 0
    "interval_" = "30|30 seconds"
    "errorintervalsdown_" = 2
    "sensortype" = "exexml"
    "inherittriggers_" = 0
}

$params = New-SensorParameters $table

Get-Device -Id 1001 | Add-Sensor $params

When constructing unsupported sensor parameters, PrtgAPI will validate that at a minimum the name_ and sensortype parameters have been specified. If either of these is not specified, PrtgAPI will throw an InvalidOperationException specifying the value that was missing.

Alternatively, PrtgAPI supports creating an empty set of sensor parameters, allowing all of their fields to be populated after the object has been created

C:\> New-SensorParameters -Empty

SensorType        :
Priority          :
InheritTriggers   :
InheritInterval   :
Interval          :
IntervalErrorMode :
Name              :
Tags              :

Empty sensor parameters must have their Name and SensorType assigned to before passing to Add-Sensor. Failure to populate these fields will generate an InvalidOperationException specifying the property is mandatory.

Once created, RawSensorParameters 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 was a dictionary

$params.mutex_ = "mutex1"

$params["mutex_"] = "mutex1"

Unlike Dynamic Parameters, RawSensorParameters do not abstract away the trailing underscores from the ends of parameter names and can only add new properties via their indexer. Attempting to retrieve a non-existent property via a property name or an indexer will return $null.

$params.test_         # Returns null
$params["test_"]      # Returns null

$params.test1 = 3     # PropertyAssignmentException
$params["test1_"] = 3 # OK

Objects return null when accessing non-existent values due to default strict mode of the PowerShell engine. In order to generate the expected exceptions, you must set the strict mode of your session to PowerShell 3 or higher

Set-StrictMode -Version 3

$params.test_    # PropertyNotFoundException
$params["test_"] # InvalidOperationException

Parameters are accessed from RawSensorParameters case insensitively. The true case of a parameter is determined by the case that was used when the parameter was first created

$params["NEWPARAM_"] = 3
$params.newparam_ = 4

The raw underlying key/value pairs of a parameter set can be viewed by accessing the hidden Parameters member

C:\> $params.Parameters

Name       Value
----       -----
name_      New Sensor
...

The presence of a parameter can be determined via the Contains method, while parameters can be removed via the Remove method.

In practice it is only necessary to specify values that absolutely require values (such as the name, sensor type and EXE file). If any optional fields are not specified, PRTG will assign these their default values.

Overriding Parameters

RawSensorParameters derives from the types NewSensorParameters and NewObjectParameters, which define a number of well typed properties for the parameters common to all sensor types (such as Priority, Name, Interval, etc).

Generally speaking, the serialized name of these parameters is common across all sensor types. However, certain sensor types may require a non-standard parameter name in order to work properly (such as snmplibrary, which requires its Name property name be serialized as name rather than name_. To support this behavior, PrtgAPI provides the facilities to override, inspect and remove parameter name overrides for all known ObjectProperty values.

A parameter name override can be added with the AddNameOverride method

//C#

//Rename the "name" parameter name from "name_" to "name"
var parameters = new RawSensorParameters("test", "snmplibrary");
parameters.AddNameOverride(ObjectProperty.Name, "name");
# PowerShell

# Rename the "name" parameter name from "name_" to "name"
$params = New-SensorParameters $table
$params.AddNameOverride("Name", "name")

Parameter name overrides can be inspected with the GetNameOverrides and ContainsNameOverride methods, and can be removed via the RemoveNameOverride method.

Note that Dynamic Parameters do not need to specify parameter name overrides manually, as this is done automatically by PrtgAPI.

See Also

Clone this wiki locally