In the XML parser, we have several operators which need to be used at different levels.
_vars - allows you to define variable which can be used later on in the script. The parser will basically replace the vars throughout the script with the value you set. For example, this:
_vars:
root: /response/result
Means "${root}" will be replaced with "/response/result" throughout the script.
_tags:
"os.name":
_constant: "panos"
"os.version":
_text: "/response/result/system/sw-version"
"vendor":
_constant: "paloaltonetworks"
"model":
_text: "/response/result/system/model"
_metrics:
-
_value.double:
_count: "${root}/entry"
_tags:
"im.name":
_constant: "routes-usage"
A few things to note:
_optional_metrics
instead of _metrics
, one could override this behavior and not fail the command when no metrics are parsed._omit: - _top: 2 - _bottom: 3 - _regex: "regex"
Means omit 2 lines from the top, then three lines from the bottom, the lines matching "regex". The order matters - the omitting will be executed according to the order. Older versions didn't use the "-" at the beginning of each operator line. In that case, it only supported _top and _bottom, no _regex.
Metrics can be either DOUBLE (a number) or COMPLEX (essentially a JSON structure):
_value.double:
_constant: "1"
When grabbing a value (for the double metric, for a temporary variable (discussed further below) or for a value in a JSON structure), you can use these operators:
_attribute: _name: "name"Will extract "john" from <element name="john">blah blah<element>
In order to iterate over multiple elements which match a certain xpath (for example, a list of users, or a list of disks), use the _groups section. For example:
_metrics: - _groups: ${root}/job: # This will iterate over each element called "job". _value.complex: id: _text: "id" status: _text: "status" result: _text: "result" details: _text: "details" _tags: "im.name": _constant: "jobs" _value: complex-array # Tells the parser to treat this as a JSON array - multiple objects, each has the id, status, result and details keys |
Lastly, there's the _transform block. This allows you to translate the contents you've pulled from the XML to the format the metrics need. You use _awk to do this. For example:
_metrics: - _tags: "im.name": _constant: "uptime-seconds" "live-config": _constant: "true" "display-name": _constant: "Uptime" "im.dstype.displayType": _constant: "seconds" _temp: "uptime": _text: "/response/result/system/uptime" _transform: _value.double: | { # 230 days, 16:57:34 split("${temp.uptime}", vals, " ") if (arraylen(vals) == 3 && vals[2] == "days,") { # 230 days, 16:57:34 days = vals[1] split(vals[3], timevals, ":") hours = timevals[1] minutes = timevals[2] seconds = timevals[3] uptime = (days * 3600 * 24) + (hours * 3600) + (minutes * 60) + seconds print uptime } } |
_metrics: - _groups: ${root}/*: _temp: status: _text: "status" _tags: name: _text: "name" "im.name": _constant: "ntp-server-state" "live-config": _constant: "true" "display-name": _constant: "NTP Servers - State" "im.dstype.displayType": _constant: "state" "im.identity-tags": _constant: "name" _transform: _value.double: | { if ("${temp.status}" == "synched") {print "1.0"} else {print "0.0"} } |
If you want to try and grab information from a parent element, use ancestor, like here:
_metrics: - _groups: ${root}/data-processors/*/second/cpu-load-average/entry: _value.double: _text: value _temp: coreid: _text: "coreid" dpid: _name: ancestor::node()[3] _tags: "im.name": _constant: "cpu-usage" "live-config": _constant: "true" "display-name": _constant: "CPU Usage" "im.dstype.displayType": _constant: "percentage" "im.identity-tags": _constant: "cpu-id" "cpu-is-avg": _constant: "false" _transform: _tags: "cpu-id": | { print "${temp.dpid}: ${temp.coreid}" } |