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
54
plugins/inputs/system/README.md
Normal file
54
plugins/inputs/system/README.md
Normal 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
|
||||
```
|
3
plugins/inputs/system/sample.conf
Normal file
3
plugins/inputs/system/sample.conf
Normal file
|
@ -0,0 +1,3 @@
|
|||
# Read metrics about system load & uptime
|
||||
[[inputs.system]]
|
||||
# no configuration
|
117
plugins/inputs/system/system.go
Normal file
117
plugins/inputs/system/system.go
Normal 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{}
|
||||
})
|
||||
}
|
64
plugins/inputs/system/system_test.go
Normal file
64
plugins/inputs/system/system_test.go
Normal 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)
|
||||
})
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue