Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Ethtool Input Plugin (#5864) #5865

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions Gopkg.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 4 additions & 0 deletions Gopkg.toml
Original file line number Diff line number Diff line change
Expand Up @@ -301,3 +301,7 @@
[[constraint]]
name = "gopkg.in/ldap.v3"
version = "3.1.0"

[[constraint]]
name = "github.com/safchain/ethtool"
revision = "42ed695e3de80b9d695f280295fd7994639f209d"
1 change: 1 addition & 0 deletions plugins/inputs/all/all.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ import (
_ "github.com/influxdata/telegraf/plugins/inputs/dovecot"
_ "github.com/influxdata/telegraf/plugins/inputs/ecs"
_ "github.com/influxdata/telegraf/plugins/inputs/elasticsearch"
_ "github.com/influxdata/telegraf/plugins/inputs/ethtool"
_ "github.com/influxdata/telegraf/plugins/inputs/exec"
_ "github.com/influxdata/telegraf/plugins/inputs/fail2ban"
_ "github.com/influxdata/telegraf/plugins/inputs/fibaro"
Expand Down
33 changes: 33 additions & 0 deletions plugins/inputs/ethtool/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
# Ethtool Input Plugin

The ethtool input plugin pulls ethernet device stats. Fields pulled will depend on the network device and driver

### Configuration:

```toml
# Returns ethtool statistics for given interfaces
[[inputs.ethtool]]
## List of interfaces to pull metrics for
# interface_include = ["eth0"]

## List of interfaces to ignore when pulling metrics.
# interface_exclude = ["eth1"]
```

Interfaces can be included or ignored using

- `interface_include`
- `interface_exclude`

Note that loopback interfaces will be automatically ignored

### Metrics:

Metrics are dependant on the network device and driver

### Example Output:

```
ethtool,driver=igb,host=test01,interface=mgmt0 tx_queue_1_packets=280782i,rx_queue_5_csum_err=0i,tx_queue_4_restart=0i,tx_multicast=7i,tx_queue_1_bytes=39674885i,rx_queue_2_alloc_failed=0i,tx_queue_5_packets=173970i,tx_single_coll_ok=0i,rx_queue_1_drops=0i,tx_queue_2_restart=0i,tx_aborted_errors=0i,rx_queue_6_csum_err=0i,tx_queue_5_restart=0i,tx_queue_4_bytes=64810835i,tx_abort_late_coll=0i,tx_queue_4_packets=109102i,os2bmc_tx_by_bmc=0i,tx_bytes=427527435i,tx_queue_7_packets=66665i,dropped_smbus=0i,rx_queue_0_csum_err=0i,tx_flow_control_xoff=0i,rx_packets=25926536i,rx_queue_7_csum_err=0i,rx_queue_3_bytes=84326060i,rx_multicast=83771i,rx_queue_4_alloc_failed=0i,rx_queue_3_drops=0i,rx_queue_3_csum_err=0i,rx_errors=0i,tx_errors=0i,tx_queue_6_packets=183236i,rx_broadcast=24378893i,rx_queue_7_packets=88680i,tx_dropped=0i,rx_frame_errors=0i,tx_queue_3_packets=161045i,tx_packets=1257017i,rx_queue_1_csum_err=0i,tx_window_errors=0i,tx_dma_out_of_sync=0i,rx_length_errors=0i,rx_queue_5_drops=0i,tx_timeout_count=0i,rx_queue_4_csum_err=0i,rx_flow_control_xon=0i,tx_heartbeat_errors=0i,tx_flow_control_xon=0i,collisions=0i,tx_queue_0_bytes=29465801i,rx_queue_6_drops=0i,rx_queue_0_alloc_failed=0i,tx_queue_1_restart=0i,rx_queue_0_drops=0i,tx_broadcast=9i,tx_carrier_errors=0i,tx_queue_7_bytes=13777515i,tx_queue_7_restart=0i,rx_queue_5_bytes=50732006i,rx_queue_7_bytes=35744457i,tx_deferred_ok=0i,tx_multi_coll_ok=0i,rx_crc_errors=0i,rx_fifo_errors=0i,rx_queue_6_alloc_failed=0i,tx_queue_2_packets=175206i,tx_queue_0_packets=107011i,rx_queue_4_bytes=201364548i,rx_queue_6_packets=372573i,os2bmc_rx_by_host=0i,multicast=83771i,rx_queue_4_drops=0i,rx_queue_5_packets=130535i,rx_queue_6_bytes=139488035i,tx_fifo_errors=0i,tx_queue_5_bytes=84899130i,rx_queue_0_packets=24529563i,rx_queue_3_alloc_failed=0i,rx_queue_7_drops=0i,tx_queue_6_bytes=96288614i,tx_queue_2_bytes=22132949i,tx_tcp_seg_failed=0i,rx_queue_1_bytes=246703840i,rx_queue_0_bytes=1506870738i,tx_queue_0_restart=0i,rx_queue_2_bytes=111344804i,tx_tcp_seg_good=0i,tx_queue_3_restart=0i,rx_no_buffer_count=0i,rx_smbus=0i,rx_queue_1_packets=273865i,rx_over_errors=0i,os2bmc_tx_by_host=0i,rx_queue_1_alloc_failed=0i,rx_queue_7_alloc_failed=0i,rx_short_length_errors=0i,tx_hwtstamp_timeouts=0i,tx_queue_6_restart=0i,rx_queue_2_packets=207136i,tx_queue_3_bytes=70391970i,rx_queue_3_packets=112007i,rx_queue_4_packets=212177i,tx_smbus=0i,rx_long_byte_count=2480280632i,rx_queue_2_csum_err=0i,rx_missed_errors=0i,rx_bytes=2480280632i,rx_queue_5_alloc_failed=0i,rx_queue_2_drops=0i,os2bmc_rx_by_bmc=0i,rx_align_errors=0i,rx_long_length_errors=0i,rx_hwtstamp_cleared=0i,rx_flow_control_xoff=0i 1564658080000000000
ethtool,driver=igb,host=test02,interface=mgmt0 rx_queue_2_bytes=111344804i,tx_queue_3_bytes=70439858i,multicast=83771i,rx_broadcast=24378975i,tx_queue_0_packets=107011i,rx_queue_6_alloc_failed=0i,rx_queue_6_drops=0i,rx_hwtstamp_cleared=0i,tx_window_errors=0i,tx_tcp_seg_good=0i,rx_queue_1_drops=0i,tx_queue_1_restart=0i,rx_queue_7_csum_err=0i,rx_no_buffer_count=0i,tx_queue_1_bytes=39675245i,tx_queue_5_bytes=84899130i,tx_broadcast=9i,rx_queue_1_csum_err=0i,tx_flow_control_xoff=0i,rx_queue_6_csum_err=0i,tx_timeout_count=0i,os2bmc_tx_by_bmc=0i,rx_queue_6_packets=372577i,rx_queue_0_alloc_failed=0i,tx_flow_control_xon=0i,rx_queue_2_drops=0i,tx_queue_2_packets=175206i,rx_queue_3_csum_err=0i,tx_abort_late_coll=0i,tx_queue_5_restart=0i,tx_dropped=0i,rx_queue_2_alloc_failed=0i,tx_multi_coll_ok=0i,rx_queue_1_packets=273865i,rx_flow_control_xon=0i,tx_single_coll_ok=0i,rx_length_errors=0i,rx_queue_7_bytes=35744457i,rx_queue_4_alloc_failed=0i,rx_queue_6_bytes=139488395i,rx_queue_2_csum_err=0i,rx_long_byte_count=2480288216i,rx_queue_1_alloc_failed=0i,tx_queue_0_restart=0i,rx_queue_0_csum_err=0i,tx_queue_2_bytes=22132949i,rx_queue_5_drops=0i,tx_dma_out_of_sync=0i,rx_queue_3_drops=0i,rx_queue_4_packets=212177i,tx_queue_6_restart=0i,rx_packets=25926650i,rx_queue_7_packets=88680i,rx_frame_errors=0i,rx_queue_3_bytes=84326060i,rx_short_length_errors=0i,tx_queue_7_bytes=13777515i,rx_queue_3_alloc_failed=0i,tx_queue_6_packets=183236i,rx_queue_0_drops=0i,rx_multicast=83771i,rx_queue_2_packets=207136i,rx_queue_5_csum_err=0i,rx_queue_5_packets=130535i,rx_queue_7_alloc_failed=0i,tx_smbus=0i,tx_queue_3_packets=161081i,rx_queue_7_drops=0i,tx_queue_2_restart=0i,tx_multicast=7i,tx_fifo_errors=0i,tx_queue_3_restart=0i,rx_long_length_errors=0i,tx_queue_6_bytes=96288614i,tx_queue_1_packets=280786i,tx_tcp_seg_failed=0i,rx_align_errors=0i,tx_errors=0i,rx_crc_errors=0i,rx_queue_0_packets=24529673i,rx_flow_control_xoff=0i,tx_queue_0_bytes=29465801i,rx_over_errors=0i,rx_queue_4_drops=0i,os2bmc_rx_by_bmc=0i,rx_smbus=0i,dropped_smbus=0i,tx_hwtstamp_timeouts=0i,rx_errors=0i,tx_queue_4_packets=109102i,tx_carrier_errors=0i,tx_queue_4_bytes=64810835i,tx_queue_4_restart=0i,rx_queue_4_csum_err=0i,tx_queue_7_packets=66665i,tx_aborted_errors=0i,rx_missed_errors=0i,tx_bytes=427575843i,collisions=0i,rx_queue_1_bytes=246703840i,rx_queue_5_bytes=50732006i,rx_bytes=2480288216i,os2bmc_rx_by_host=0i,rx_queue_5_alloc_failed=0i,rx_queue_3_packets=112007i,tx_deferred_ok=0i,os2bmc_tx_by_host=0i,tx_heartbeat_errors=0i,rx_queue_0_bytes=1506877506i,tx_queue_7_restart=0i,tx_packets=1257057i,rx_queue_4_bytes=201364548i,rx_fifo_errors=0i,tx_queue_5_packets=173970i 1564658090000000000
```
46 changes: 46 additions & 0 deletions plugins/inputs/ethtool/ethtool.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
package ethtool

import (
"net"
)

type Command interface {
Init() error
DriverName(intf string) (string, error)
Interfaces() ([]net.Interface, error)
Stats(intf string) (map[string]uint64, error)
}

type Ethtool struct {
// This is the list of interface names to include
InterfaceInclude []string `toml:"interface_include"`

// This is the list of interface names to ignore
InterfaceExclude []string `toml:"interface_exclude"`

// the ethtool command
command Command
}

const (
pluginName = "ethtool"
tagInterface = "interface"
tagDriverName = "driver"

sampleConfig = `
## List of interfaces to pull metrics for
# interface_include = ["eth0"]

## List of interfaces to ignore when pulling metrics.
# interface_exclude = ["eth1"]
`
)

func (e *Ethtool) SampleConfig() string {
return sampleConfig
}

// Description returns a one-sentence description on the Input
func (e *Ethtool) Description() string {
return "Returns ethtool statistics for given interfaces"
}
136 changes: 136 additions & 0 deletions plugins/inputs/ethtool/ethtool_linux.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,136 @@
// +build linux

package ethtool

import (
"net"
philippreston marked this conversation as resolved.
Show resolved Hide resolved
"sync"

"github.com/influxdata/telegraf"
"github.com/influxdata/telegraf/filter"
"github.com/influxdata/telegraf/plugins/inputs"
"github.com/pkg/errors"
"github.com/safchain/ethtool"
)

type CommandEthtool struct {
ethtool *ethtool.Ethtool
}

func (e *Ethtool) Gather(acc telegraf.Accumulator) error {

// Get the list of interfaces
interfaces, err := e.command.Interfaces()
if err != nil {
acc.AddError(err)
return nil
}

interfaceFilter, err := filter.NewIncludeExcludeFilter(e.InterfaceInclude, e.InterfaceExclude)
if err != nil {
return err
}

// parallelize the ethtool call in event of many interfaces
var wg sync.WaitGroup

for _, iface := range interfaces {

// Check this isn't a loop back and that its matched by the filter
if (iface.Flags&net.FlagLoopback == 0) && interfaceFilter.Match(iface.Name) {
wg.Add(1)

go func(i net.Interface) {
e.gatherEthtoolStats(i, acc)
wg.Done()
}(iface)
}
}

// Waiting for all the interfaces
wg.Wait()
return nil
}

// Initialise the Command Tool
func (e *Ethtool) Init() error {
return e.command.Init()
}

// Gather the stats for the interface.
func (e *Ethtool) gatherEthtoolStats(iface net.Interface, acc telegraf.Accumulator) {

tags := make(map[string]string)
tags[tagInterface] = iface.Name

driverName, err := e.command.DriverName(iface.Name)
if err != nil {
driverErr := errors.Wrapf(err, "%s driver", iface.Name)
acc.AddError(driverErr)
return
}

tags[tagDriverName] = driverName

fields := make(map[string]interface{})
stats, err := e.command.Stats(iface.Name)
if err != nil {
statsErr := errors.Wrapf(err, "%s stats", iface.Name)
acc.AddError(statsErr)
return
}

for k, v := range stats {
fields[k] = v
}

acc.AddFields(pluginName, fields, tags)
}

func NewCommandEthtool() *CommandEthtool {
return &CommandEthtool{}
}

func (c *CommandEthtool) Init() error {

if c.ethtool != nil {
return nil
}

e, err := ethtool.NewEthtool()
if err == nil {
c.ethtool = e
}

return err
}

func (c *CommandEthtool) DriverName(intf string) (string, error) {
return c.ethtool.DriverName(intf)
}

func (c *CommandEthtool) Stats(intf string) (map[string]uint64, error) {
return c.ethtool.Stats(intf)
}

func (c *CommandEthtool) Interfaces() ([]net.Interface, error) {

// Get the list of interfaces
interfaces, err := net.Interfaces()
if err != nil {
return nil, err
}

return interfaces, nil
}

func init() {

inputs.Add(pluginName, func() telegraf.Input {
return &Ethtool{
InterfaceInclude: []string{},
InterfaceExclude: []string{},
command: NewCommandEthtool(),
}
})
}
21 changes: 21 additions & 0 deletions plugins/inputs/ethtool/ethtool_nonlinux.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
// +build !linux

package ethtool

import (
"log"

"github.com/influxdata/telegraf"
"github.com/influxdata/telegraf/plugins/inputs"
)

func (e *Ethtool) Gather(acc telegraf.Accumulator) error {
return nil
}

func init() {
inputs.Add(pluginName, func() telegraf.Input {
log.Print("W! [inputs.ethtool] Current platform is not supported")
return &Ethtool{}
})
}
Loading