feat(inputs.internet_speed): Introduce packet loss field (#15329)

This commit is contained in:
r3inbowari 2024-05-10 23:22:14 +08:00 committed by GitHub
parent 8284e21e87
commit afd7f93355
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 61 additions and 22 deletions

2
go.mod
View File

@ -171,7 +171,7 @@ require (
github.com/santhosh-tekuri/jsonschema/v5 v5.3.1
github.com/sensu/sensu-go/api/core/v2 v2.16.0
github.com/shirou/gopsutil/v3 v3.24.4
github.com/showwin/speedtest-go v1.6.10
github.com/showwin/speedtest-go v1.7.5
github.com/signalfx/golib/v3 v3.3.53
github.com/sirupsen/logrus v1.9.3
github.com/sleepinggenius2/gosmi v0.4.4

4
go.sum
View File

@ -2128,8 +2128,8 @@ github.com/shopspring/decimal v0.0.0-20180709203117-cd690d0c9e24/go.mod h1:M+9Nz
github.com/shopspring/decimal v1.2.0/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o=
github.com/shopspring/decimal v1.3.1 h1:2Usl1nmF/WZucqkFZhnfFYxxxu8LG21F6nPQBE5gKV8=
github.com/shopspring/decimal v1.3.1/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o=
github.com/showwin/speedtest-go v1.6.10 h1:dPxr1gVOu30KvMNl2L8UZD937Ge7zsZW0JulzYpyP48=
github.com/showwin/speedtest-go v1.6.10/go.mod h1:uLgdWCNarXxlYsL2E5TOZpCIwpgSWnEANZp7gfHXHu0=
github.com/showwin/speedtest-go v1.7.5 h1:FQ3EdM2vnfw5BRCRzGCYe8aWu70rr21Az5ZFHiW9CdE=
github.com/showwin/speedtest-go v1.7.5/go.mod h1:uLgdWCNarXxlYsL2E5TOZpCIwpgSWnEANZp7gfHXHu0=
github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc=
github.com/signalfx/com_signalfx_metrics_protobuf v0.0.3 h1:32k2QLgsKhcEs55q4REPKyIadvid5FPy2+VMgvbmKJ0=
github.com/signalfx/com_signalfx_metrics_protobuf v0.0.3/go.mod h1:gJrXWi7wSGXfiC7+VheQaz+ypdCt5SmZNL+BRxUe7y4=

View File

@ -45,6 +45,7 @@ See the [CONFIGURATION.md][CONFIGURATION.md] for more details.
## By default, a single sever is used for testing. This may work for most,
## however, setting to "multi" will reach out to multiple servers in an
## attempt to get closer to ideal internet speeds.
## And "multi" will use all available servers to calculate average packet loss.
# test_mode = "single"
## Server ID exclude filter
@ -63,18 +64,21 @@ See the [CONFIGURATION.md][CONFIGURATION.md] for more details.
It collects the following fields:
| Name | field name | type | Unit |
|----------------|------------| ------- | ---- |
| Download Speed | download | float64 | Mbps |
| Upload Speed | upload | float64 | Mbps |
| Latency | latency | float64 | ms |
| Jitter | jitter | float64 | ms |
| Location | location | string | - |
| Name | Field Name | Type | Unit |
|----------------|-------------|---------|------------|
| Download Speed | download | float64 | Mbps |
| Upload Speed | upload | float64 | Mbps |
| Latency | latency | float64 | ms |
| Jitter | jitter | float64 | ms |
| Packet Loss | packet_loss | float64 | percentage |
| Location | location | string | - |
The `packet_loss` will return -1, if packet loss not applicable.
And the following tags:
| Name | tag name |
| --------- | --------- |
|-----------|-----------|
| Source | source |
| Server ID | server_id |
| Test Mode | test_mode |
@ -82,5 +86,6 @@ And the following tags:
## Example Output
```text
internet_speed,source=speedtest02.z4internet.com:8080,server_id=54619,test_mode=single download=318.37580265897725,upload=30.444407341274385,latency=37.73174,jitter=1.99810,location="Somewhere, TX" 1675458921000000000
internet_speed,source=speedtest02.z4internet.com:8080,server_id=54619,test_mode=single download=318.37580265897725,upload=30.444407341274385,latency=37.73174,jitter=1.99810,packet_loss=0.05377,location="Somewhere, TX" 1675458921000000000
internet_speed,source=speedtest02.z4internet.com:8080,server_id=54619,test_mode=multi download=318.37580265897725,upload=30.444407341274385,latency=37.73174,jitter=1.99810,packet_loss=-1,location="Somewhere, TX" 1675458921000000000
```

View File

@ -11,6 +11,7 @@ import (
"time"
"github.com/showwin/speedtest-go/speedtest"
"github.com/showwin/speedtest-go/speedtest/transport"
"github.com/influxdata/telegraf"
"github.com/influxdata/telegraf/filter"
@ -83,6 +84,13 @@ func (is *InternetSpeed) Gather(acc telegraf.Accumulator) error {
return fmt.Errorf("ping test failed: %w", err)
}
analyzer := speedtest.NewPacketLossAnalyzer(&speedtest.PacketLossAnalyzerOptions{
PacketSendingInterval: time.Millisecond * 100,
SamplingDuration: time.Second * 15,
})
pLoss := -1.0
if is.TestMode == testModeMulti {
err = is.server.MultiDownloadTestContext(context.Background(), is.servers)
if err != nil {
@ -90,7 +98,13 @@ func (is *InternetSpeed) Gather(acc telegraf.Accumulator) error {
}
err = is.server.MultiUploadTestContext(context.Background(), is.servers)
if err != nil {
return fmt.Errorf("upload test failed failed: %w", err)
return fmt.Errorf("upload test failed: %w", err)
}
// Not all servers are applicable for packet loss testing.
// If err != nil, we skip it and just report a warning.
pLoss, err = analyzer.RunMulti(is.servers.Hosts())
if err != nil {
is.Log.Warnf("packet loss test failed: %s", err)
}
} else {
err = is.server.DownloadTest()
@ -99,16 +113,35 @@ func (is *InternetSpeed) Gather(acc telegraf.Accumulator) error {
}
err = is.server.UploadTest()
if err != nil {
return fmt.Errorf("upload test failed failed: %w", err)
return fmt.Errorf("upload test failed: %w", err)
}
// Not all servers are applicable for packet loss testing.
// If err != nil, we skip it and just report a warning.
err = analyzer.Run(is.server.Host, func(packetLoss *transport.PLoss) {
if packetLoss != nil && packetLoss.Sent != 0 {
pLoss = packetLoss.Loss()
}
})
if err != nil {
is.Log.Warnf("packet loss test failed: %s", err)
}
}
lossPercent := 0.0
if pLoss == -1 {
// If all servers are not applicable, returned -1.
lossPercent = -1
} else {
lossPercent = pLoss * 100.0
}
fields := map[string]any{
"download": is.server.DLSpeed,
"upload": is.server.ULSpeed,
"latency": timeDurationMillisecondToFloat64(is.server.Latency),
"jitter": timeDurationMillisecondToFloat64(is.server.Jitter),
"location": is.server.Name,
"download": is.server.DLSpeed.Mbps(),
"upload": is.server.ULSpeed.Mbps(),
"latency": timeDurationMillisecondToFloat64(is.server.Latency),
"jitter": timeDurationMillisecondToFloat64(is.server.Jitter),
"packet_loss": lossPercent,
"location": is.server.Name,
}
tags := map[string]string{
"server_id": is.server.ID,
@ -148,7 +181,7 @@ func (is *InternetSpeed) findClosestServer() error {
// Return the first match or the server with the lowest latency
// when filter mismatch all servers.
var min int64 = math.MaxInt64
var minLatency int64 = math.MaxInt64
selectIndex := -1
for index, server := range is.servers {
if is.serverFilter.Match(server.ID) {
@ -156,8 +189,8 @@ func (is *InternetSpeed) findClosestServer() error {
break
}
if server.Latency > 0 {
if min > server.Latency.Milliseconds() {
min = server.Latency.Milliseconds()
if minLatency > server.Latency.Milliseconds() {
minLatency = server.Latency.Milliseconds()
selectIndex = index
}
}

View File

@ -21,6 +21,7 @@
## By default, a single sever is used for testing. This may work for most,
## however, setting to "multi" will reach out to multiple servers in an
## attempt to get closer to ideal internet speeds.
## And "multi" will use all available servers to calculate average packet loss.
# test_mode = "single"
## Server ID exclude filter