feat(inputs.ethtool): Add support for link speed, duplex, autoneg and… (#12814)
This commit is contained in:
parent
7981260f22
commit
d063dc2e58
2
go.mod
2
go.mod
|
|
@ -147,7 +147,7 @@ require (
|
||||||
github.com/rabbitmq/amqp091-go v1.7.0
|
github.com/rabbitmq/amqp091-go v1.7.0
|
||||||
github.com/riemann/riemann-go-client v0.5.1-0.20211206220514-f58f10cdce16
|
github.com/riemann/riemann-go-client v0.5.1-0.20211206220514-f58f10cdce16
|
||||||
github.com/robbiet480/go.nut v0.0.0-20220219091450-bd8f121e1fa1
|
github.com/robbiet480/go.nut v0.0.0-20220219091450-bd8f121e1fa1
|
||||||
github.com/safchain/ethtool v0.0.0-20210803160452-9aa261dae9b1
|
github.com/safchain/ethtool v0.2.0
|
||||||
github.com/sensu/sensu-go/api/core/v2 v2.15.0
|
github.com/sensu/sensu-go/api/core/v2 v2.15.0
|
||||||
github.com/shirou/gopsutil/v3 v3.22.12
|
github.com/shirou/gopsutil/v3 v3.22.12
|
||||||
github.com/showwin/speedtest-go v1.4.2
|
github.com/showwin/speedtest-go v1.4.2
|
||||||
|
|
|
||||||
4
go.sum
4
go.sum
|
|
@ -2041,8 +2041,8 @@ github.com/ryanrolds/sqlclosecheck v0.3.0/go.mod h1:1gREqxyTGR3lVtpngyFo3hZAgk0K
|
||||||
github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts=
|
github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts=
|
||||||
github.com/ryanuber/columnize v2.1.0+incompatible/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts=
|
github.com/ryanuber/columnize v2.1.0+incompatible/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts=
|
||||||
github.com/ryanuber/go-glob v1.0.0/go.mod h1:807d1WSdnB0XRJzKNil9Om6lcp/3a0v4qIHxIXzX/Yc=
|
github.com/ryanuber/go-glob v1.0.0/go.mod h1:807d1WSdnB0XRJzKNil9Om6lcp/3a0v4qIHxIXzX/Yc=
|
||||||
github.com/safchain/ethtool v0.0.0-20210803160452-9aa261dae9b1 h1:ZFfeKAhIQiiOrQaI3/znw0gOmYpO28Tcu1YaqMa/jtQ=
|
github.com/safchain/ethtool v0.2.0 h1:dILxMBqDnQfX192cCAPjZr9v2IgVXeElHPy435Z/IdE=
|
||||||
github.com/safchain/ethtool v0.0.0-20210803160452-9aa261dae9b1/go.mod h1:Z0q5wiBQGYcxhMZ6gUqHn6pYNLypFAvaL3UvgZLR0U4=
|
github.com/safchain/ethtool v0.2.0/go.mod h1:WkKB1DnNtvsMlDmQ50sgwowDJV/hGbJSOvJoEXs1AJQ=
|
||||||
github.com/sagikazarmark/crypt v0.5.0/go.mod h1:l+nzl7KWh51rpzp2h7t4MZWyiEWdhNpOAnclKvg+mdA=
|
github.com/sagikazarmark/crypt v0.5.0/go.mod h1:l+nzl7KWh51rpzp2h7t4MZWyiEWdhNpOAnclKvg+mdA=
|
||||||
github.com/sagikazarmark/crypt v0.6.0/go.mod h1:U8+INwJo3nBv1m6A/8OBXAq7Jnpspk5AxSgDyEQcea8=
|
github.com/sagikazarmark/crypt v0.6.0/go.mod h1:U8+INwJo3nBv1m6A/8OBXAq7Jnpspk5AxSgDyEQcea8=
|
||||||
github.com/samuel/go-zookeeper v0.0.0-20190923202752-2cc03de413da/go.mod h1:gi+0XIa01GRL2eRQVjQkKGqKF3SF9vZR/HnPullcV2E=
|
github.com/samuel/go-zookeeper v0.0.0-20190923202752-2cc03de413da/go.mod h1:gi+0XIa01GRL2eRQVjQkKGqKF3SF9vZR/HnPullcV2E=
|
||||||
|
|
|
||||||
|
|
@ -101,6 +101,6 @@ Metrics are dependent on the network device and driver.
|
||||||
## Example Output
|
## Example Output
|
||||||
|
|
||||||
```shell
|
```shell
|
||||||
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,interface_up=1i,rx_hwtstamp_cleared=0i,rx_flow_control_xoff=0i 1564658080000000000
|
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,interface_up=1i,rx_hwtstamp_cleared=0i,rx_flow_control_xoff=0i,speed=1000i,link=1i,duplex=1i,autoneg=1i 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,interface_up=0i,rx_fifo_errors=0i,tx_queue_5_packets=173970i 1564658090000000000
|
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,interface_up=0i,rx_fifo_errors=0i,tx_queue_5_packets=173970i,speed=1000i,link=1i,duplex=1i,autoneg=1i 1564658090000000000
|
||||||
```
|
```
|
||||||
|
|
|
||||||
|
|
@ -18,6 +18,7 @@ type Command interface {
|
||||||
DriverName(intf NamespacedInterface) (string, error)
|
DriverName(intf NamespacedInterface) (string, error)
|
||||||
Interfaces(includeNamespaces bool) ([]NamespacedInterface, error)
|
Interfaces(includeNamespaces bool) ([]NamespacedInterface, error)
|
||||||
Stats(intf NamespacedInterface) (map[string]uint64, error)
|
Stats(intf NamespacedInterface) (map[string]uint64, error)
|
||||||
|
Get(intf NamespacedInterface) (map[string]uint64, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
type Ethtool struct {
|
type Ethtool struct {
|
||||||
|
|
|
||||||
|
|
@ -132,6 +132,16 @@ func (e *Ethtool) gatherEthtoolStats(iface NamespacedInterface, acc telegraf.Acc
|
||||||
fields[e.normalizeKey(k)] = v
|
fields[e.normalizeKey(k)] = v
|
||||||
}
|
}
|
||||||
|
|
||||||
|
cmdget, err := e.command.Get(iface)
|
||||||
|
if err != nil {
|
||||||
|
acc.AddError(fmt.Errorf("%q get: %w", iface.Name, err))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
for k, v := range cmdget {
|
||||||
|
fields[e.normalizeKey(k)] = v
|
||||||
|
}
|
||||||
|
|
||||||
acc.AddFields(pluginName, fields, tags)
|
acc.AddFields(pluginName, fields, tags)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -221,6 +231,10 @@ func (c *CommandEthtool) Stats(intf NamespacedInterface) (stats map[string]uint6
|
||||||
return intf.Namespace.Stats(intf)
|
return intf.Namespace.Stats(intf)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *CommandEthtool) Get(intf NamespacedInterface) (stats map[string]uint64, err error) {
|
||||||
|
return intf.Namespace.Get(intf)
|
||||||
|
}
|
||||||
|
|
||||||
func (c *CommandEthtool) Interfaces(includeNamespaces bool) ([]NamespacedInterface, error) {
|
func (c *CommandEthtool) Interfaces(includeNamespaces bool) ([]NamespacedInterface, error) {
|
||||||
const namespaceDirectory = "/var/run/netns"
|
const namespaceDirectory = "/var/run/netns"
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -24,6 +24,7 @@ type InterfaceMock struct {
|
||||||
Stat map[string]uint64
|
Stat map[string]uint64
|
||||||
LoopBack bool
|
LoopBack bool
|
||||||
InterfaceUp bool
|
InterfaceUp bool
|
||||||
|
CmdGet map[string]uint64
|
||||||
}
|
}
|
||||||
|
|
||||||
type NamespaceMock struct {
|
type NamespaceMock struct {
|
||||||
|
|
@ -46,6 +47,10 @@ func (n *NamespaceMock) Stats(_ NamespacedInterface) (map[string]uint64, error)
|
||||||
return nil, errors.New("it is a test bug to invoke this function")
|
return nil, errors.New("it is a test bug to invoke this function")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (n *NamespaceMock) Get(_ NamespacedInterface) (map[string]uint64, error) {
|
||||||
|
return nil, errors.New("it is a test bug to invoke this function")
|
||||||
|
}
|
||||||
|
|
||||||
type CommandEthtoolMock struct {
|
type CommandEthtoolMock struct {
|
||||||
InterfaceMap map[string]*InterfaceMock
|
InterfaceMap map[string]*InterfaceMock
|
||||||
}
|
}
|
||||||
|
|
@ -117,6 +122,14 @@ func (c *CommandEthtoolMock) Stats(intf NamespacedInterface) (map[string]uint64,
|
||||||
return nil, errors.New("interface not found")
|
return nil, errors.New("interface not found")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *CommandEthtoolMock) Get(intf NamespacedInterface) (map[string]uint64, error) {
|
||||||
|
i := c.InterfaceMap[intf.Name]
|
||||||
|
if i != nil {
|
||||||
|
return i.CmdGet, nil
|
||||||
|
}
|
||||||
|
return nil, errors.New("interface not found")
|
||||||
|
}
|
||||||
|
|
||||||
func setup() {
|
func setup() {
|
||||||
interfaceMap = make(map[string]*InterfaceMock)
|
interfaceMap = make(map[string]*InterfaceMock)
|
||||||
|
|
||||||
|
|
@ -219,7 +232,13 @@ func setup() {
|
||||||
"tx_tso_fallbacks": 0,
|
"tx_tso_fallbacks": 0,
|
||||||
"tx_tso_long_headers": 0,
|
"tx_tso_long_headers": 0,
|
||||||
}
|
}
|
||||||
eth1 := &InterfaceMock{"eth1", "driver1", "", eth1Stat, false, true}
|
eth1Get := map[string]uint64{
|
||||||
|
"autoneg": 1,
|
||||||
|
"duplex": 1,
|
||||||
|
"link": 1,
|
||||||
|
"speed": 1000,
|
||||||
|
}
|
||||||
|
eth1 := &InterfaceMock{"eth1", "driver1", "", eth1Stat, false, true, eth1Get}
|
||||||
interfaceMap[eth1.Name] = eth1
|
interfaceMap[eth1.Name] = eth1
|
||||||
|
|
||||||
eth2Stat := map[string]uint64{
|
eth2Stat := map[string]uint64{
|
||||||
|
|
@ -321,7 +340,13 @@ func setup() {
|
||||||
"tx_tso_fallbacks": 0,
|
"tx_tso_fallbacks": 0,
|
||||||
"tx_tso_long_headers": 0,
|
"tx_tso_long_headers": 0,
|
||||||
}
|
}
|
||||||
eth2 := &InterfaceMock{"eth2", "driver1", "", eth2Stat, false, false}
|
eth2Get := map[string]uint64{
|
||||||
|
"autoneg": 0,
|
||||||
|
"duplex": 255,
|
||||||
|
"link": 0,
|
||||||
|
"speed": 9223372036854775807,
|
||||||
|
}
|
||||||
|
eth2 := &InterfaceMock{"eth2", "driver1", "", eth2Stat, false, false, eth2Get}
|
||||||
interfaceMap[eth2.Name] = eth2
|
interfaceMap[eth2.Name] = eth2
|
||||||
|
|
||||||
eth3Stat := map[string]uint64{
|
eth3Stat := map[string]uint64{
|
||||||
|
|
@ -423,7 +448,13 @@ func setup() {
|
||||||
"tx_tso_fallbacks": 0,
|
"tx_tso_fallbacks": 0,
|
||||||
"tx_tso_long_headers": 0,
|
"tx_tso_long_headers": 0,
|
||||||
}
|
}
|
||||||
eth3 := &InterfaceMock{"eth3", "driver1", "namespace1", eth3Stat, false, true}
|
eth3Get := map[string]uint64{
|
||||||
|
"autoneg": 1,
|
||||||
|
"duplex": 1,
|
||||||
|
"link": 1,
|
||||||
|
"speed": 1000,
|
||||||
|
}
|
||||||
|
eth3 := &InterfaceMock{"eth3", "driver1", "namespace1", eth3Stat, false, true, eth3Get}
|
||||||
interfaceMap[eth3.Name] = eth3
|
interfaceMap[eth3.Name] = eth3
|
||||||
|
|
||||||
eth4Stat := map[string]uint64{
|
eth4Stat := map[string]uint64{
|
||||||
|
|
@ -525,14 +556,26 @@ func setup() {
|
||||||
"tx_tso_fallbacks": 0,
|
"tx_tso_fallbacks": 0,
|
||||||
"tx_tso_long_headers": 0,
|
"tx_tso_long_headers": 0,
|
||||||
}
|
}
|
||||||
eth4 := &InterfaceMock{"eth4", "driver1", "namespace2", eth4Stat, false, true}
|
eth4Get := map[string]uint64{
|
||||||
|
"autoneg": 1,
|
||||||
|
"duplex": 1,
|
||||||
|
"link": 1,
|
||||||
|
"speed": 100,
|
||||||
|
}
|
||||||
|
eth4 := &InterfaceMock{"eth4", "driver1", "namespace2", eth4Stat, false, true, eth4Get}
|
||||||
interfaceMap[eth4.Name] = eth4
|
interfaceMap[eth4.Name] = eth4
|
||||||
|
|
||||||
// dummy loopback including dummy stat to ensure that the ignore feature is working
|
// dummy loopback including dummy stat to ensure that the ignore feature is working
|
||||||
lo0Stat := map[string]uint64{
|
lo0Stat := map[string]uint64{
|
||||||
"dummy": 0,
|
"dummy": 0,
|
||||||
}
|
}
|
||||||
lo0 := &InterfaceMock{"lo0", "", "", lo0Stat, true, true}
|
lo0Get := map[string]uint64{
|
||||||
|
"autoneg": 1,
|
||||||
|
"duplex": 1,
|
||||||
|
"link": 1,
|
||||||
|
"speed": 1000,
|
||||||
|
}
|
||||||
|
lo0 := &InterfaceMock{"lo0", "", "", lo0Stat, true, true, lo0Get}
|
||||||
interfaceMap[lo0.Name] = lo0
|
interfaceMap[lo0.Name] = lo0
|
||||||
|
|
||||||
c := &CommandEthtoolMock{interfaceMap}
|
c := &CommandEthtoolMock{interfaceMap}
|
||||||
|
|
@ -573,6 +616,9 @@ func TestGather(t *testing.T) {
|
||||||
require.Len(t, acc.Metrics, 2)
|
require.Len(t, acc.Metrics, 2)
|
||||||
|
|
||||||
expectedFieldsEth1 := toStringMapInterface(interfaceMap["eth1"].Stat)
|
expectedFieldsEth1 := toStringMapInterface(interfaceMap["eth1"].Stat)
|
||||||
|
for k, v := range interfaceMap["eth1"].CmdGet {
|
||||||
|
expectedFieldsEth1[k] = v
|
||||||
|
}
|
||||||
expectedFieldsEth1["interface_up_counter"] = expectedFieldsEth1["interface_up"]
|
expectedFieldsEth1["interface_up_counter"] = expectedFieldsEth1["interface_up"]
|
||||||
expectedFieldsEth1["interface_up"] = true
|
expectedFieldsEth1["interface_up"] = true
|
||||||
|
|
||||||
|
|
@ -582,7 +628,11 @@ func TestGather(t *testing.T) {
|
||||||
"namespace": "",
|
"namespace": "",
|
||||||
}
|
}
|
||||||
acc.AssertContainsTaggedFields(t, pluginName, expectedFieldsEth1, expectedTagsEth1)
|
acc.AssertContainsTaggedFields(t, pluginName, expectedFieldsEth1, expectedTagsEth1)
|
||||||
|
|
||||||
expectedFieldsEth2 := toStringMapInterface(interfaceMap["eth2"].Stat)
|
expectedFieldsEth2 := toStringMapInterface(interfaceMap["eth2"].Stat)
|
||||||
|
for k, v := range interfaceMap["eth2"].CmdGet {
|
||||||
|
expectedFieldsEth2[k] = v
|
||||||
|
}
|
||||||
expectedFieldsEth2["interface_up_counter"] = expectedFieldsEth2["interface_up"]
|
expectedFieldsEth2["interface_up_counter"] = expectedFieldsEth2["interface_up"]
|
||||||
expectedFieldsEth2["interface_up"] = false
|
expectedFieldsEth2["interface_up"] = false
|
||||||
expectedTagsEth2 := map[string]string{
|
expectedTagsEth2 := map[string]string{
|
||||||
|
|
@ -608,6 +658,9 @@ func TestGatherIncludeInterfaces(t *testing.T) {
|
||||||
|
|
||||||
// Should contain eth1
|
// Should contain eth1
|
||||||
expectedFieldsEth1 := toStringMapInterface(interfaceMap["eth1"].Stat)
|
expectedFieldsEth1 := toStringMapInterface(interfaceMap["eth1"].Stat)
|
||||||
|
for k, v := range interfaceMap["eth1"].CmdGet {
|
||||||
|
expectedFieldsEth1[k] = v
|
||||||
|
}
|
||||||
expectedFieldsEth1["interface_up_counter"] = expectedFieldsEth1["interface_up"]
|
expectedFieldsEth1["interface_up_counter"] = expectedFieldsEth1["interface_up"]
|
||||||
expectedFieldsEth1["interface_up"] = true
|
expectedFieldsEth1["interface_up"] = true
|
||||||
expectedTagsEth1 := map[string]string{
|
expectedTagsEth1 := map[string]string{
|
||||||
|
|
@ -619,6 +672,9 @@ func TestGatherIncludeInterfaces(t *testing.T) {
|
||||||
|
|
||||||
// Should not contain eth2
|
// Should not contain eth2
|
||||||
expectedFieldsEth2 := toStringMapInterface(interfaceMap["eth2"].Stat)
|
expectedFieldsEth2 := toStringMapInterface(interfaceMap["eth2"].Stat)
|
||||||
|
for k, v := range interfaceMap["eth2"].CmdGet {
|
||||||
|
expectedFieldsEth2[k] = v
|
||||||
|
}
|
||||||
expectedFieldsEth2["interface_up_counter"] = expectedFieldsEth2["interface_up"]
|
expectedFieldsEth2["interface_up_counter"] = expectedFieldsEth2["interface_up"]
|
||||||
expectedFieldsEth2["interface_up"] = false
|
expectedFieldsEth2["interface_up"] = false
|
||||||
expectedTagsEth2 := map[string]string{
|
expectedTagsEth2 := map[string]string{
|
||||||
|
|
@ -644,6 +700,9 @@ func TestGatherIgnoreInterfaces(t *testing.T) {
|
||||||
|
|
||||||
// Should not contain eth1
|
// Should not contain eth1
|
||||||
expectedFieldsEth1 := toStringMapInterface(interfaceMap["eth1"].Stat)
|
expectedFieldsEth1 := toStringMapInterface(interfaceMap["eth1"].Stat)
|
||||||
|
for k, v := range interfaceMap["eth1"].CmdGet {
|
||||||
|
expectedFieldsEth1[k] = v
|
||||||
|
}
|
||||||
expectedFieldsEth1["interface_up_counter"] = expectedFieldsEth1["interface_up"]
|
expectedFieldsEth1["interface_up_counter"] = expectedFieldsEth1["interface_up"]
|
||||||
expectedFieldsEth1["interface_up"] = true
|
expectedFieldsEth1["interface_up"] = true
|
||||||
expectedTagsEth1 := map[string]string{
|
expectedTagsEth1 := map[string]string{
|
||||||
|
|
@ -655,6 +714,9 @@ func TestGatherIgnoreInterfaces(t *testing.T) {
|
||||||
|
|
||||||
// Should contain eth2
|
// Should contain eth2
|
||||||
expectedFieldsEth2 := toStringMapInterface(interfaceMap["eth2"].Stat)
|
expectedFieldsEth2 := toStringMapInterface(interfaceMap["eth2"].Stat)
|
||||||
|
for k, v := range interfaceMap["eth2"].CmdGet {
|
||||||
|
expectedFieldsEth2[k] = v
|
||||||
|
}
|
||||||
expectedFieldsEth2["interface_up_counter"] = expectedFieldsEth2["interface_up"]
|
expectedFieldsEth2["interface_up_counter"] = expectedFieldsEth2["interface_up"]
|
||||||
expectedFieldsEth2["interface_up"] = false
|
expectedFieldsEth2["interface_up"] = false
|
||||||
expectedTagsEth2 := map[string]string{
|
expectedTagsEth2 := map[string]string{
|
||||||
|
|
@ -679,6 +741,9 @@ func TestSkipMetricsForInterfaceDown(t *testing.T) {
|
||||||
require.Len(t, acc.Metrics, 1)
|
require.Len(t, acc.Metrics, 1)
|
||||||
|
|
||||||
expectedFieldsEth1 := toStringMapInterface(interfaceMap["eth1"].Stat)
|
expectedFieldsEth1 := toStringMapInterface(interfaceMap["eth1"].Stat)
|
||||||
|
for k, v := range interfaceMap["eth1"].CmdGet {
|
||||||
|
expectedFieldsEth1[k] = v
|
||||||
|
}
|
||||||
expectedFieldsEth1["interface_up_counter"] = expectedFieldsEth1["interface_up"]
|
expectedFieldsEth1["interface_up_counter"] = expectedFieldsEth1["interface_up"]
|
||||||
expectedFieldsEth1["interface_up"] = true
|
expectedFieldsEth1["interface_up"] = true
|
||||||
|
|
||||||
|
|
@ -705,6 +770,9 @@ func TestGatherIncludeNamespaces(t *testing.T) {
|
||||||
|
|
||||||
// Should contain eth3
|
// Should contain eth3
|
||||||
expectedFieldsEth3 := toStringMapInterface(interfaceMap["eth3"].Stat)
|
expectedFieldsEth3 := toStringMapInterface(interfaceMap["eth3"].Stat)
|
||||||
|
for k, v := range interfaceMap["eth3"].CmdGet {
|
||||||
|
expectedFieldsEth3[k] = v
|
||||||
|
}
|
||||||
expectedFieldsEth3["interface_up_counter"] = expectedFieldsEth3["interface_up"]
|
expectedFieldsEth3["interface_up_counter"] = expectedFieldsEth3["interface_up"]
|
||||||
expectedFieldsEth3["interface_up"] = true
|
expectedFieldsEth3["interface_up"] = true
|
||||||
expectedTagsEth3 := map[string]string{
|
expectedTagsEth3 := map[string]string{
|
||||||
|
|
@ -716,6 +784,9 @@ func TestGatherIncludeNamespaces(t *testing.T) {
|
||||||
|
|
||||||
// Should not contain eth2
|
// Should not contain eth2
|
||||||
expectedFieldsEth2 := toStringMapInterface(interfaceMap["eth2"].Stat)
|
expectedFieldsEth2 := toStringMapInterface(interfaceMap["eth2"].Stat)
|
||||||
|
for k, v := range interfaceMap["eth2"].CmdGet {
|
||||||
|
expectedFieldsEth2[k] = v
|
||||||
|
}
|
||||||
expectedFieldsEth2["interface_up_counter"] = expectedFieldsEth2["interface_up"]
|
expectedFieldsEth2["interface_up_counter"] = expectedFieldsEth2["interface_up"]
|
||||||
expectedFieldsEth2["interface_up"] = false
|
expectedFieldsEth2["interface_up"] = false
|
||||||
expectedTagsEth2 := map[string]string{
|
expectedTagsEth2 := map[string]string{
|
||||||
|
|
@ -741,6 +812,9 @@ func TestGatherIgnoreNamespaces(t *testing.T) {
|
||||||
|
|
||||||
// Should not contain eth4
|
// Should not contain eth4
|
||||||
expectedFieldsEth4 := toStringMapInterface(interfaceMap["eth4"].Stat)
|
expectedFieldsEth4 := toStringMapInterface(interfaceMap["eth4"].Stat)
|
||||||
|
for k, v := range interfaceMap["eth4"].CmdGet {
|
||||||
|
expectedFieldsEth4[k] = v
|
||||||
|
}
|
||||||
expectedFieldsEth4["interface_up_counter"] = expectedFieldsEth4["interface_up"]
|
expectedFieldsEth4["interface_up_counter"] = expectedFieldsEth4["interface_up"]
|
||||||
expectedFieldsEth4["interface_up"] = true
|
expectedFieldsEth4["interface_up"] = true
|
||||||
expectedTagsEth4 := map[string]string{
|
expectedTagsEth4 := map[string]string{
|
||||||
|
|
@ -752,6 +826,9 @@ func TestGatherIgnoreNamespaces(t *testing.T) {
|
||||||
|
|
||||||
// Should contain eth2
|
// Should contain eth2
|
||||||
expectedFieldsEth2 := toStringMapInterface(interfaceMap["eth2"].Stat)
|
expectedFieldsEth2 := toStringMapInterface(interfaceMap["eth2"].Stat)
|
||||||
|
for k, v := range interfaceMap["eth2"].CmdGet {
|
||||||
|
expectedFieldsEth2[k] = v
|
||||||
|
}
|
||||||
expectedFieldsEth2["interface_up_counter"] = expectedFieldsEth2["interface_up"]
|
expectedFieldsEth2["interface_up_counter"] = expectedFieldsEth2["interface_up"]
|
||||||
expectedFieldsEth2["interface_up"] = false
|
expectedFieldsEth2["interface_up"] = false
|
||||||
expectedTagsEth2 := map[string]string{
|
expectedTagsEth2 := map[string]string{
|
||||||
|
|
@ -763,6 +840,9 @@ func TestGatherIgnoreNamespaces(t *testing.T) {
|
||||||
|
|
||||||
// Should contain eth3
|
// Should contain eth3
|
||||||
expectedFieldsEth3 := toStringMapInterface(interfaceMap["eth3"].Stat)
|
expectedFieldsEth3 := toStringMapInterface(interfaceMap["eth3"].Stat)
|
||||||
|
for k, v := range interfaceMap["eth3"].CmdGet {
|
||||||
|
expectedFieldsEth3[k] = v
|
||||||
|
}
|
||||||
expectedFieldsEth3["interface_up_counter"] = expectedFieldsEth3["interface_up"]
|
expectedFieldsEth3["interface_up_counter"] = expectedFieldsEth3["interface_up"]
|
||||||
expectedFieldsEth3["interface_up"] = true
|
expectedFieldsEth3["interface_up"] = true
|
||||||
expectedTagsEth3 := map[string]string{
|
expectedTagsEth3 := map[string]string{
|
||||||
|
|
@ -880,7 +960,7 @@ func TestNormalizedKeys(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, c := range cases {
|
for _, c := range cases {
|
||||||
eth0 := &InterfaceMock{"eth0", "e1000e", "", toStringMapUint(c.stats), false, true}
|
eth0 := &InterfaceMock{"eth0", "e1000e", "", toStringMapUint(c.stats), false, true, map[string]uint64{}}
|
||||||
expectedTags := map[string]string{
|
expectedTags := map[string]string{
|
||||||
"interface": eth0.Name,
|
"interface": eth0.Name,
|
||||||
"driver": eth0.DriverName,
|
"driver": eth0.DriverName,
|
||||||
|
|
|
||||||
|
|
@ -7,6 +7,7 @@ type Namespace interface {
|
||||||
Interfaces() ([]NamespacedInterface, error)
|
Interfaces() ([]NamespacedInterface, error)
|
||||||
DriverName(intf NamespacedInterface) (string, error)
|
DriverName(intf NamespacedInterface) (string, error)
|
||||||
Stats(intf NamespacedInterface) (map[string]uint64, error)
|
Stats(intf NamespacedInterface) (map[string]uint64, error)
|
||||||
|
Get(intf NamespacedInterface) (map[string]uint64, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
type NamespacedInterface struct {
|
type NamespacedInterface struct {
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
package ethtool
|
package ethtool
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"math"
|
||||||
"net"
|
"net"
|
||||||
"runtime"
|
"runtime"
|
||||||
|
|
||||||
|
|
@ -68,6 +69,36 @@ func (n *NamespaceGoroutine) Stats(intf NamespacedInterface) (map[string]uint64,
|
||||||
return driver.(map[string]uint64), err
|
return driver.(map[string]uint64), err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (n *NamespaceGoroutine) Get(intf NamespacedInterface) (map[string]uint64, error) {
|
||||||
|
result, err := n.Do(func(n *NamespaceGoroutine) (interface{}, error) {
|
||||||
|
ecmd := ethtoolLib.EthtoolCmd{}
|
||||||
|
speed32, err := n.ethtoolClient.CmdGet(&ecmd, intf.Name)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
var speed = uint64(speed32)
|
||||||
|
if speed == math.MaxUint32 {
|
||||||
|
speed = math.MaxUint64
|
||||||
|
}
|
||||||
|
|
||||||
|
var link32 uint32
|
||||||
|
link32, err = n.ethtoolClient.LinkState(intf.Name)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return map[string]uint64{
|
||||||
|
"speed": speed,
|
||||||
|
"duplex": uint64(ecmd.Duplex),
|
||||||
|
"autoneg": uint64(ecmd.Autoneg),
|
||||||
|
"link": uint64(link32),
|
||||||
|
}, nil
|
||||||
|
})
|
||||||
|
|
||||||
|
return result.(map[string]uint64), err
|
||||||
|
}
|
||||||
|
|
||||||
// Start locks a goroutine to an OS thread and ties it to the namespace, then
|
// Start locks a goroutine to an OS thread and ties it to the namespace, then
|
||||||
// loops for actions to run in the namespace.
|
// loops for actions to run in the namespace.
|
||||||
func (n *NamespaceGoroutine) Start() error {
|
func (n *NamespaceGoroutine) Start() error {
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue