-
Notifications
You must be signed in to change notification settings - Fork 5.6k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Added new input plugin that will support pulling of data from ethernet devices via ethtool
- Loading branch information
1 parent
43c6d13
commit 5cb7ac9
Showing
8 changed files
with
722 additions
and
0 deletions.
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
# 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 | ||
# include_interfaces = ["eth0"] | ||
|
||
## List of interfaces to ignore when pulling metrics. | ||
# ignore_interfaces = ["lo0"] | ||
|
||
## List of stat fields to include - default is all | ||
# include_fields = [""] | ||
|
||
## Add driver information as tag | ||
driver_name_tag = true | ||
``` | ||
|
||
Interfaces can be included or ignored using | ||
|
||
- `include_interfaces` | ||
- `ignore_interfaces` | ||
|
||
Fields can be filtered using the `include_fields` array | ||
|
||
The driver name can be dropped by setting `driver_name_tag` to false | ||
|
||
### Metrics: | ||
|
||
Metrics are dependant on the network device and drive | ||
|
||
### Example Output: | ||
|
||
``` | ||
1558004820000000000 sfc host1 sfc0 34503285 17460420127 2110321 2864308103 575875087 461432982 1936943999 1331 330765 0 83297760 5031166659864 0 19816863653 1916 5423 1 0 23335592573 5031166329099 0 0 21155071896 467 0 23335593904 0 0 0 0 118510 0 0 0 2097222917 5935186 37589985 19562047 1970004687 65731417 1337584 11020953 15 769847731426 0 0 104088 2111181859 4 2111077752 33185072 386225 367805 364416 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 95859 82516 61007 82432 1 1982 241268 321814 0 0 0 0 server | ||
1558004820000000000 sfc host1 sfc1 17343701 8908686711 632191 1517683738 555287868 235073828 1198382648 4728 1157017 0 40065908 2827782326577 0 10760403171 0 1 0 0 12433085957 2827781169560 0 0 11465379144 3180 0 12433090685 0 0 0 0 0 0 0 0 927640905 5061453 23841543 16791171 1233044960 69992129 946623 7294533 3 514931291258 0 0 67467 1356972412 4 1356904938 31047711 367053 371436 389928 62 0 0 0 0 0 0 0 0 0 0 0 0 0 0 45662 75807 59790 61527 0 241 182379 240811 300 0 0 1975 server | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,61 @@ | ||
package ethtool | ||
|
||
import ( | ||
"sync" | ||
) | ||
|
||
type Command interface { | ||
DriverName(intf string) (string, error) | ||
InterfaceNames() ([]string, error) | ||
Stats(intf string) (map[string]uint64, error) | ||
} | ||
|
||
type Ethtool struct { | ||
// This is the list of interface names to include | ||
IncludeInterfaces []string `toml:"include_interfaces"` | ||
|
||
// This is the list of interface names to ignore | ||
IgnoreInterfaces []string `toml:"ignore_interfaces"` | ||
|
||
// Whether to include the driver name in the tag | ||
DriverName bool `toml:"driver_name_tag"` | ||
|
||
// Fields to include - all if empty | ||
IncludeFields []string `toml:"include_fields"` | ||
|
||
// the ethtool command | ||
command Command | ||
|
||
// Will parallelize the ethtool call in event of many interfaces | ||
// so using this to sync | ||
wg sync.WaitGroup | ||
} | ||
|
||
const ( | ||
pluginName = "ethtool" | ||
tagInterface = "interface" | ||
tagDriverName = "driver" | ||
|
||
sampleConfig = ` | ||
## List of interfaces to pull metrics for | ||
# include_interfaces = ["eth0"] | ||
## List of interfaces to ignore when pulling metrics. | ||
# ignore_interfaces = ["lo0"] | ||
## List of stat fields to include - default is all | ||
# include_fields = [""] | ||
## Add driver information as tag | ||
driver_name_tag = true | ||
` | ||
) | ||
|
||
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" | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,168 @@ | ||
// +build linux | ||
|
||
package ethtool | ||
|
||
import ( | ||
"net" | ||
|
||
"github.com/influxdata/telegraf" | ||
"github.com/influxdata/telegraf/plugins/inputs" | ||
"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.InterfaceNames() | ||
if err != nil { | ||
acc.AddError(err) | ||
return nil | ||
} | ||
|
||
for _, iface := range interfaces { | ||
|
||
// Check if this is something we are configured to process | ||
if e.shouldProcessInterface(iface) { | ||
e.wg.Add(1) | ||
go e.gatherEthtoolStats(iface, acc) | ||
} | ||
} | ||
|
||
// Waiting for all the interfaces | ||
e.wg.Wait() | ||
return nil | ||
} | ||
|
||
// Decide whether or not to process the interface. If the interface list is empty or the interface name | ||
// in the list - pass to the deny processing | ||
func (e *Ethtool) shouldProcessInterface(iface string) bool { | ||
|
||
// If there is an include filter - allow if in this list | ||
if len(e.IncludeInterfaces) > 0 { | ||
if contains(e.IncludeInterfaces, iface) { | ||
return true | ||
} else { | ||
return false | ||
} | ||
} | ||
|
||
// If there is an exclude filter - deny if in this list | ||
if len(e.IgnoreInterfaces) > 0 { | ||
if contains(e.IgnoreInterfaces, iface) { | ||
return false | ||
} | ||
} | ||
|
||
// By default include all interfaces | ||
return true | ||
} | ||
|
||
// Decide whether a field should be included | ||
func (e *Ethtool) shouldIncludeField(field string) bool { | ||
|
||
if len(e.IncludeFields) > 0 { | ||
if contains(e.IncludeFields, field) { | ||
return true | ||
} else { | ||
return false | ||
} | ||
|
||
} | ||
|
||
// By default include all fields | ||
return true | ||
} | ||
|
||
func contains(s []string, value string) bool { | ||
for _, item := range s { | ||
if item == value { | ||
return true | ||
} | ||
} | ||
return false | ||
} | ||
|
||
// Gather the stats for the interface. Passing by value here as running in goroutine | ||
func (e *Ethtool) gatherEthtoolStats(iface string, acc telegraf.Accumulator) { | ||
defer e.wg.Done() | ||
|
||
tags := make(map[string]string) | ||
tags[tagInterface] = iface | ||
|
||
// Optionally add driver name as a tag | ||
if e.DriverName { | ||
|
||
driverName, err := e.command.DriverName(iface) | ||
if err != nil { | ||
acc.AddError(err) | ||
return | ||
} | ||
|
||
tags[tagDriverName] = driverName | ||
} | ||
|
||
fields := make(map[string]interface{}) | ||
stats, err := e.command.Stats(iface) | ||
if err != nil { | ||
acc.AddError(err) | ||
return | ||
} | ||
|
||
// Apply the field filter | ||
for k, v := range stats { | ||
if e.shouldIncludeField(k) { | ||
fields[k] = v | ||
} | ||
} | ||
|
||
acc.AddFields(pluginName, fields, tags) | ||
} | ||
|
||
func NewCommandEthtool() *CommandEthtool { | ||
e, _ := ethtool.NewEthtool() | ||
return &CommandEthtool{e} | ||
} | ||
|
||
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) InterfaceNames() ([]string, error) { | ||
// Get the list of interfaces | ||
interfaces, err := net.Interfaces() | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
interfaceNames := make([]string, len(interfaces)) | ||
for _, iface := range interfaces { | ||
interfaceNames = append(interfaceNames, iface.Name) | ||
} | ||
|
||
return interfaceNames, nil | ||
} | ||
|
||
func init() { | ||
|
||
// Create command handler | ||
e := NewCommandEthtool() | ||
s := Ethtool{ | ||
IncludeInterfaces: []string{}, | ||
IgnoreInterfaces: []string{}, | ||
IncludeFields: []string{}, | ||
DriverName: true, | ||
command: e, | ||
} | ||
|
||
inputs.Add(pluginName, func() telegraf.Input { | ||
return &s | ||
}) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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{} | ||
}) | ||
} |
Oops, something went wrong.