DSL Processor
Introduction
The DSL Processor is a powerful tool designed to streamline and enhance your data processing workflows. It allows you to define and execute complex data transformations using a simple and intuitive domain-specific language (DSL). The NetObserv Trap Collector leverages Benthos Bloblang as a DSL and includes additional SNMP-specific functions to enrich and transform the data from SNMP traps.
Features
- Intuitive Syntax: Write clear and concise transformation rules.
- High Performance: Optimized for speed and efficiency.
- Flexibility: Easily adaptable to various data processing needs.
Custom Functions
Trapcoll DSL Processor supports the following custom functions:
snmp_display_string()
The snmp_display_string()
transforms a raw OCTET STRING
to a DisplayString
value (per SNMPv2-TC
). In the case of an error while processing the raw value, an empty string is returned.
Example:
root.out.netapp.productSerialNum = this.trap.VarBinds.index(1).Value.snmp_display_string()
snmp_date_and_time()
The snmp_date_and_time()
transforms a raw OCTET STRING
to a DateAndTime
value (per SNMPv2-TC
). In the case of an error processing the raw value an empty string is returned.
Example:
root.out.juniper.jnxOperatingRestartTime = this.trap.VarBinds.index(0).Value.snmp_date_and_time().ts_unix_milli()
snmp_int_enum_enrich() - was enum_enrich()
The snmp_int_enum_enrich()
function transforms an integer to the enumerated string that it represents. Integer enumerations are located by default in /etc/elastiflow/snmp/enums/integer
. Note that enum_enrich()
is deprecated. While it still works, it will be removed in a future release.
Example:
root.out.IETF.ospfLsdbType = this.trap.VarBinds.index(2).Value.snmp_int_enum_enrich(".1.3.6.1.2.1.14.4.1.2")
Syntax
snmp_int_enum_enrich("[OID]")
Parameters
OID
(string): The Object Identifier used as a key for the enumeration keys.
snmp_mac_address()
The snmp_mac_address()
function transforms a raw OCTET STRING
to a MacAddress
value (per SNMPv2-TC
). In the case of an error processing the raw value an empty string is returned.
Example:
root.out.cisco.cVpcSystemOperMacAddress = this.trap.VarBinds.index(2).Value.snmp_mac_address()
snmp_octet_string()
The snmp_octet_string()
function transforms a raw OCTET STRING
to a hex string, e.g. 0708090a0b0c
. In the case of an error processing the raw value an empty string is returned.
Example:
root.out.IETF.nlmLogVariableOpaqueVal = this.trap.VarBinds.index(0).Value.snmp_octet_string()
snmp_oid_get_index()
The snmp_oid_get_index()
function extracts the Index portion of a variable binding OID following a supplied prefix.
Example:
root.out.object.index = this.trap.VarBinds.index(0).OID.snmp_oid_get_index(".1.3.6.1.2.1.14.4.1.2")
Syntax
snmp_oid_get_index("[OID]")
Parameters
OID
(string): The Object Identifier used as a key for the enumeration keys.
snmp_oid_extract_index()
The snmp_oid_extract_index()
function extracts the index values from a variable binding OID based on a comma-separated list of index types. The output is an array of index values.
Example:
root.out.object.index.snmp_oid_extract_index("IpAddress,Integer,IpAddress,IpAddress")
Syntax
snmp_oid_extract_index("[comma-separated list of Index value types]")
Parameters
comma-separated list of Index value types
(string): The list of index value types to extract from the OID index.
The following is a list of supported values. Note that these are the same index value types supported by the NetObserv SNMP Collector object definitions.
Integer
OctetString
ImplicitOctetString
ObjectIdentifier
ImplicitObjectIdentifier
Integer32
IpAddress
MacAddress
Unsigned32
Opaque
snmp_inet_address()
The snmp_inet_address()
function transforms an InetAddress
value (per INET-ADDRESS-MIB
) into an IP address, IP address with Zone, or DNS name based on an Integer
value of InetAddressType
.
Example:
root.out.TEST.inetAddress = this.trap.VarBinds.index(2).Value.snmp_inet_address(root.out.TEMP.inetAddressType)
Syntax
snmp_inet_address([InetAddressType])
Parameters
InetAddressType
(Integer): The value ofInetAddressType
which indicates the type of theInetAddress
that is being transformed.
snmp_int_to_ipv4()
The snmp_int_to_ipv4()
function transforms an Integer raw value into an IPv4 address string.
Example:
root.out.TEST.intToIPv4 = this.trap.VarBinds.index(3).Value.snmp_int_to_ipv4()
Examples of using the custom functions
Extract and transform index values from the OID of a variable binding
The following variable binding contains and instance of ospfLsdbType
from OSPF-MIB
.
{
Name: ".1.3.6.1.2.1.14.4.1.2.0.0.0.103.3.155.172.64.15.192.168.215.36", // ospfLsdbType
Type: Integer,
Value: 3,
},
First we extract the index portion of the variable bindings OID:
root.out.snmp.object.index = this.trap.VarBinds.index(0).OID.snmp_oid_get_index(".1.3.6.1.2.1.14.4.1.2")
Which produces the following output:
{
"snmp":
"object": {
"index": "0.0.0.103.3.155.172.64.15.192.168.215.36"
}
}
}
Next we extract the individual components of the index, assigning them to a temporary variable that can be deleted later.
root.TEMP.ospfLsdbEntry = root.out.object.index.snmp_oid_extract_index("IpAddress,Integer,IpAddress,IpAddress")
We can then assign the values from the array to fields in the output record. Note the use of snmp_int_enum_enrich()
to also transform root.out.ospf.LsdbType
to its enumerated string value.
root.out.ospf.LsdbAreaId = root.TEMP.ospfLsdbEntry.index(0)
root.out.ospf.LsdbType = root.TEMP.ospfLsdbEntry.index(1).snmp_int_enum_enrich(".1.3.6.1.2.1.14.4.1.2")
root.out.ospf.LsdbLsid = root.TEMP.ospfLsdbEntry.index(2)
root.out.ospf.LsdbRouterId = root.TEMP.ospfLsdbEntry.index(3)
The resulting output record is now:
{
"ospf": {
"LsdbAreaId": "0.0.0.103",
"LsdbLsid": "155.172.64.15",
"LsdbRouterId": "192.168.215.36",
"LsdbType": "summary link"
},
"snmp":
"object": {
"index": "0.0.0.103.3.155.172.64.15.192.168.215.36"
}
}
}
Handling the various forms of IP addresses
SNMP has various ways of expressing IP addresses.
- Originally SNMP only supported IPv4 addresses, the
IpAddress
type. - As an IPv4 address is 4 bytes in size, some vendors choose to use a 32-bit integer to express the four bytes.
- To add support for IPv6 and other possible types, the
INET-ADDRESS-MIB
introducedInetAddress
andInetAddressType
, where the latter declares the type, and thus the necessary transformation, of the former. As a result these two value are commonly seen together.
Handling values of types InetAddress
and InetAddressType
Let's look at this last use-case first. Consider the following variable bindings which contain an InetAddressType
and an InetAddress
.
{
Name: ".1.2.3.4.5.6.7.8.9.0.1", // IPv6 InetAddressType
Type: Integer,
Value: 2,
},
{
Name: ".1.2.3.4.5.6.7.8.9.0.2", // IPv6 InetAddress
Type: OctetString,
Value: []byte{0x20, 0x1, 0x0d, 0xb8, 0x85, 0xa3, 0x00, 0x00, 0x00, 0x00, 0x8a, 0x2e, 0x03, 0x70, 0x73, 0x34},
},
Let's first assign the InetAddressType
to a field.
root.out.MyInetAddressType = this.trap.VarBinds.index(1).Value
We can then pass this InetAddressType
value into snmp_inet_address()
to transform the InetAddress
variable binding's value.
root.out.MyInetAddress = this.trap.VarBinds.index(2).Value.snmp_inet_address(root.out.MyInetAddressType)
The resulting record fields are:
{
"MyInetAddress": "2001:db8:85a3::8a2e:370:7334",
"MyInetAddressType": 2
}
Note that we could also use snmp_int_enum_enrich()
to further transform MyInetAddressType
, or we could drop the field if it is no longer needed after the transformation of MyInetAddress
.
Handling IPv4 addresses expressed as a 32-bit integer
As mentioned above, an IPv4 address is 4 bytes in size, so some vendors will choose to use a 32-bit integer to express the four bytes of the address.
{
Name: ".1.2.3.4.5.6.7.8.9.0.3", // 192.168.1.1 as an Unsigned32
Type: Uinteger32,
Value: uint32(3232235777),
},
The snmp_int_to_ipv4()
function allows the integer value to be easily transformed into an IPv4 address.
root.out.MyIntToIPv4 = this.trap.VarBinds.index(3).Value.snmp_int_to_ipv4()
The resulting output is:
{
"MyIntToIPv4": "192.168.1.1"
}