feat(inputs.net): Add speed metric (#14625)

This commit is contained in:
Dane Strandboge 2024-01-29 14:11:18 -06:00 committed by GitHub
parent 2153769218
commit 1e3597d889
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 157 additions and 0 deletions

View File

@ -47,6 +47,7 @@ Fields (all platforms):
* err_out - The total number of transmit errors detected by the interface
* drop_in - The total number of received packets dropped by the interface
* drop_out - The total number of transmitted packets dropped by the interface
* speed - The interface's latest or current speed value, in Mbits/sec. May be -1 if unsupported by the interface
Different platforms gather the data above with different mechanisms. Telegraf
uses the ([gopsutil](https://github.com/shirou/gopsutil)) package, which under

View File

@ -5,6 +5,9 @@ import (
_ "embed"
"fmt"
"net"
"os"
"path/filepath"
"strconv"
"strings"
"github.com/influxdata/telegraf"
@ -104,6 +107,7 @@ func (n *NetIOStats) Gather(acc telegraf.Accumulator) error {
"err_out": io.Errout,
"drop_in": io.Dropin,
"drop_out": io.Dropout,
"speed": getInterfaceSpeed(io.Name),
}
acc.AddCounter("net", fields, tags)
}
@ -129,6 +133,25 @@ func (n *NetIOStats) Gather(acc telegraf.Accumulator) error {
return nil
}
// Get the interface speed from /sys/class/net/*/speed file. returns -1 if unsupported
func getInterfaceSpeed(ioName string) int64 {
sysPath := os.Getenv("HOST_SYS")
if sysPath == "" {
sysPath = "/sys"
}
raw, err := os.ReadFile(filepath.Join(sysPath, "class", "net", ioName, "speed"))
if err != nil {
return -1
}
speed, err := strconv.ParseInt(strings.TrimSuffix(string(raw), "\n"), 10, 64)
if err != nil {
return -1
}
return speed
}
func init() {
inputs.Add("net", func() telegraf.Input {
return &NetIOStats{ps: system.NewSystemPS()}

View File

@ -1,6 +1,8 @@
package net
import (
"os"
"path/filepath"
"testing"
"github.com/influxdata/telegraf/plugins/inputs/system"
@ -40,6 +42,8 @@ func TestNetIOStats(t *testing.T) {
}
mps.On("NetProto").Return(netprotos, nil)
require.NoError(t, os.Setenv("HOST_SYS", filepath.Join("testdata", "general", "sys")))
err = (&NetIOStats{ps: &mps, skipChecks: true}).Gather(&acc)
require.NoError(t, err)
@ -56,6 +60,133 @@ func TestNetIOStats(t *testing.T) {
"err_out": uint64(8),
"drop_in": uint64(7),
"drop_out": uint64(1),
"speed": int64(100),
}
acc.AssertContainsTaggedFields(t, "net", fields1, ntags)
fields2 := map[string]interface{}{
"udp_noports": int64(892592),
"udp_indatagrams": int64(4655),
}
ntags = map[string]string{
"interface": "all",
}
acc.AssertContainsTaggedFields(t, "net", fields2, ntags)
}
func TestNetIOStatsSpeedUnsupported(t *testing.T) {
var mps system.MockPS
var err error
defer mps.AssertExpectations(t)
var acc testutil.Accumulator
netio := net.IOCountersStat{
Name: "eth1",
BytesSent: 1123,
BytesRecv: 8734422,
PacketsSent: 781,
PacketsRecv: 23456,
Errin: 832,
Errout: 8,
Dropin: 7,
Dropout: 1,
}
mps.On("NetIO").Return([]net.IOCountersStat{netio}, nil)
netprotos := []net.ProtoCountersStat{
{
Protocol: "Udp",
Stats: map[string]int64{
"InDatagrams": 4655,
"NoPorts": 892592,
},
},
}
mps.On("NetProto").Return(netprotos, nil)
require.NoError(t, os.Setenv("HOST_SYS", filepath.Join("testdata", "general", "sys")))
err = (&NetIOStats{ps: &mps, skipChecks: true}).Gather(&acc)
require.NoError(t, err)
ntags := map[string]string{
"interface": "eth1",
}
fields1 := map[string]interface{}{
"bytes_sent": uint64(1123),
"bytes_recv": uint64(8734422),
"packets_sent": uint64(781),
"packets_recv": uint64(23456),
"err_in": uint64(832),
"err_out": uint64(8),
"drop_in": uint64(7),
"drop_out": uint64(1),
"speed": int64(-1),
}
acc.AssertContainsTaggedFields(t, "net", fields1, ntags)
fields2 := map[string]interface{}{
"udp_noports": int64(892592),
"udp_indatagrams": int64(4655),
}
ntags = map[string]string{
"interface": "all",
}
acc.AssertContainsTaggedFields(t, "net", fields2, ntags)
}
func TestNetIOStatsNoSpeedFile(t *testing.T) {
var mps system.MockPS
var err error
defer mps.AssertExpectations(t)
var acc testutil.Accumulator
netio := net.IOCountersStat{
Name: "eth2",
BytesSent: 1123,
BytesRecv: 8734422,
PacketsSent: 781,
PacketsRecv: 23456,
Errin: 832,
Errout: 8,
Dropin: 7,
Dropout: 1,
}
mps.On("NetIO").Return([]net.IOCountersStat{netio}, nil)
netprotos := []net.ProtoCountersStat{
{
Protocol: "Udp",
Stats: map[string]int64{
"InDatagrams": 4655,
"NoPorts": 892592,
},
},
}
mps.On("NetProto").Return(netprotos, nil)
require.NoError(t, os.Setenv("HOST_SYS", filepath.Join("testdata", "general", "sys")))
err = (&NetIOStats{ps: &mps, skipChecks: true}).Gather(&acc)
require.NoError(t, err)
ntags := map[string]string{
"interface": "eth2",
}
fields1 := map[string]interface{}{
"bytes_sent": uint64(1123),
"bytes_recv": uint64(8734422),
"packets_sent": uint64(781),
"packets_recv": uint64(23456),
"err_in": uint64(832),
"err_out": uint64(8),
"drop_in": uint64(7),
"drop_out": uint64(1),
"speed": int64(-1),
}
acc.AssertContainsTaggedFields(t, "net", fields1, ntags)

View File

@ -0,0 +1 @@
100

View File

@ -0,0 +1 @@
-1