-
-
Notifications
You must be signed in to change notification settings - Fork 38
Deferred Tree Values
- Core Concepts
- Tree Creation
-
Infrastructure As Code
- Introduction
- Deferred Tree Values
- Migration
- Tree Manipulation
- Extensibility
Consider the following command:
SensorNode ping
This creates a new SensorNode
for any Sensor
objects named ping. Or so you'd think. There of course could be many dozen ping sensors on your PRTG installation, and you might only be interested in one of them!
Now consider the following: suppose we have a device, dc-1, that we'd like to model as having a child sensor. i.e, we wish to describe the tree
Server (Device)
└──Ping (Sensor)
PrtgAPI enables you to model this hierarchy via the use of ScriptBlock
objects that can be specified to PrtgAPI's node cmdlets. These ScriptBlock
s literally allow you to describe the levels at which different objects should appear.
DeviceNode dc-1 {
SensorNode ping
}
While this all sounds nice, we have a problem: logically, when we do SensorNode ping
, what we really want is to retrieve only ping sensors that exist within the context of the parent dc-1 device. However, the SensorNode
doesn't know anything about its parent context. How are we supposed to retrieve the right information?
It's even worse in this example:
We want to describe the following tree
Windows Infrastructure (Group)
└──dc-1 (Device)
└──Ping (Sensor)
└──exch-1 (Device)
└──Ping (Sensor)
So we do the following in PowerShell
$ping = SensorNode ping
GroupNode "Windows Infrastructure" {
DeviceNode dc-1 {
$ping
}
DeviceNode exch-1 {
$ping
}
}
Not only did we retrieve our ping sensors outside of the scope of their parent objects, but we've then attempted to apply these as the children of two completely different devices. How can PrtgAPI possibly deal with this madness? We certainly don't want to retrieve all ping sensors and then filter them down to just 1 or 2.
The answer is simple: when a node cmdlet is invoked with non-uniquely identifiable parameters (e.g. there could be several objects all over the tree with a given Name, Position or Tag), PrtgAPI simply wraps up your request and returns a deferred value that will be evaluated later, once it has been made the child of a suitable parent.
# Create a SensorNode around sensors named ping. Upon emitting the value to the pipeline,
# we see that two such sensors exist within the PRTG server
C:\> SensorNode ping
Name Type Parent Children
---- ---- ------ --------
[Maybe] Ping, Ping Sensor {}
If any members of the node's Value
are accessed (such as its Name
), PrtgAPI will execute an API request to PRTG based on what it knows so far to identify the potential candidates that may satisfy your original request. When a single matching candidate is found, you will be able to access the members of that candidate via your deferred value
# Get the Tags of the single "Uptime" candidate"
C:\> $node = SensorNode Uptime
C:\> $node.Value.Tags
wmiuptimesensor
C_OS_VMware
# Note that it's not a real sensor however!
C:\> $node.Value.GetType()
IsPublic IsSerial Name BaseType
-------- -------- ---- --------
False False SensorProxy PrtgAPI.Tree.SensorOrDeviceOrGroupO...
If zero matches were found, the PowerShell formatting system will helpfully display to you that an error occurred, however you won't be able to get more specific information until you actually try and resolve your SensorNode
under a parent.
C:\> $node = SensorNode Uptime1
C:\> $node
Name Type Parent Children
---- ---- ------ --------
#ERR Sensor {}
Failed to evaluate expression "Name".
+ CategoryInfo : InvalidArgument: (:PSObject) [], GetValueInvocationException
+ FullyQualifiedErrorId : mshExpressionError
C:\> DeviceNode dc-1 { $node }
format-default : The following exception occurred while retrieving members: "Failed to resolve any Sensor objects
where 'Name = Uptime1, Device = dc-1'. Could not create a SensorNode."
+ CategoryInfo : NotSpecified: (:) [format-default], ExtendedTypeSystemException
+ FullyQualifiedErrorId : CatchFromBaseGetMembers,Microsoft.PowerShell.Commands.FormatDefaultCommand
Note that in both of these examples, since both the sensor and devices list here are deferred values, both of these errors are actually thrown while emitting these value to the pipeline
-
In the first example, accessing the
Name
of the sensor triggers the exception.Since this exception occurs inside of PowerShell's formatting engine (rather than a PrtgAPI cmdlet such as the
New-SensorNode
cmdlet, which has already ended) we're unable to get more detailed information about what went wrong -
In the second example, the exception is thrown while trying to display the names of the
Children
under the device.Since the sensor is resolved under the context of the still-active
New-DeviceNode
cmdlet, we're able to see the error message when the sensor cannot be resolved
Ultimately, PrtgAPI will force resolution of all of the objects in your tree when you go to calculate the changes that will need to be applied to PRTG, so any errors like this will ultimately be caught one way or the other.