Adding a conntrack input plugin
- Collects conntrack stats from the configured directories and files. Applying PR feedback: - Rebased onto master - Updated README/CHANGELOG - Limited lines to 80 chars - Improved plugin docs and README - added a dummy notlinux build file Fixed up CHANGELOG and README after rebase closes #1164
This commit is contained in:
parent
3af65e7abb
commit
0fb2d2ffae
|
@ -19,6 +19,7 @@ time before a new metric is included by the plugin.
|
||||||
|
|
||||||
### Features
|
### Features
|
||||||
|
|
||||||
|
- [#1164](https://github.com/influxdata/telegraf/pull/1164): conntrack input plugin. Thanks @robinpercy!
|
||||||
- [#1247](https://github.com/influxdata/telegraf/pull/1247): rollbar input plugin. Thanks @francois2metz and @cduez!
|
- [#1247](https://github.com/influxdata/telegraf/pull/1247): rollbar input plugin. Thanks @francois2metz and @cduez!
|
||||||
- [#1208](https://github.com/influxdata/telegraf/pull/1208): Standardized AWS credentials evaluation & wildcard CloudWatch dimensions. Thanks @johnrengelman!
|
- [#1208](https://github.com/influxdata/telegraf/pull/1208): Standardized AWS credentials evaluation & wildcard CloudWatch dimensions. Thanks @johnrengelman!
|
||||||
- [#1264](https://github.com/influxdata/telegraf/pull/1264): Add SSL config options to http_response plugin.
|
- [#1264](https://github.com/influxdata/telegraf/pull/1264): Add SSL config options to http_response plugin.
|
||||||
|
|
|
@ -145,6 +145,7 @@ Currently implemented sources:
|
||||||
* [cassandra](https://github.com/influxdata/telegraf/tree/master/plugins/inputs/cassandra)
|
* [cassandra](https://github.com/influxdata/telegraf/tree/master/plugins/inputs/cassandra)
|
||||||
* [ceph](https://github.com/influxdata/telegraf/tree/master/plugins/inputs/ceph)
|
* [ceph](https://github.com/influxdata/telegraf/tree/master/plugins/inputs/ceph)
|
||||||
* [chrony](https://github.com/influxdata/telegraf/tree/master/plugins/inputs/chrony)
|
* [chrony](https://github.com/influxdata/telegraf/tree/master/plugins/inputs/chrony)
|
||||||
|
* [conntrack](https://github.com/influxdata/telegraf/tree/master/plugins/inputs/conntrack)
|
||||||
* [couchbase](https://github.com/influxdata/telegraf/tree/master/plugins/inputs/couchbase)
|
* [couchbase](https://github.com/influxdata/telegraf/tree/master/plugins/inputs/couchbase)
|
||||||
* [couchdb](https://github.com/influxdata/telegraf/tree/master/plugins/inputs/couchdb)
|
* [couchdb](https://github.com/influxdata/telegraf/tree/master/plugins/inputs/couchdb)
|
||||||
* [disque](https://github.com/influxdata/telegraf/tree/master/plugins/inputs/disque)
|
* [disque](https://github.com/influxdata/telegraf/tree/master/plugins/inputs/disque)
|
||||||
|
|
|
@ -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,56 @@
|
||||||
|
# Conntrack Plugin
|
||||||
|
|
||||||
|
Collects stats from Netfilter's conntrack-tools.
|
||||||
|
|
||||||
|
The conntrack-tools provide a mechanism for tracking various aspects of
|
||||||
|
network connections as they are processed by netfilter. At runtime,
|
||||||
|
conntrack exposes many of those connection statistics within /proc/sys/net.
|
||||||
|
Depending on your kernel version, these files can be found in either
|
||||||
|
/proc/sys/net/ipv4/netfilter or /proc/sys/net/netfilter and will be
|
||||||
|
prefixed with either ip_ or nf_. This plugin reads the files specified
|
||||||
|
in its configuration and publishes each one as a field, with the prefix
|
||||||
|
normalized to ip_.
|
||||||
|
|
||||||
|
In order to simplify configuration in a heterogeneous environment, a superset
|
||||||
|
of directory and filenames can be specified. Any locations that don't exist
|
||||||
|
will be ignored.
|
||||||
|
|
||||||
|
For more information on conntrack-tools, see the
|
||||||
|
[Netfilter Documentation](http://conntrack-tools.netfilter.org/).
|
||||||
|
|
||||||
|
|
||||||
|
### Configuration:
|
||||||
|
|
||||||
|
```toml
|
||||||
|
# Collects conntrack stats from the configured directories and files.
|
||||||
|
[[inputs.conntrack]]
|
||||||
|
## The following defaults would work with multiple versions of conntrack.
|
||||||
|
## Note the nf_ and ip_ filename prefixes are mutually exclusive across
|
||||||
|
## kernel 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,119 @@
|
||||||
|
// +build linux
|
||||||
|
|
||||||
|
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 = `
|
||||||
|
## The following defaults would work with multiple versions of conntrack.
|
||||||
|
## Note the nf_ and ip_ filename prefixes are mutually exclusive across
|
||||||
|
## kernel 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,3 @@
|
||||||
|
// +build !linux
|
||||||
|
|
||||||
|
package conntrack
|
|
@ -0,0 +1,90 @@
|
||||||
|
// +build linux
|
||||||
|
|
||||||
|
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