
[[snmp-index]]
= Create a Custom Resource Type
:description: Create custom resource types in {page-component-title} to collect SNMP data from tables with arbitrary indexes: attributes, mibObj definitions.

This section describes how to create a custom resource type to collect SNMP data from tables with arbitrary indexes.
Whether it is a MIB-2 `host-resources` storage table, a Brocade Fibre Channel port table, or the existing node-level performance data and interface resource types, {page-component-title} uses the custom resource type to collect and display the data.

[[resourcetype-def]]
== Create a resourceType definition

The process to create a custom resourceType definition is the same as configuring your data collection settings, with only a few small differences.
First, you must make sure that a resourceType is defined for it through *Admin -> Manage SNMP Data Collection Config* (the underlying schema is shown below).

For the MIB-2 host resources storage table, {page-component-title} uses the following definition:

.resourceType definition for the MIB-2 host resources storage table
[source, xml]
----
<resourceType name="hrStorageIndex" label="Storage (MIB-2 Host Resources)">
  <persistenceSelectorStrategy class="org.opennms.netmgt.collectd.PersistAllSelectorStrategy"/>
  <storageStrategy class="org.opennms.netmgt.dao.support.IndexStorageStrategy"/>
</resourceType>
----

=== Name attribute

The name attribute ("hrStorageIndex" in the example above) is not magical in any way; it does not need to correlate to a MIB that OpenNMS has knowledge of.
Other parts of the SNMP data collection config and `snmp-graph.properties` use this attribute to refer to the custom resource type.

To ensure that all resource type data stays separate, all RRD data goes into a directory based on this attribute.
For example, for node 1, all data for the example resource type goes into `$\{OPENNMS_HOME}/share/rrd/snmp/1/hrStorageIndex`.

The length of the index does not matter; this facility should work to collect from multiply indexed tables such as `tcpConnTable`.

=== Label attribute

The label attribute ("Storage (MIB-2 Host Resources)" in the example above) provides a user-friendly label in the web UI when listing this resource type.

=== Storage strategy classes

The `persistenceSelectorStrategy` and `storageStrategy` attributes define the classes used to decide whether data for this resource type should be persisted (written to the disk), and, if so, how the data is written to the disk.
The classes in the example above are the usual ones, but, for more flexibility, you can use the  xref:deep-dive/performance-data-collection/resource-types.adoc#siblingcolumnstoragestrategy[SiblingColumnStorageStrategy] or the xref:deep-dive/performance-data-collection/resource-types.adoc#persistregexselectorstrategy[PersistRegexSelectorStrategy].

[[group-def]]
== Create group and mibObj definitions

You can create the `group` and `mibObj` elements as you normally would, but with two key differences:

* Set the `ifType` attribute for the group element to "all".
Without this, the data will be incorrectly assumed to be node-level data (not indexed).
* Set the `instance` attribute on the `mibObj` elements to be the resource type's name.
In the example above, this would be `hrStorageIndex`.

This code snippet shows what data is collected for the `hrStorageIndex` resource type:

[source, xml]
----
<group name="mib2-host-resources-storage" ifType="all">
  <mibObj oid=".1.3.6.1.2.1.25.2.3.1.3" instance="hrStorageIndex" alias="hrStorageDescr" type="string" />
  <mibObj oid=".1.3.6.1.2.1.25.2.3.1.4" instance="hrStorageIndex" alias="hrStorageAllocUnits" type="gauge" />
  <mibObj oid=".1.3.6.1.2.1.25.2.3.1.5" instance="hrStorageIndex" alias="hrStorageSize" type="gauge" />
  <mibObj oid=".1.3.6.1.2.1.25.2.3.1.6" instance="hrStorageIndex" alias="hrStorageUsed" type="gauge" />
</group>
----

[[system-def]]
== Add the group to a system definition

{page-component-title} needs to be able to map a remote SNMP agent's system object ID to a set of data collection groups.
This ensures that {page-component-title} knows what it should gather for different types of SNMP agents.

You must add any newly created collection groups to one or more system definitions through *Admin -> Manage SNMP Data Collection Config*.
Otherwise, {page-component-title} will not collect data for that collection group.

This code snippet shows that the group for `mib2-host-resources-storage` was added to the `Net-SNMP` definition, which matches any agent that has a system object ID that begins with `.1.3.6.1.4.8072.3.`:

[source, xml]
----
<systemDef name="Net-SNMP">
  <sysoidMask>.1.3.6.1.4.1.8072.3.</sysoidMask>
  <collect>
    <includeGroup>mib2-host-resources-storage</includeGroup>
    <includeGroup>mib2-host-resources-system</includeGroup>
    <includeGroup>mib2-host-resources-memory</includeGroup>
    <includeGroup>net-snmp-disk</includeGroup>
    <includeGroup>ucd-loadavg</includeGroup>
    <includeGroup>ucd-memory</includeGroup>
    <includeGroup>ucd-sysstat</includeGroup>
  </collect>
</systemDef>
----

[[report-snmp-graph]]
== Create a report in snmp-graph.properties

Finally, you can create a report in `snmp-graph.properties` like you normally would, with the exception that you must set the type to match the resource type's name.
See xref:deep-dive/performance-data-collection/graphs.adoc[Graphing Metrics] for more information on creating resource graphs.

This code snippet creates a report for `hrStorageIndex` disk utilization data:

[source, properties]
----
report.mib2.storage.usage.name=Storage Utilization (MIB-2 Host Resources)
report.mib2.storage.usage.columns=hrStorageSize, hrStorageUsed, hrStorageAllocUnits
report.mib2.storage.usage.type=hrStorageIndex
report.mib2.storage.usage.command=--title="Storage Utilization" \
   --vertical-label="Bytes" \
   DEF:total={rrd1}:hrStorageSize:AVERAGE \
   DEF:used={rrd2}:hrStorageUsed:AVERAGE \
   DEF:units={rrd3}:hrStorageAllocUnits:AVERAGE \
   CDEF:totalBytes=total,units,* \
   CDEF:usedBytes=total,used,-,units,* \
   LINE2:totalBytes#0000ff:"Total" \
   GPRINT:totalBytes:AVERAGE:" Avg  \\: %8.2lf %s" \
   GPRINT:totalBytes:MIN:"Min  \\: %8.2lf %s" \
   GPRINT:totalBytes:MAX:"Max  \\: %8.2lf %s\\n" \
   AREA:usedBytes#ff0000:"Used " \
   GPRINT:usedBytes:AVERAGE:" Avg  \\: %8.2lf %s" \
   GPRINT:usedBytes:MIN:"Min  \\: %8.2lf %s" \
   GPRINT:usedBytes:MAX:"Max  \\: %8.2lf %s\\n"
----

You must make sure that you add your new report to the `reports` parameter in the same file; otherwise, the graphing system will not add it as an available report.
In the example above, the report name is `mib2.storage.usage`.

.Example of `reports` parameter, which configures available reports
[source, properties]
----
reports=mib2.bits, mib2.percentdiscards, mib2.percenterrors, \
...
mib2.storage.usage, \
...
----
