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 * 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_in - The total number of received packets dropped by the interface
* drop_out - The total number of transmitted 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 Different platforms gather the data above with different mechanisms. Telegraf
uses the ([gopsutil](https://github.com/shirou/gopsutil)) package, which under uses the ([gopsutil](https://github.com/shirou/gopsutil)) package, which under

View File

@ -5,6 +5,9 @@ import (
_ "embed" _ "embed"
"fmt" "fmt"
"net" "net"
"os"
"path/filepath"
"strconv"
"strings" "strings"
"github.com/influxdata/telegraf" "github.com/influxdata/telegraf"
@ -104,6 +107,7 @@ func (n *NetIOStats) Gather(acc telegraf.Accumulator) error {
"err_out": io.Errout, "err_out": io.Errout,
"drop_in": io.Dropin, "drop_in": io.Dropin,
"drop_out": io.Dropout, "drop_out": io.Dropout,
"speed": getInterfaceSpeed(io.Name),
} }
acc.AddCounter("net", fields, tags) acc.AddCounter("net", fields, tags)
} }
@ -129,6 +133,25 @@ func (n *NetIOStats) Gather(acc telegraf.Accumulator) error {
return nil 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() { func init() {
inputs.Add("net", func() telegraf.Input { inputs.Add("net", func() telegraf.Input {
return &NetIOStats{ps: system.NewSystemPS()} return &NetIOStats{ps: system.NewSystemPS()}

View File

@ -1,6 +1,8 @@
package net package net
import ( import (
"os"
"path/filepath"
"testing" "testing"
"github.com/influxdata/telegraf/plugins/inputs/system" "github.com/influxdata/telegraf/plugins/inputs/system"
@ -40,6 +42,8 @@ func TestNetIOStats(t *testing.T) {
} }
mps.On("NetProto").Return(netprotos, nil) 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) err = (&NetIOStats{ps: &mps, skipChecks: true}).Gather(&acc)
require.NoError(t, err) require.NoError(t, err)
@ -56,6 +60,133 @@ func TestNetIOStats(t *testing.T) {
"err_out": uint64(8), "err_out": uint64(8),
"drop_in": uint64(7), "drop_in": uint64(7),
"drop_out": uint64(1), "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) acc.AssertContainsTaggedFields(t, "net", fields1, ntags)

View File

@ -0,0 +1 @@
100

View File

@ -0,0 +1 @@
-1