Skip to content
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
1 change: 1 addition & 0 deletions plugins/inputs/net/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
23 changes: 23 additions & 0 deletions plugins/inputs/net/net.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@ import (
_ "embed"
"fmt"
"net"
"os"
"path/filepath"
"strconv"
"strings"

"github.com/influxdata/telegraf"
Expand Down Expand Up @@ -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)
}
Expand All @@ -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
}
Comment thread
srebhan marked this conversation as resolved.
return speed
}

func init() {
inputs.Add("net", func() telegraf.Input {
return &NetIOStats{ps: system.NewSystemPS()}
Expand Down
131 changes: 131 additions & 0 deletions plugins/inputs/net/net_test.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package net

import (
"os"
"path/filepath"
"testing"

"github.com/influxdata/telegraf/plugins/inputs/system"
Expand Down Expand Up @@ -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)

Expand All @@ -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)

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
100
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
-1