Adding upstream version 1.34.4.
Signed-off-by: Daniel Baumann <daniel@debian.org>
This commit is contained in:
parent
e393c3af3f
commit
4978089aab
4963 changed files with 677545 additions and 0 deletions
99
plugins/inputs/internet_speed/README.md
Normal file
99
plugins/inputs/internet_speed/README.md
Normal file
|
@ -0,0 +1,99 @@
|
|||
# Internet Speed Monitor Input Plugin
|
||||
|
||||
This plugin collects metrics about the internet speed on the system like
|
||||
download/upload speed, latency etc using the [speedtest.net service][speedtest].
|
||||
|
||||
⭐ Telegraf v1.20.0
|
||||
🏷️ network
|
||||
💻 all
|
||||
|
||||
[speedtest]: https://www.speedtest.net/
|
||||
|
||||
## Global configuration options <!-- @/docs/includes/plugin_config.md -->
|
||||
|
||||
In addition to the plugin-specific configuration settings, plugins support
|
||||
additional global and plugin configuration settings. These settings are used to
|
||||
modify metrics, tags, and field or create aliases and configure ordering, etc.
|
||||
See the [CONFIGURATION.md][CONFIGURATION.md] for more details.
|
||||
|
||||
[CONFIGURATION.md]: ../../../docs/CONFIGURATION.md#plugins
|
||||
|
||||
## Configuration
|
||||
|
||||
```toml @sample.conf
|
||||
# Monitors internet speed using speedtest.net service
|
||||
[[inputs.internet_speed]]
|
||||
## This plugin downloads many MB of data each time it is run. As such
|
||||
## consider setting a higher interval for this plugin to reduce the
|
||||
## demand on your internet connection.
|
||||
# interval = "60m"
|
||||
|
||||
## Enable to reduce memory usage
|
||||
# memory_saving_mode = false
|
||||
|
||||
## Caches the closest server location
|
||||
# cache = false
|
||||
|
||||
## Number of concurrent connections
|
||||
## By default or set to zero, the number of CPU cores is used. Use this to
|
||||
## reduce the impact on system performance or to increase the connections on
|
||||
## faster connections to ensure the fastest speed.
|
||||
# connections = 0
|
||||
|
||||
## Test mode
|
||||
## 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
|
||||
## Allows the user to exclude or include specific server IDs received by
|
||||
## speedtest-go. Values in the exclude option will be skipped over. Values in
|
||||
## the include option are the only options that will be picked from.
|
||||
##
|
||||
## See the list of servers speedtest-go will return at:
|
||||
## https://www.speedtest.net/api/js/servers?engine=js&limit=10
|
||||
##
|
||||
# server_id_exclude = []
|
||||
# server_id_include = []
|
||||
```
|
||||
|
||||
> [!TIP]
|
||||
> On some systems, the default settings may cause speed tests to fail. If this
|
||||
> affects your system, try enabling `memory_saving_mode`, which reduces the
|
||||
> memory requirements and the runtime of the test at the cost of a reduced
|
||||
> accuracy especially for fast (>30Mb/s) connections. Check the
|
||||
> [upstream documentation][docs] for details
|
||||
|
||||
[docs]: https://github.com/showwin/speedtest-go#memory-saving-mode
|
||||
|
||||
## Metrics
|
||||
|
||||
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 |
|
||||
| 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,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
|
||||
```
|
210
plugins/inputs/internet_speed/internet_speed.go
Normal file
210
plugins/inputs/internet_speed/internet_speed.go
Normal file
|
@ -0,0 +1,210 @@
|
|||
//go:generate ../../../tools/readme_config_includer/generator
|
||||
package internet_speed
|
||||
|
||||
import (
|
||||
"context"
|
||||
_ "embed"
|
||||
"errors"
|
||||
"fmt"
|
||||
"math"
|
||||
"os"
|
||||
"time"
|
||||
|
||||
"github.com/showwin/speedtest-go/speedtest"
|
||||
"github.com/showwin/speedtest-go/speedtest/transport"
|
||||
|
||||
"github.com/influxdata/telegraf"
|
||||
"github.com/influxdata/telegraf/filter"
|
||||
"github.com/influxdata/telegraf/internal"
|
||||
"github.com/influxdata/telegraf/plugins/inputs"
|
||||
)
|
||||
|
||||
//go:embed sample.conf
|
||||
var sampleConfig string
|
||||
|
||||
const (
|
||||
measurement = "internet_speed"
|
||||
testModeSingle = "single"
|
||||
testModeMulti = "multi"
|
||||
)
|
||||
|
||||
type InternetSpeed struct {
|
||||
ServerIDInclude []string `toml:"server_id_include"`
|
||||
ServerIDExclude []string `toml:"server_id_exclude"`
|
||||
EnableFileDownload bool `toml:"enable_file_download" deprecated:"1.25.0;1.35.0;use 'memory_saving_mode' instead"`
|
||||
MemorySavingMode bool `toml:"memory_saving_mode"`
|
||||
Cache bool `toml:"cache"`
|
||||
Connections int `toml:"connections"`
|
||||
TestMode string `toml:"test_mode"`
|
||||
|
||||
Log telegraf.Logger `toml:"-"`
|
||||
|
||||
server *speedtest.Server // The main(best) server
|
||||
servers speedtest.Servers // Auxiliary servers
|
||||
serverFilter filter.Filter
|
||||
}
|
||||
|
||||
func (*InternetSpeed) SampleConfig() string {
|
||||
return sampleConfig
|
||||
}
|
||||
|
||||
func (is *InternetSpeed) Init() error {
|
||||
switch is.TestMode {
|
||||
case testModeSingle, testModeMulti:
|
||||
case "":
|
||||
is.TestMode = testModeSingle
|
||||
default:
|
||||
return fmt.Errorf("unrecognized test mode: %q", is.TestMode)
|
||||
}
|
||||
|
||||
is.MemorySavingMode = is.MemorySavingMode || is.EnableFileDownload
|
||||
|
||||
var err error
|
||||
is.serverFilter, err = filter.NewIncludeExcludeFilterDefaults(is.ServerIDInclude, is.ServerIDExclude, false, false)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error compiling server ID filters: %w", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (is *InternetSpeed) Gather(acc telegraf.Accumulator) error {
|
||||
// If not caching, go find the closest server each time.
|
||||
// We will find the best server as the main server. And
|
||||
// the remaining servers will be auxiliary candidates.
|
||||
if !is.Cache || is.server == nil {
|
||||
if err := is.findClosestServer(); err != nil {
|
||||
return fmt.Errorf("unable to find closest server: %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
err := is.server.PingTest(nil)
|
||||
if err != nil {
|
||||
return fmt.Errorf("ping test failed: %w", err)
|
||||
}
|
||||
|
||||
analyzer := speedtest.NewPacketLossAnalyzer(&speedtest.PacketLossAnalyzerOptions{
|
||||
PacketSendingInterval: time.Millisecond * 100,
|
||||
SamplingDuration: time.Second * 15,
|
||||
})
|
||||
|
||||
var pLoss *transport.PLoss
|
||||
|
||||
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: %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()
|
||||
if err != nil {
|
||||
return fmt.Errorf("download test failed: %w", err)
|
||||
}
|
||||
err = is.server.UploadTest()
|
||||
if err != nil {
|
||||
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(pl *transport.PLoss) {
|
||||
pLoss = pl
|
||||
})
|
||||
if err != nil {
|
||||
is.Log.Warnf("packet loss test failed: %s", err)
|
||||
}
|
||||
}
|
||||
|
||||
packetLoss := -1.0
|
||||
if pLoss != nil {
|
||||
packetLoss = pLoss.LossPercent()
|
||||
}
|
||||
|
||||
fields := map[string]any{
|
||||
"download": is.server.DLSpeed.Mbps(),
|
||||
"upload": is.server.ULSpeed.Mbps(),
|
||||
"latency": timeDurationMillisecondToFloat64(is.server.Latency),
|
||||
"jitter": timeDurationMillisecondToFloat64(is.server.Jitter),
|
||||
"packet_loss": packetLoss,
|
||||
"location": is.server.Name,
|
||||
}
|
||||
tags := map[string]string{
|
||||
"server_id": is.server.ID,
|
||||
"source": is.server.Host,
|
||||
"test_mode": is.TestMode,
|
||||
}
|
||||
// Recycle the history of each test to prevent data backlog.
|
||||
is.server.Context.Reset()
|
||||
acc.AddFields(measurement, fields, tags)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (is *InternetSpeed) findClosestServer() error {
|
||||
proto := speedtest.HTTP
|
||||
if os.Getegid() <= 0 {
|
||||
proto = speedtest.ICMP
|
||||
}
|
||||
|
||||
client := speedtest.New(speedtest.WithUserConfig(&speedtest.UserConfig{
|
||||
UserAgent: internal.ProductToken(),
|
||||
PingMode: proto,
|
||||
SavingMode: is.MemorySavingMode,
|
||||
}))
|
||||
if is.Connections > 0 {
|
||||
client.SetNThread(is.Connections)
|
||||
}
|
||||
|
||||
var err error
|
||||
is.servers, err = client.FetchServers()
|
||||
if err != nil {
|
||||
return fmt.Errorf("fetching server list failed: %w", err)
|
||||
}
|
||||
|
||||
if len(is.servers) < 1 {
|
||||
return errors.New("no servers found")
|
||||
}
|
||||
|
||||
// Return the first match or the server with the lowest latency
|
||||
// when filter mismatch all servers.
|
||||
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 minLatency > server.Latency.Milliseconds() {
|
||||
minLatency = server.Latency.Milliseconds()
|
||||
selectIndex = index
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if selectIndex != -1 {
|
||||
is.server = is.servers[selectIndex]
|
||||
is.Log.Debugf("using server %s in %s (%s)\n", is.server.ID, is.server.Name, is.server.Host)
|
||||
return nil
|
||||
}
|
||||
|
||||
return errors.New("no server set: filter excluded all servers or no available server found")
|
||||
}
|
||||
|
||||
func timeDurationMillisecondToFloat64(d time.Duration) float64 {
|
||||
return float64(d) / float64(time.Millisecond)
|
||||
}
|
||||
|
||||
func init() {
|
||||
inputs.Add("internet_speed", func() telegraf.Input {
|
||||
return &InternetSpeed{}
|
||||
})
|
||||
}
|
41
plugins/inputs/internet_speed/internet_speed_test.go
Normal file
41
plugins/inputs/internet_speed/internet_speed_test.go
Normal file
|
@ -0,0 +1,41 @@
|
|||
package internet_speed
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"github.com/influxdata/telegraf/testutil"
|
||||
)
|
||||
|
||||
func TestGathering(t *testing.T) {
|
||||
if testing.Short() {
|
||||
t.Skip("Skipping network-dependent test in short mode.")
|
||||
}
|
||||
internetSpeed := &InternetSpeed{
|
||||
MemorySavingMode: true,
|
||||
Log: testutil.Logger{},
|
||||
}
|
||||
require.NoError(t, internetSpeed.Init())
|
||||
|
||||
acc := &testutil.Accumulator{}
|
||||
require.NoError(t, internetSpeed.Gather(acc))
|
||||
}
|
||||
|
||||
func TestDataGen(t *testing.T) {
|
||||
if testing.Short() {
|
||||
t.Skip("Skipping network-dependent test in short mode.")
|
||||
}
|
||||
internetSpeed := &InternetSpeed{
|
||||
MemorySavingMode: true,
|
||||
Log: testutil.Logger{},
|
||||
}
|
||||
require.NoError(t, internetSpeed.Init())
|
||||
|
||||
acc := &testutil.Accumulator{}
|
||||
require.NoError(t, internetSpeed.Gather(acc))
|
||||
|
||||
metric, ok := acc.Get("internet_speed")
|
||||
require.True(t, ok)
|
||||
acc.AssertContainsTaggedFields(t, "internet_speed", metric.Fields, metric.Tags)
|
||||
}
|
36
plugins/inputs/internet_speed/sample.conf
Normal file
36
plugins/inputs/internet_speed/sample.conf
Normal file
|
@ -0,0 +1,36 @@
|
|||
# Monitors internet speed using speedtest.net service
|
||||
[[inputs.internet_speed]]
|
||||
## This plugin downloads many MB of data each time it is run. As such
|
||||
## consider setting a higher interval for this plugin to reduce the
|
||||
## demand on your internet connection.
|
||||
# interval = "60m"
|
||||
|
||||
## Enable to reduce memory usage
|
||||
# memory_saving_mode = false
|
||||
|
||||
## Caches the closest server location
|
||||
# cache = false
|
||||
|
||||
## Number of concurrent connections
|
||||
## By default or set to zero, the number of CPU cores is used. Use this to
|
||||
## reduce the impact on system performance or to increase the connections on
|
||||
## faster connections to ensure the fastest speed.
|
||||
# connections = 0
|
||||
|
||||
## Test mode
|
||||
## 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
|
||||
## Allows the user to exclude or include specific server IDs received by
|
||||
## speedtest-go. Values in the exclude option will be skipped over. Values in
|
||||
## the include option are the only options that will be picked from.
|
||||
##
|
||||
## See the list of servers speedtest-go will return at:
|
||||
## https://www.speedtest.net/api/js/servers?engine=js&limit=10
|
||||
##
|
||||
# server_id_exclude = []
|
||||
# server_id_include = []
|
Loading…
Add table
Add a link
Reference in a new issue