diff --git a/CHANGELOG.md b/CHANGELOG.md index 59eca9832..0c75a6512 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,16 @@ # Changelog +## Unreleased + +### Important Changes + +- [PR #15186](https://github.com/influxdata/telegraf/pull/15186) changes the + meaning of `inputs.procstat` fields `read_bytes` and `write_bytes` on Linux + to now contain _all_ I/O operations for consistency with other + operating-systems. The previous values are output as `disk_read_bytes` and + `disk_write_bytes` measuring _only_ the I/O on the storage layer. + ## v1.30.2 [2024-04-22] ### Important Changes diff --git a/plugins/inputs/procstat/README.md b/plugins/inputs/procstat/README.md index 1970c0719..5217df6f0 100644 --- a/plugins/inputs/procstat/README.md +++ b/plugins/inputs/procstat/README.md @@ -159,6 +159,8 @@ Below are an example set of tags and fields: - cpu_time_system (float) - cpu_time_user (float) - cpu_usage (float) + - disk_read_bytes (int, Linux only, *telegraf* may need to be ran as **root**) + - disk_write_bytes (int, Linux only, *telegraf* may need to be ran as **root**) - involuntary_context_switches (int) - major_faults (int) - memory_anonymous (int) diff --git a/plugins/inputs/procstat/os_linux.go b/plugins/inputs/procstat/os_linux.go index 673f910fb..2b25e7be7 100644 --- a/plugins/inputs/procstat/os_linux.go +++ b/plugins/inputs/procstat/os_linux.go @@ -6,6 +6,9 @@ import ( "context" "errors" "fmt" + "os" + + "github.com/prometheus/procfs" "github.com/coreos/go-systemd/v22/dbus" "github.com/shirou/gopsutil/v3/process" @@ -76,3 +79,27 @@ func findBySystemdUnits(units []string) ([]processGroup, error) { func findByWindowsServices(_ []string) ([]processGroup, error) { return nil, nil } + +func collectTotalReadWrite(proc Process) (r, w uint64, err error) { + path := procfs.DefaultMountPoint + if hp := os.Getenv("HOST_PROC"); hp != "" { + path = hp + } + + fs, err := procfs.NewFS(path) + if err != nil { + return 0, 0, err + } + + p, err := fs.Proc(int(proc.PID())) + if err != nil { + return 0, 0, err + } + + stat, err := p.IO() + if err != nil { + return 0, 0, err + } + + return stat.RChar, stat.WChar, nil +} diff --git a/plugins/inputs/procstat/os_others.go b/plugins/inputs/procstat/os_others.go index d9408a158..105226940 100644 --- a/plugins/inputs/procstat/os_others.go +++ b/plugins/inputs/procstat/os_others.go @@ -25,3 +25,7 @@ func findBySystemdUnits(_ []string) ([]processGroup, error) { func findByWindowsServices(_ []string) ([]processGroup, error) { return nil, nil } + +func collectTotalReadWrite(_ Process) (r, w uint64, err error) { + return 0, 0, errors.ErrUnsupported +} diff --git a/plugins/inputs/procstat/os_windows.go b/plugins/inputs/procstat/os_windows.go index 7f1b29830..e93bcf58b 100644 --- a/plugins/inputs/procstat/os_windows.go +++ b/plugins/inputs/procstat/os_windows.go @@ -82,3 +82,7 @@ func findByWindowsServices(services []string) ([]processGroup, error) { return groups, nil } + +func collectTotalReadWrite(_ Process) (r, w uint64, err error) { + return 0, 0, errors.ErrUnsupported +} diff --git a/plugins/inputs/procstat/process.go b/plugins/inputs/procstat/process.go index 74342d50c..e2b227a0e 100644 --- a/plugins/inputs/procstat/process.go +++ b/plugins/inputs/procstat/process.go @@ -104,6 +104,15 @@ func (p *Proc) Metric(prefix string, tagging map[string]bool, solarisMode bool) fields[prefix+"write_bytes"] = io.WriteBytes } + // Linux fixup for gopsutils exposing the disk-only-IO instead of the total + // I/O as for example on Windows + if rc, wc, err := collectTotalReadWrite(p); err == nil { + fields[prefix+"read_bytes"] = rc + fields[prefix+"write_bytes"] = wc + fields[prefix+"disk_read_bytes"] = io.ReadBytes + fields[prefix+"disk_write_bytes"] = io.WriteBytes + } + createdAt, err := p.CreateTime() // returns epoch in ms if err == nil { fields[prefix+"created_at"] = createdAt * 1000000 // ms to ns diff --git a/plugins/inputs/procstat/procstat_test.go b/plugins/inputs/procstat/procstat_test.go index 922306669..3cc02b920 100644 --- a/plugins/inputs/procstat/procstat_test.go +++ b/plugins/inputs/procstat/procstat_test.go @@ -347,8 +347,6 @@ func TestGather_ProcessName(t *testing.T) { var acc testutil.Accumulator require.NoError(t, p.Gather(&acc)) - - testutil.PrintMetrics(acc.GetTelegrafMetrics()) require.Equal(t, "custom_name", acc.TagValue("procstat", "process_name")) testutil.RequireMetricsEqual(t, expected, acc.GetTelegrafMetrics(), testutil.IgnoreTime()) }