Skip to content

Commit

Permalink
Add features from #546
Browse files Browse the repository at this point in the history
  • Loading branch information
titilambert committed Jan 20, 2016
1 parent a24ebc7 commit aba0856
Show file tree
Hide file tree
Showing 3 changed files with 25,800 additions and 69 deletions.
96 changes: 59 additions & 37 deletions plugins/inputs/snmp/snmp.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package snmp

import (
"fmt"
"io/ioutil"
"log"
"net"
Expand Down Expand Up @@ -41,14 +40,18 @@ type Host struct {

type Data struct {
Name string
// OIds
// OID (could be numbers or name)
Oid string
// Unit
Unit string
// SNMP getbulk max repetition
MaxRepetition uint8 `toml:"max_repetition"`
// We want to resolve oid to names oids text file
Snmptranslate bool
// SNMP Instance (default 0)
// (only used with GET request and if
// OID is a name from snmptranslate file)
Instance string
// OID (only number) (used for computation)
rawOid string
}

type Node struct {
Expand All @@ -63,6 +66,8 @@ var initNode = Node{
subnodes: make(map[string]Node),
}

var NameToOid = make(map[string]string)

var sampleConfig = `
# Use 'oids.txt' file to translate oids to names
# To generate 'oids.txt' you need to run:
Expand Down Expand Up @@ -93,25 +98,28 @@ var sampleConfig = `
collect = ["mybulk"]
[[inputs.snmp.get]]
name = "sysservices"
oid = ".1.3.6.1.2.1.1.7.0"
name = "ifnumber"
oid = "ifNumber"
[[inputs.snmp.get]]
name = "sysdescr"
oid = ".1.3.6.1.2.1.1.1.0"
snmptranslate = true
name = "interface_speed"
oid = "ifSpeed"
instance = 0
[[inputs.snmp.get]]
name = "sysuptime"
oid = ".1.3.6.1.2.1.1.3.0"
unit = "seconds"
snmptranslate = true
unit = "second"
[[inputs.snmp.bulk]]
name = "mybulk"
max_repetition = 127
oid = ".1.3.6.1.2.1.1"
snmptranslate = true
[[inputs.snmp.bulk]]
name = "ifoutoctets"
max_repetition = 127
oid = "ifOutOctets"
`

// SampleConfig returns sample configuration message
Expand Down Expand Up @@ -144,10 +152,10 @@ func fillnode(parentNode Node, oid_name string, ids []string) {
}
}

func findnodename(node Node, ids []string) string {
func findnodename(node Node, ids []string) (string, string) {
// ids = ["1", "3", "6", ...]
if len(ids) == 1 {
return node.name
return node.name, ids[0]
}
id, ids := ids[0], ids[1:]
// Get node
Expand All @@ -159,24 +167,25 @@ func findnodename(node Node, ids []string) string {
// Get node name
if node.name != "" && len(ids) == 0 && id == "0" {
// node with instance 0
return node.name
return node.name, "0"
} else if node.name != "" && len(ids) == 0 && id != "0" {
// node with an instance
return node.name + "." + string(id)
return node.name, string(id)
} else if node.name != "" && len(ids) > 0 {
// node with subinstances
return node.name + "." + strings.Join(ids, ".")
return node.name, strings.Join(ids, ".")
}
// return an empty node name
return node.name
return node.name, ""
}

func (s *Snmp) Gather(acc inputs.Accumulator) error {
// Create oid tree
if s.SnmptranslateFile != "" {
if s.SnmptranslateFile != "" && len(initNode.subnodes) == 0 {
data, err := ioutil.ReadFile(s.SnmptranslateFile)
if err != nil {
fmt.Print(err)
log.Printf("Reading SNMPtranslate file error: %s", err)
return err
} else {
for _, line := range strings.Split(string(data), "\n") {
oidsRegEx := regexp.MustCompile(`([^\t]*)\t*([^\t]*)`)
Expand All @@ -185,6 +194,7 @@ func (s *Snmp) Gather(acc inputs.Accumulator) error {
oid_name := oids[1]
oid := oids[2]
fillnode(initNode, oid_name, strings.Split(string(oid), "."))
NameToOid[oid_name] = oid
}
}
}
Expand All @@ -209,12 +219,27 @@ func (s *Snmp) Gather(acc inputs.Accumulator) error {
// Get GET oids
for _, oid := range s.Get {
if oid.Name == oid_name {
if val, ok := NameToOid[oid.Oid]; ok {
// TODO should we add the 0 instance ?
if oid.Instance != "" {
oid.rawOid = "." + val + "." + oid.Instance
} else {
oid.rawOid = "." + val + ".0"
}
} else {
oid.rawOid = oid.Oid
}
host.getOids = append(host.getOids, oid)
}
}
// Get GETBULK oids
for _, oid := range s.Bulk {
if oid.Name == oid_name {
if val, ok := NameToOid[oid.Oid]; ok {
oid.rawOid = "." + val
} else {
oid.rawOid = oid.Oid
}
host.bulkOids = append(host.bulkOids, oid)
}
}
Expand All @@ -239,11 +264,11 @@ func (h *Host) SNMPGet(acc inputs.Accumulator) error {
// Prepare OIDs
oidsList := make(map[string]Data)
for _, oid := range h.getOids {
oidsList[oid.Oid] = oid
oidsList[oid.rawOid] = oid
}
oidsNameList := make([]string, 0, len(oidsList))
for _, oid := range oidsList {
oidsNameList = append(oidsNameList, oid.Oid)
oidsNameList = append(oidsNameList, oid.rawOid)
}

// gosnmp.MAX_OIDS == 60
Expand Down Expand Up @@ -281,11 +306,11 @@ func (h *Host) SNMPBulk(acc inputs.Accumulator) error {
// Prepare OIDs
oidsList := make(map[string]Data)
for _, oid := range h.bulkOids {
oidsList[oid.Oid] = oid
oidsList[oid.rawOid] = oid
}
oidsNameList := make([]string, 0, len(oidsList))
for _, oid := range oidsList {
oidsNameList = append(oidsNameList, oid.Oid)
oidsNameList = append(oidsNameList, oid.rawOid)
}
// TODO Trying to make requests with more than one OID
// to reduce the number of requests
Expand Down Expand Up @@ -379,31 +404,28 @@ func (h *Host) HandleResponse(oids map[string]Data, result *gosnmp.SnmpPacket, a
// Get name and instance
var oid_name string
var instance string
if oid.Snmptranslate {
// Get oidname and instannce from translate file
oidfullname := findnodename(initNode,
strings.Split(string(variable.Name[1:]), "."))
res := strings.SplitN(string(oidfullname), ".", 2)
oid_name = res[0]
if len(res) > 1 {
instance = res[1]
}
}
// Get oidname and instannce from translate file
oid_name, instance = findnodename(initNode,
strings.Split(string(variable.Name[1:]), "."))

if instance != "" {
tags["instance"] = instance
}

// Set name
var field_name string
if oid_name != "" {
// Set fieldname as oid name from translate file
field_name = oid_name
} else if oid.Oid == variable.Name {
field_name = oid.Name
} else {
field_name = variable.Name
// Set fieldname as oid name from inputs.snmp.get section
// Because the result oid is equal to inputs.snmp.get section
field_name = oid.Name
}
tags["host"], _, _ = net.SplitHostPort(h.Address)
fields := make(map[string]interface{})
fields[string(field_name)] = variable.Value

acc.AddFields(field_name, fields, tags)
case gosnmp.NoSuchObject, gosnmp.NoSuchInstance:
// Oid not found
Expand Down
Loading

0 comments on commit aba0856

Please sign in to comment.