1
0
Fork 0

Adding upstream version 1.34.4.

Signed-off-by: Daniel Baumann <daniel@debian.org>
This commit is contained in:
Daniel Baumann 2025-05-24 07:26:29 +02:00
parent e393c3af3f
commit 4978089aab
Signed by: daniel
GPG key ID: FBB4F0E80A80222F
4963 changed files with 677545 additions and 0 deletions

View file

@ -0,0 +1,54 @@
# System Input Plugin
The system plugin gathers general stats on system load, uptime,
and number of users logged in. It is similar to the unix `uptime` command.
Number of CPUs is obtained from the /proc/cpuinfo file.
## 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
# Read metrics about system load & uptime
[[inputs.system]]
# no configuration
```
### Permissions
The `n_users` field requires read access to `/var/run/utmp`, and may require the
`telegraf` user to be added to the `utmp` group on some systems. If this file
does not exist `n_users` will be skipped.
The `n_unique_users` shows the count of unique usernames logged in. This way if
a user has multiple sessions open/started they would only get counted once. The
same requirements for `n_users` apply.
## Metrics
- system
- fields:
- load1 (float)
- load15 (float)
- load5 (float)
- n_users (integer)
- n_unique_users (integer)
- n_cpus (integer)
- uptime (integer, seconds)
- uptime_format (string, deprecated in 1.10, use `uptime` field)
## Example Output
```text
system,host=tyrion load1=3.72,load5=2.4,load15=2.1,n_users=3i,n_cpus=4i 1483964144000000000
system,host=tyrion uptime=1249632i 1483964144000000000
system,host=tyrion uptime_format="14 days, 11:07" 1483964144000000000
```

View file

@ -0,0 +1,3 @@
# Read metrics about system load & uptime
[[inputs.system]]
# no configuration

View file

@ -0,0 +1,117 @@
//go:generate ../../../tools/readme_config_includer/generator
package system
import (
"bufio"
"bytes"
_ "embed"
"fmt"
"os"
"strings"
"time"
"github.com/shirou/gopsutil/v4/cpu"
"github.com/shirou/gopsutil/v4/host"
"github.com/shirou/gopsutil/v4/load"
"github.com/influxdata/telegraf"
"github.com/influxdata/telegraf/plugins/inputs"
)
//go:embed sample.conf
var sampleConfig string
type System struct {
Log telegraf.Logger `toml:"-"`
}
func (*System) SampleConfig() string {
return sampleConfig
}
func (s *System) Gather(acc telegraf.Accumulator) error {
loadavg, err := load.Avg()
if err != nil && !strings.Contains(err.Error(), "not implemented") {
return err
}
numCPUs, err := cpu.Counts(true)
if err != nil {
return err
}
fields := map[string]interface{}{
"load1": loadavg.Load1,
"load5": loadavg.Load5,
"load15": loadavg.Load15,
"n_cpus": numCPUs,
}
users, err := host.Users()
if err == nil {
fields["n_users"] = len(users)
fields["n_unique_users"] = findUniqueUsers(users)
} else if os.IsNotExist(err) {
s.Log.Debugf("Reading users: %s", err.Error())
} else if os.IsPermission(err) {
s.Log.Debug(err.Error())
}
now := time.Now()
acc.AddGauge("system", fields, nil, now)
uptime, err := host.Uptime()
if err != nil {
return err
}
acc.AddCounter("system", map[string]interface{}{
"uptime": uptime,
}, nil, now)
acc.AddFields("system", map[string]interface{}{
"uptime_format": formatUptime(uptime),
}, nil, now)
return nil
}
func findUniqueUsers(userStats []host.UserStat) int {
uniqueUsers := make(map[string]bool)
for _, userstat := range userStats {
if _, ok := uniqueUsers[userstat.User]; !ok {
uniqueUsers[userstat.User] = true
}
}
return len(uniqueUsers)
}
func formatUptime(uptime uint64) string {
buf := new(bytes.Buffer)
w := bufio.NewWriter(buf)
days := uptime / (60 * 60 * 24)
if days != 0 {
s := ""
if days > 1 {
s = "s"
}
fmt.Fprintf(w, "%d day%s, ", days, s)
}
minutes := uptime / 60
hours := minutes / 60
hours %= 24
minutes %= 60
fmt.Fprintf(w, "%2d:%02d", hours, minutes)
w.Flush()
return buf.String()
}
func init() {
inputs.Add("system", func() telegraf.Input {
return &System{}
})
}

View file

@ -0,0 +1,64 @@
package system
import (
"testing"
"github.com/shirou/gopsutil/v4/host"
"github.com/stretchr/testify/require"
)
func TestUniqueUsers(t *testing.T) {
tests := []struct {
name string
expected int
data []host.UserStat
}{
{
name: "single entry",
expected: 1,
data: []host.UserStat{
{User: "root"},
},
},
{
name: "empty entry",
expected: 0,
},
{
name: "all duplicates",
expected: 1,
data: []host.UserStat{
{User: "root"},
{User: "root"},
{User: "root"},
},
},
{
name: "all unique",
expected: 3,
data: []host.UserStat{
{User: "root"},
{User: "ubuntu"},
{User: "ec2-user"},
},
},
{
name: "mix of dups",
expected: 3,
data: []host.UserStat{
{User: "root"},
{User: "ubuntu"},
{User: "ubuntu"},
{User: "ubuntu"},
{User: "ec2-user"},
{User: "ec2-user"},
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
actual := findUniqueUsers(tt.data)
require.Equal(t, tt.expected, actual, tt.name)
})
}
}