Adding a conntrack input plugin
- Collects conntrack stats from the configured directories and files.
This commit is contained in:
parent
3af65e7abb
commit
b6873e3191
|
@ -1575,3 +1575,13 @@
|
||||||
# ## https://github.com/influxdata/telegraf/blob/master/docs/DATA_FORMATS_INPUT.md
|
# ## https://github.com/influxdata/telegraf/blob/master/docs/DATA_FORMATS_INPUT.md
|
||||||
# data_format = "influx"
|
# data_format = "influx"
|
||||||
|
|
||||||
|
# # Collects conntrack stats from the configured directories and files.
|
||||||
|
# [[inputs.conntrack]]
|
||||||
|
# ## The following defaults would work with multiple versions of contrack. Note the nf_ and ip_
|
||||||
|
# ## filename prefixes are mutually exclusive across conntrack versions, as are the directory locations.
|
||||||
|
#
|
||||||
|
# ## Superset of filenames to look for within the conntrack dirs. Missing files will be ignored.
|
||||||
|
# files = ["ip_conntrack_count","ip_conntrack_max","nf_conntrack_count","nf_conntrack_max"]
|
||||||
|
#
|
||||||
|
# ## Directories to search within for the conntrack files above. Missing directrories will be ignored.
|
||||||
|
# dirs = ["/proc/sys/net/ipv4/netfilter","/proc/sys/net/netfilter"]
|
||||||
|
|
|
@ -8,6 +8,7 @@ import (
|
||||||
_ "github.com/influxdata/telegraf/plugins/inputs/ceph"
|
_ "github.com/influxdata/telegraf/plugins/inputs/ceph"
|
||||||
_ "github.com/influxdata/telegraf/plugins/inputs/chrony"
|
_ "github.com/influxdata/telegraf/plugins/inputs/chrony"
|
||||||
_ "github.com/influxdata/telegraf/plugins/inputs/cloudwatch"
|
_ "github.com/influxdata/telegraf/plugins/inputs/cloudwatch"
|
||||||
|
_ "github.com/influxdata/telegraf/plugins/inputs/conntrack"
|
||||||
_ "github.com/influxdata/telegraf/plugins/inputs/couchbase"
|
_ "github.com/influxdata/telegraf/plugins/inputs/couchbase"
|
||||||
_ "github.com/influxdata/telegraf/plugins/inputs/couchdb"
|
_ "github.com/influxdata/telegraf/plugins/inputs/couchdb"
|
||||||
_ "github.com/influxdata/telegraf/plugins/inputs/disque"
|
_ "github.com/influxdata/telegraf/plugins/inputs/disque"
|
||||||
|
|
|
@ -0,0 +1,35 @@
|
||||||
|
# Conntrack Plugin
|
||||||
|
|
||||||
|
Collects conntrack stats from the configured directories and files.
|
||||||
|
|
||||||
|
### Configuration:
|
||||||
|
|
||||||
|
```toml
|
||||||
|
# Collects conntrack stats from the configured directories and files.
|
||||||
|
[[inputs.conntrack]]
|
||||||
|
## The following defaults would work with multiple versions of contrack. Note the nf_ and ip_
|
||||||
|
## filename prefixes are mutually exclusive across conntrack versions, as are the directory locations.
|
||||||
|
|
||||||
|
## Superset of filenames to look for within the conntrack dirs. Missing files will be ignored.
|
||||||
|
files = ["ip_conntrack_count","ip_conntrack_max","nf_conntrack_count","nf_conntrack_max"]
|
||||||
|
|
||||||
|
## Directories to search within for the conntrack files above. Missing directrories will be ignored.
|
||||||
|
dirs = ["/proc/sys/net/ipv4/netfilter","/proc/sys/net/netfilter"]
|
||||||
|
```
|
||||||
|
|
||||||
|
### Measurements & Fields:
|
||||||
|
|
||||||
|
- conntrack
|
||||||
|
- ip_conntrack_count (int, count): the number of entries in the conntrack table
|
||||||
|
- ip_conntrack_max (int, size): the max capacity of the conntrack table
|
||||||
|
|
||||||
|
### Tags:
|
||||||
|
|
||||||
|
This input does not use tags.
|
||||||
|
|
||||||
|
### Example Output:
|
||||||
|
|
||||||
|
```
|
||||||
|
$ ./telegraf -config telegraf.conf -input-filter conntrack -test
|
||||||
|
conntrack,host=myhost ip_conntrack_count=2,ip_conntrack_max=262144 1461620427667995735
|
||||||
|
```
|
|
@ -0,0 +1,112 @@
|
||||||
|
package conntrack
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"io/ioutil"
|
||||||
|
"os"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/influxdata/telegraf"
|
||||||
|
"github.com/influxdata/telegraf/plugins/inputs"
|
||||||
|
"log"
|
||||||
|
"path/filepath"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Conntrack struct {
|
||||||
|
Path string
|
||||||
|
Dirs []string
|
||||||
|
Files []string
|
||||||
|
}
|
||||||
|
|
||||||
|
const (
|
||||||
|
inputName = "conntrack"
|
||||||
|
)
|
||||||
|
|
||||||
|
var dfltDirs = []string{
|
||||||
|
"/proc/sys/net/ipv4/netfilter",
|
||||||
|
"/proc/sys/net/netfilter",
|
||||||
|
}
|
||||||
|
|
||||||
|
var dfltFiles = []string{
|
||||||
|
"ip_conntrack_count",
|
||||||
|
"ip_conntrack_max",
|
||||||
|
"nf_conntrack_count",
|
||||||
|
"nf_conntrack_max",
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Conntrack) setDefaults() {
|
||||||
|
if len(c.Dirs) == 0 {
|
||||||
|
c.Dirs = dfltDirs
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(c.Files) == 0 {
|
||||||
|
c.Files = dfltFiles
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Conntrack) Description() string {
|
||||||
|
return "Collects conntrack stats from the configured directories and files."
|
||||||
|
}
|
||||||
|
|
||||||
|
var sampleConfig = `
|
||||||
|
# Collects conntrack stats from the configured directories and files.
|
||||||
|
[[inputs.conntrack]]
|
||||||
|
## The following defaults would work with multiple versions of contrack. Note the nf_ and ip_
|
||||||
|
## filename prefixes are mutually exclusive across conntrack versions, as are the directory locations.
|
||||||
|
|
||||||
|
## Superset of filenames to look for within the conntrack dirs. Missing files will be ignored.
|
||||||
|
files = ["ip_conntrack_count","ip_conntrack_max","nf_conntrack_count","nf_conntrack_max"]
|
||||||
|
|
||||||
|
## Directories to search within for the conntrack files above. Missing directrories will be ignored.
|
||||||
|
dirs = ["/proc/sys/net/ipv4/netfilter","/proc/sys/net/netfilter"]
|
||||||
|
`
|
||||||
|
|
||||||
|
func (c *Conntrack) SampleConfig() string {
|
||||||
|
return sampleConfig
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Conntrack) Gather(acc telegraf.Accumulator) error {
|
||||||
|
c.setDefaults()
|
||||||
|
|
||||||
|
var metricKey string
|
||||||
|
fields := make(map[string]interface{})
|
||||||
|
|
||||||
|
for _, dir := range c.Dirs {
|
||||||
|
for _, file := range c.Files {
|
||||||
|
// NOTE: no system will have both nf_ and ip_ prefixes, so we're safe to branch on suffix only.
|
||||||
|
parts := strings.SplitN(file, "_", 2)
|
||||||
|
if len(parts) < 2 {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
metricKey = "ip_" + parts[1]
|
||||||
|
|
||||||
|
fName := filepath.Join(dir, file)
|
||||||
|
if _, err := os.Stat(fName); err != nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
contents, err := ioutil.ReadFile(fName)
|
||||||
|
if err != nil {
|
||||||
|
log.Printf("failed to read file '%s': %v", fName, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
v := strings.TrimSpace(string(contents))
|
||||||
|
fields[metricKey], err = strconv.ParseFloat(v, 64)
|
||||||
|
if err != nil {
|
||||||
|
log.Printf("failed to parse metric, expected number but found '%s': %v", v, err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(fields) == 0 {
|
||||||
|
return fmt.Errorf("Conntrack input failed to collect metrics. Is the conntrack kernel module loaded?")
|
||||||
|
}
|
||||||
|
|
||||||
|
acc.AddFields(inputName, fields, nil)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
inputs.Add(inputName, func() telegraf.Input { return &Conntrack{} })
|
||||||
|
}
|
|
@ -0,0 +1,86 @@
|
||||||
|
package conntrack
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/influxdata/telegraf/testutil"
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
"io/ioutil"
|
||||||
|
"os"
|
||||||
|
"path"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func restoreDflts(savedFiles, savedDirs []string) {
|
||||||
|
dfltFiles = savedFiles
|
||||||
|
dfltDirs = savedDirs
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestNoFilesFound(t *testing.T) {
|
||||||
|
defer restoreDflts(dfltFiles, dfltDirs)
|
||||||
|
|
||||||
|
dfltFiles = []string{"baz.txt"}
|
||||||
|
dfltDirs = []string{"./foo/bar"}
|
||||||
|
c := &Conntrack{}
|
||||||
|
acc := &testutil.Accumulator{}
|
||||||
|
err := c.Gather(acc)
|
||||||
|
|
||||||
|
assert.EqualError(t, err, "Conntrack input failed to collect metrics. Is the conntrack kernel module loaded?")
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestDefaultsUsed(t *testing.T) {
|
||||||
|
defer restoreDflts(dfltFiles, dfltDirs)
|
||||||
|
tmpdir, err := ioutil.TempDir("", "tmp1")
|
||||||
|
assert.NoError(t, err)
|
||||||
|
defer os.Remove(tmpdir)
|
||||||
|
|
||||||
|
tmpFile, err := ioutil.TempFile(tmpdir, "ip_conntrack_count")
|
||||||
|
assert.NoError(t, err)
|
||||||
|
|
||||||
|
dfltDirs = []string{tmpdir}
|
||||||
|
fname := path.Base(tmpFile.Name())
|
||||||
|
dfltFiles = []string{fname}
|
||||||
|
|
||||||
|
count := 1234321
|
||||||
|
ioutil.WriteFile(tmpFile.Name(), []byte(strconv.Itoa(count)), 0660)
|
||||||
|
c := &Conntrack{}
|
||||||
|
acc := &testutil.Accumulator{}
|
||||||
|
|
||||||
|
c.Gather(acc)
|
||||||
|
acc.AssertContainsFields(t, inputName, map[string]interface{}{fname: float64(count)})
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestConfigsUsed(t *testing.T) {
|
||||||
|
defer restoreDflts(dfltFiles, dfltDirs)
|
||||||
|
tmpdir, err := ioutil.TempDir("", "tmp1")
|
||||||
|
assert.NoError(t, err)
|
||||||
|
defer os.Remove(tmpdir)
|
||||||
|
|
||||||
|
cntFile, err := ioutil.TempFile(tmpdir, "nf_conntrack_count")
|
||||||
|
maxFile, err := ioutil.TempFile(tmpdir, "nf_conntrack_max")
|
||||||
|
assert.NoError(t, err)
|
||||||
|
|
||||||
|
dfltDirs = []string{tmpdir}
|
||||||
|
cntFname := path.Base(cntFile.Name())
|
||||||
|
maxFname := path.Base(maxFile.Name())
|
||||||
|
dfltFiles = []string{cntFname, maxFname}
|
||||||
|
|
||||||
|
count := 1234321
|
||||||
|
max := 9999999
|
||||||
|
ioutil.WriteFile(cntFile.Name(), []byte(strconv.Itoa(count)), 0660)
|
||||||
|
ioutil.WriteFile(maxFile.Name(), []byte(strconv.Itoa(max)), 0660)
|
||||||
|
c := &Conntrack{}
|
||||||
|
acc := &testutil.Accumulator{}
|
||||||
|
|
||||||
|
c.Gather(acc)
|
||||||
|
|
||||||
|
fix := func(s string) string {
|
||||||
|
return strings.Replace(s, "nf_", "ip_", 1)
|
||||||
|
}
|
||||||
|
|
||||||
|
acc.AssertContainsFields(t, inputName,
|
||||||
|
map[string]interface{}{
|
||||||
|
fix(cntFname): float64(count),
|
||||||
|
fix(maxFname): float64(max),
|
||||||
|
})
|
||||||
|
}
|
Loading…
Reference in New Issue