WIP adding snmptranslate MIB-lookup integration
This commit is contained in:
parent
1357525f0d
commit
de7c35280b
|
@ -1379,7 +1379,7 @@
|
||||||
|
|
||||||
# # Retrieves SNMP values from remote agents
|
# # Retrieves SNMP values from remote agents
|
||||||
# [[inputs.snmp]]
|
# [[inputs.snmp]]
|
||||||
# agents = [ "127.0.0.1:161" ]
|
# agents = ["127.0.0.1:161"]
|
||||||
# version = 2 # Values: 1, 2, or 3
|
# version = 2 # Values: 1, 2, or 3
|
||||||
#
|
#
|
||||||
# ## SNMPv1 & SNMPv2 parameters
|
# ## SNMPv1 & SNMPv2 parameters
|
||||||
|
@ -1399,6 +1399,8 @@
|
||||||
#
|
#
|
||||||
# ## measurement name
|
# ## measurement name
|
||||||
# name = "system"
|
# name = "system"
|
||||||
|
# ## SNMP fields are gotten by using an "snmpget" request. If a name is not
|
||||||
|
# ## specified, we attempt to use snmptranslate on the OID to get the MIB name.
|
||||||
# [[inputs.snmp.field]]
|
# [[inputs.snmp.field]]
|
||||||
# name = "hostname"
|
# name = "hostname"
|
||||||
# oid = ".1.2.3.0.1.1"
|
# oid = ".1.2.3.0.1.1"
|
||||||
|
@ -1406,13 +1408,14 @@
|
||||||
# name = "uptime"
|
# name = "uptime"
|
||||||
# oid = ".1.2.3.0.1.200"
|
# oid = ".1.2.3.0.1.200"
|
||||||
# [[inputs.snmp.field]]
|
# [[inputs.snmp.field]]
|
||||||
# name = "load"
|
|
||||||
# oid = ".1.2.3.0.1.201"
|
# oid = ".1.2.3.0.1.201"
|
||||||
#
|
#
|
||||||
# [[inputs.snmp.table]]
|
# [[inputs.snmp.table]]
|
||||||
# # measurement name
|
# ## measurement name
|
||||||
# name = "remote_servers"
|
# name = "remote_servers"
|
||||||
# inherit_tags = [ "hostname" ]
|
# inherit_tags = ["hostname"]
|
||||||
|
# ## SNMP table fields must be specified individually. If the table field has
|
||||||
|
# ## multiple rows, they will all be gotten.
|
||||||
# [[inputs.snmp.table.field]]
|
# [[inputs.snmp.table.field]]
|
||||||
# name = "server"
|
# name = "server"
|
||||||
# oid = ".1.2.3.0.0.0"
|
# oid = ".1.2.3.0.0.0"
|
||||||
|
|
|
@ -4,11 +4,13 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"math"
|
"math"
|
||||||
"net"
|
"net"
|
||||||
|
"os/exec"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/influxdata/telegraf"
|
"github.com/influxdata/telegraf"
|
||||||
|
"github.com/influxdata/telegraf/internal"
|
||||||
"github.com/influxdata/telegraf/plugins/inputs"
|
"github.com/influxdata/telegraf/plugins/inputs"
|
||||||
|
|
||||||
"github.com/soniah/gosnmp"
|
"github.com/soniah/gosnmp"
|
||||||
|
@ -16,7 +18,7 @@ import (
|
||||||
|
|
||||||
const description = `Retrieves SNMP values from remote agents`
|
const description = `Retrieves SNMP values from remote agents`
|
||||||
const sampleConfig = `
|
const sampleConfig = `
|
||||||
agents = [ "127.0.0.1:161" ]
|
agents = ["127.0.0.1:161"]
|
||||||
version = 2 # Values: 1, 2, or 3
|
version = 2 # Values: 1, 2, or 3
|
||||||
|
|
||||||
## SNMPv1 & SNMPv2 parameters
|
## SNMPv1 & SNMPv2 parameters
|
||||||
|
@ -36,6 +38,8 @@ const sampleConfig = `
|
||||||
|
|
||||||
## measurement name
|
## measurement name
|
||||||
name = "system"
|
name = "system"
|
||||||
|
## SNMP fields are gotten by using an "snmpget" request. If a name is not
|
||||||
|
## specified, we attempt to use snmptranslate on the OID to get the MIB name.
|
||||||
[[inputs.snmp.field]]
|
[[inputs.snmp.field]]
|
||||||
name = "hostname"
|
name = "hostname"
|
||||||
oid = ".1.2.3.0.1.1"
|
oid = ".1.2.3.0.1.1"
|
||||||
|
@ -43,13 +47,14 @@ const sampleConfig = `
|
||||||
name = "uptime"
|
name = "uptime"
|
||||||
oid = ".1.2.3.0.1.200"
|
oid = ".1.2.3.0.1.200"
|
||||||
[[inputs.snmp.field]]
|
[[inputs.snmp.field]]
|
||||||
name = "load"
|
|
||||||
oid = ".1.2.3.0.1.201"
|
oid = ".1.2.3.0.1.201"
|
||||||
|
|
||||||
[[inputs.snmp.table]]
|
[[inputs.snmp.table]]
|
||||||
# measurement name
|
## measurement name
|
||||||
name = "remote_servers"
|
name = "remote_servers"
|
||||||
inherit_tags = [ "hostname" ]
|
inherit_tags = ["hostname"]
|
||||||
|
## SNMP table fields must be specified individually. If the table field has
|
||||||
|
## multiple rows, they will all be gotten.
|
||||||
[[inputs.snmp.table.field]]
|
[[inputs.snmp.table.field]]
|
||||||
name = "server"
|
name = "server"
|
||||||
oid = ".1.2.3.0.0.0"
|
oid = ".1.2.3.0.0.0"
|
||||||
|
@ -102,6 +107,8 @@ type Snmp struct {
|
||||||
Fields []Field `toml:"field"`
|
Fields []Field `toml:"field"`
|
||||||
|
|
||||||
connectionCache map[string]snmpConnection
|
connectionCache map[string]snmpConnection
|
||||||
|
|
||||||
|
inited bool
|
||||||
}
|
}
|
||||||
|
|
||||||
// Table holds the configuration for a SNMP table.
|
// Table holds the configuration for a SNMP table.
|
||||||
|
@ -189,15 +196,6 @@ func Errorf(err error, msg string, format ...interface{}) error {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func init() {
|
|
||||||
inputs.Add("snmp", func() telegraf.Input {
|
|
||||||
return &Snmp{
|
|
||||||
Retries: 5,
|
|
||||||
MaxRepetitions: 50,
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// SampleConfig returns the default configuration of the input.
|
// SampleConfig returns the default configuration of the input.
|
||||||
func (s *Snmp) SampleConfig() string {
|
func (s *Snmp) SampleConfig() string {
|
||||||
return sampleConfig
|
return sampleConfig
|
||||||
|
@ -212,6 +210,10 @@ func (s *Snmp) Description() string {
|
||||||
// Any error encountered does not halt the process. The errors are accumulated
|
// Any error encountered does not halt the process. The errors are accumulated
|
||||||
// and returned at the end.
|
// and returned at the end.
|
||||||
func (s *Snmp) Gather(acc telegraf.Accumulator) error {
|
func (s *Snmp) Gather(acc telegraf.Accumulator) error {
|
||||||
|
if !s.inited {
|
||||||
|
s.initOidNames()
|
||||||
|
}
|
||||||
|
s.inited = true
|
||||||
var errs Errors
|
var errs Errors
|
||||||
for _, agent := range s.Agents {
|
for _, agent := range s.Agents {
|
||||||
gs, err := s.getConnection(agent)
|
gs, err := s.getConnection(agent)
|
||||||
|
@ -244,7 +246,52 @@ func (s *Snmp) Gather(acc telegraf.Accumulator) error {
|
||||||
return errs
|
return errs
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Snmp) gatherTable(acc telegraf.Accumulator, gs snmpConnection, t Table, topTags map[string]string, walk bool) error {
|
// initOidNames loops through each [[inputs.snmp.field]] defined.
|
||||||
|
// If the field doesn't have a 'name' defined, it will attempt to use
|
||||||
|
// snmptranslate to get a name for the OID. If snmptranslate doesn't return a
|
||||||
|
// name, or snmptranslate is not available, then use the OID as the name.
|
||||||
|
func (s *Snmp) initOidNames() {
|
||||||
|
bin, _ := exec.LookPath("snmptranslate")
|
||||||
|
|
||||||
|
// Lookup names for each OID defined as a "field"
|
||||||
|
for i, field := range s.Fields {
|
||||||
|
if field.Name != "" {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
s.Fields[i].Name = lookupOidName(bin, field.Oid)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Lookup names for each OID defined as a "table.field"
|
||||||
|
for i, table := range s.Tables {
|
||||||
|
for j, field := range table.Fields {
|
||||||
|
if field.Name != "" {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
s.Tables[i].Fields[j].Name = lookupOidName(bin, field.Oid)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func lookupOidName(bin, oid string) string {
|
||||||
|
name := oid
|
||||||
|
if bin != "" {
|
||||||
|
out, err := internal.CombinedOutputTimeout(
|
||||||
|
exec.Command(bin, "-Os", oid),
|
||||||
|
time.Millisecond*250)
|
||||||
|
if err == nil && len(out) > 0 {
|
||||||
|
name = strings.TrimSpace(string(out))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return name
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Snmp) gatherTable(
|
||||||
|
acc telegraf.Accumulator,
|
||||||
|
gs snmpConnection,
|
||||||
|
t Table,
|
||||||
|
topTags map[string]string,
|
||||||
|
walk bool,
|
||||||
|
) error {
|
||||||
rt, err := t.Build(gs, walk)
|
rt, err := t.Build(gs, walk)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
@ -296,7 +343,6 @@ func (t Table) Build(gs snmpConnection, walk bool) (*RTable, error) {
|
||||||
|
|
||||||
// ifv contains a mapping of table OID index to field value
|
// ifv contains a mapping of table OID index to field value
|
||||||
ifv := map[string]interface{}{}
|
ifv := map[string]interface{}{}
|
||||||
|
|
||||||
if !walk {
|
if !walk {
|
||||||
// This is used when fetching non-table fields. Fields configured a the top
|
// This is used when fetching non-table fields. Fields configured a the top
|
||||||
// scope of the plugin.
|
// scope of the plugin.
|
||||||
|
@ -622,3 +668,12 @@ func fieldConvert(conv string, v interface{}) interface{} {
|
||||||
|
|
||||||
return v
|
return v
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
inputs.Add("snmp", func() telegraf.Input {
|
||||||
|
return &Snmp{
|
||||||
|
Retries: 5,
|
||||||
|
MaxRepetitions: 50,
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
|
@ -93,7 +93,7 @@ func TestSampleConfig(t *testing.T) {
|
||||||
Fields: []Field{
|
Fields: []Field{
|
||||||
{Name: "hostname", Oid: ".1.2.3.0.1.1"},
|
{Name: "hostname", Oid: ".1.2.3.0.1.1"},
|
||||||
{Name: "uptime", Oid: ".1.2.3.0.1.200"},
|
{Name: "uptime", Oid: ".1.2.3.0.1.200"},
|
||||||
{Name: "load", Oid: ".1.2.3.0.1.201"},
|
{Name: "", Oid: ".1.2.3.0.1.201"},
|
||||||
},
|
},
|
||||||
Tables: []Table{
|
Tables: []Table{
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in New Issue