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
207
plugins/inputs/kernel/kernel.go
Normal file
207
plugins/inputs/kernel/kernel.go
Normal file
|
@ -0,0 +1,207 @@
|
|||
//go:generate ../../../tools/readme_config_includer/generator
|
||||
//go:build linux
|
||||
|
||||
package kernel
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
_ "embed"
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strconv"
|
||||
|
||||
"github.com/prometheus/procfs"
|
||||
|
||||
"github.com/influxdata/telegraf"
|
||||
"github.com/influxdata/telegraf/plugins/inputs"
|
||||
)
|
||||
|
||||
//go:embed sample.conf
|
||||
var sampleConfig string
|
||||
|
||||
// /proc/stat file line prefixes to gather stats on:
|
||||
var (
|
||||
interrupts = []byte("intr")
|
||||
contextSwitches = []byte("ctxt")
|
||||
processesForked = []byte("processes")
|
||||
diskPages = []byte("page")
|
||||
bootTime = []byte("btime")
|
||||
)
|
||||
|
||||
type Kernel struct {
|
||||
ConfigCollect []string `toml:"collect"`
|
||||
|
||||
optCollect map[string]bool
|
||||
statFile string
|
||||
entropyStatFile string
|
||||
ksmStatsDir string
|
||||
psiDir string
|
||||
procfs procfs.FS
|
||||
}
|
||||
|
||||
func (*Kernel) SampleConfig() string {
|
||||
return sampleConfig
|
||||
}
|
||||
|
||||
func (k *Kernel) Init() error {
|
||||
k.optCollect = make(map[string]bool, len(k.ConfigCollect))
|
||||
for _, v := range k.ConfigCollect {
|
||||
k.optCollect[v] = true
|
||||
}
|
||||
|
||||
if k.optCollect["ksm"] {
|
||||
if _, err := os.Stat(k.ksmStatsDir); os.IsNotExist(err) {
|
||||
// ksm probably not enabled in the kernel, bail out early
|
||||
return fmt.Errorf("directory %q does not exist. KSM is not enabled in this kernel", k.ksmStatsDir)
|
||||
}
|
||||
}
|
||||
if k.optCollect["psi"] {
|
||||
procdir := filepath.Dir(k.psiDir)
|
||||
var err error
|
||||
if k.procfs, err = procfs.NewFS(procdir); err != nil {
|
||||
// psi probably not supported in the kernel, bail out early
|
||||
return fmt.Errorf("failed to initialize procfs on %s: %w", procdir, err)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (k *Kernel) Gather(acc telegraf.Accumulator) error {
|
||||
data, err := getProcValueBytes(k.statFile)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
entropyValue, err := getProcValueInt(k.entropyStatFile)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
fields := make(map[string]interface{})
|
||||
|
||||
fields["entropy_avail"] = entropyValue
|
||||
|
||||
dataFields := bytes.Fields(data)
|
||||
for i, field := range dataFields {
|
||||
switch {
|
||||
case bytes.Equal(field, interrupts):
|
||||
m, err := strconv.ParseInt(string(dataFields[i+1]), 10, 64)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
fields["interrupts"] = m
|
||||
case bytes.Equal(field, contextSwitches):
|
||||
m, err := strconv.ParseInt(string(dataFields[i+1]), 10, 64)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
fields["context_switches"] = m
|
||||
case bytes.Equal(field, processesForked):
|
||||
m, err := strconv.ParseInt(string(dataFields[i+1]), 10, 64)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
fields["processes_forked"] = m
|
||||
case bytes.Equal(field, bootTime):
|
||||
m, err := strconv.ParseInt(string(dataFields[i+1]), 10, 64)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
fields["boot_time"] = m
|
||||
case bytes.Equal(field, diskPages):
|
||||
in, err := strconv.ParseInt(string(dataFields[i+1]), 10, 64)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
out, err := strconv.ParseInt(string(dataFields[i+2]), 10, 64)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
fields["disk_pages_in"] = in
|
||||
fields["disk_pages_out"] = out
|
||||
}
|
||||
}
|
||||
|
||||
if k.optCollect["ksm"] {
|
||||
stats := []string{
|
||||
"full_scans", "max_page_sharing",
|
||||
"merge_across_nodes", "pages_shared",
|
||||
"pages_sharing", "pages_to_scan",
|
||||
"pages_unshared", "pages_volatile",
|
||||
"run", "sleep_millisecs",
|
||||
"stable_node_chains", "stable_node_chains_prune_millisecs",
|
||||
"stable_node_dups", "use_zero_pages",
|
||||
}
|
||||
// these exist in very recent Linux versions only, but useful to include if there.
|
||||
extraStats := []string{"general_profit"}
|
||||
|
||||
for _, f := range stats {
|
||||
m, err := getProcValueInt(filepath.Join(k.ksmStatsDir, f))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
fields["ksm_"+f] = m
|
||||
}
|
||||
|
||||
for _, f := range extraStats {
|
||||
m, err := getProcValueInt(filepath.Join(k.ksmStatsDir, f))
|
||||
if err != nil {
|
||||
// if an extraStats metric doesn't exist in our kernel version, ignore it.
|
||||
continue
|
||||
}
|
||||
|
||||
fields["ksm_"+f] = m
|
||||
}
|
||||
}
|
||||
acc.AddCounter("kernel", fields, make(map[string]string))
|
||||
|
||||
if k.optCollect["psi"] {
|
||||
if err := k.gatherPressure(acc); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func getProcValueBytes(path string) ([]byte, error) {
|
||||
if _, err := os.Stat(path); os.IsNotExist(err) {
|
||||
return nil, fmt.Errorf("path %q does not exist", path)
|
||||
} else if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
data, err := os.ReadFile(path)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to read from %q: %w", path, err)
|
||||
}
|
||||
|
||||
return data, nil
|
||||
}
|
||||
|
||||
func getProcValueInt(path string) (int64, error) {
|
||||
data, err := getProcValueBytes(path)
|
||||
if err != nil {
|
||||
return -1, err
|
||||
}
|
||||
|
||||
m, err := strconv.ParseInt(string(bytes.TrimSpace(data)), 10, 64)
|
||||
if err != nil {
|
||||
return -1, fmt.Errorf("failed to parse %q as an integer: %w", data, err)
|
||||
}
|
||||
|
||||
return m, nil
|
||||
}
|
||||
|
||||
func init() {
|
||||
inputs.Add("kernel", func() telegraf.Input {
|
||||
return &Kernel{
|
||||
statFile: "/proc/stat",
|
||||
entropyStatFile: "/proc/sys/kernel/random/entropy_avail",
|
||||
ksmStatsDir: "/sys/kernel/mm/ksm",
|
||||
psiDir: "/proc/pressure",
|
||||
}
|
||||
})
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue