Skip to content

Commit

Permalink
feat(inputs.internet_speed): Introduce packet loss field (#15329)
Browse files Browse the repository at this point in the history
  • Loading branch information
r3inbowari authored May 10, 2024
1 parent 8284e21 commit afd7f93
Show file tree
Hide file tree
Showing 5 changed files with 61 additions and 22 deletions.
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
4 changes: 2 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -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=
Expand Down
23 changes: 14 additions & 9 deletions plugins/inputs/internet_speed/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -63,24 +64,28 @@ 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 |

## 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
```
53 changes: 43 additions & 10 deletions plugins/inputs/internet_speed/internet_speed.go
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -83,14 +84,27 @@ 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 {
return fmt.Errorf("download test failed: %w", err)
}
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()
Expand All @@ -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,
Expand Down Expand Up @@ -148,16 +181,16 @@ 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) {
selectIndex = index
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
}
}
Expand Down
1 change: 1 addition & 0 deletions plugins/inputs/internet_speed/sample.conf
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down

0 comments on commit afd7f93

Please sign in to comment.