From 055ef168ae0f8d5f8cb35cec748991bc60553507 Mon Sep 17 00:00:00 2001 From: Patrick Hemmer Date: Sat, 17 Sep 2016 23:08:00 -0400 Subject: [PATCH] add oid_index_suffix to snmp plugin --- CHANGELOG.md | 1 + plugins/inputs/snmp/README.md | 3 ++ plugins/inputs/snmp/snmp.go | 16 +++++++++-- plugins/inputs/snmp/snmp_test.go | 47 +++++++++++++++++++++----------- 4 files changed, 49 insertions(+), 18 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2def3ae6d3d31..d6932142772ea 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -22,6 +22,7 @@ - [#1699](https://github.com/influxdata/telegraf/pull/1699): Add database blacklist option for Postgresql - [#1791](https://github.com/influxdata/telegraf/pull/1791): Add Docker container state metrics to Docker input plugin output - [#1755](https://github.com/influxdata/telegraf/issues/1755): Add support to SNMP for IP & MAC address conversion. +- [#1729](https://github.com/influxdata/telegraf/issues/1729): Add support to SNMP for OID index suffixes. ### Bugfixes diff --git a/plugins/inputs/snmp/README.md b/plugins/inputs/snmp/README.md index c650967691456..f8dbc7a31968c 100644 --- a/plugins/inputs/snmp/README.md +++ b/plugins/inputs/snmp/README.md @@ -136,6 +136,9 @@ Output measurement name. * `oid`: OID to get. May be a numeric or textual OID. +* `oid_index_suffix`: +The OID sub-identifier to strip off so that the index can be matched against other fields in the table. + * `name`: Output field/tag name. If not specified, it defaults to the value of `oid`. If `oid` is numeric, an attempt to translate the numeric OID into a texual OID will be made. diff --git a/plugins/inputs/snmp/snmp.go b/plugins/inputs/snmp/snmp.go index e3189df6d79a8..254a454a27556 100644 --- a/plugins/inputs/snmp/snmp.go +++ b/plugins/inputs/snmp/snmp.go @@ -258,6 +258,8 @@ type Field struct { // off the OID prefix, and use the remainder as the index. For multiple fields // to show up in the same row, they must share the same index. Oid string + // OidIndexSuffix is the trailing sub-identifier on a table record OID that will be stripped off to get the record's index. + OidIndexSuffix string // IsTag controls whether this OID is output as a tag or a value. IsTag bool // Conversion controls any type conversion that is done on the value. @@ -460,18 +462,28 @@ func (t Table) Build(gs snmpConnection, walk bool) (*RTable, error) { if err != nil { return nil, Errorf(err, "converting %q", ent.Value) } - ifv[ent.Name[len(oid):]] = fv + ifv[""] = fv } } else { err := gs.Walk(oid, func(ent gosnmp.SnmpPDU) error { if len(ent.Name) <= len(oid) || ent.Name[:len(oid)+1] != oid+"." { return NestedError{} // break the walk } + + idx := ent.Name[len(oid):] + if f.OidIndexSuffix != "" { + if !strings.HasSuffix(idx, f.OidIndexSuffix) { + // this entry doesn't match our OidIndexSuffix. skip it + return nil + } + idx = idx[:len(idx)-len(f.OidIndexSuffix)] + } + fv, err := fieldConvert(f.Conversion, ent.Value) if err != nil { return Errorf(err, "converting %q", ent.Value) } - ifv[ent.Name[len(oid):]] = fv + ifv[idx] = fv return nil }) if err != nil { diff --git a/plugins/inputs/snmp/snmp_test.go b/plugins/inputs/snmp/snmp_test.go index 0cbb6e6b362c9..0272253c88e66 100644 --- a/plugins/inputs/snmp/snmp_test.go +++ b/plugins/inputs/snmp/snmp_test.go @@ -60,18 +60,20 @@ func (tsc *testSNMPConnection) Walk(oid string, wf gosnmp.WalkFunc) error { var tsc = &testSNMPConnection{ host: "tsc", values: map[string]interface{}{ - ".1.0.0.0.1.1.0": "foo", - ".1.0.0.0.1.1.1": []byte("bar"), - ".1.0.0.0.1.102": "bad", - ".1.0.0.0.1.2.0": 1, - ".1.0.0.0.1.2.1": 2, - ".1.0.0.0.1.3.0": "0.123", - ".1.0.0.0.1.3.1": "0.456", - ".1.0.0.0.1.3.2": "9.999", - ".1.0.0.0.1.4.0": 123456, - ".1.0.0.1.1": "baz", - ".1.0.0.1.2": 234, - ".1.0.0.1.3": []byte("byte slice"), + ".1.0.0.0.1.1.0": "foo", + ".1.0.0.0.1.1.1": []byte("bar"), + ".1.0.0.0.1.102": "bad", + ".1.0.0.0.1.2.0": 1, + ".1.0.0.0.1.2.1": 2, + ".1.0.0.0.1.3.0": "0.123", + ".1.0.0.0.1.3.1": "0.456", + ".1.0.0.0.1.3.2": "9.999", + ".1.0.0.0.1.4.0": 123456, + ".1.0.0.1.1": "baz", + ".1.0.0.1.2": 234, + ".1.0.0.1.3": []byte("byte slice"), + ".1.0.0.2.1.5.0.9.9": 11, + ".1.0.0.2.1.5.1.9.9": 22, }, } @@ -371,6 +373,11 @@ func TestTableBuild_walk(t *testing.T) { Oid: ".1.0.0.0.1.3", Conversion: "float", }, + { + Name: "myfield4", + Oid: ".1.0.0.2.1.5", + OidIndexSuffix: ".9.9", + }, }, } @@ -379,12 +386,20 @@ func TestTableBuild_walk(t *testing.T) { assert.Equal(t, tb.Name, "mytable") rtr1 := RTableRow{ - Tags: map[string]string{"myfield1": "foo"}, - Fields: map[string]interface{}{"myfield2": 1, "myfield3": float64(0.123)}, + Tags: map[string]string{"myfield1": "foo"}, + Fields: map[string]interface{}{ + "myfield2": 1, + "myfield3": float64(0.123), + "myfield4": 11, + }, } rtr2 := RTableRow{ - Tags: map[string]string{"myfield1": "bar"}, - Fields: map[string]interface{}{"myfield2": 2, "myfield3": float64(0.456)}, + Tags: map[string]string{"myfield1": "bar"}, + Fields: map[string]interface{}{ + "myfield2": 2, + "myfield3": float64(0.456), + "myfield4": 22, + }, } assert.Len(t, tb.Rows, 2) assert.Contains(t, tb.Rows, rtr1)