From 2dd46922517c61f36e0029d27866d86649b839a1 Mon Sep 17 00:00:00 2001 From: Sven Rebhan Date: Thu, 18 Apr 2024 17:43:26 +0200 Subject: [PATCH 1/3] feat(inputs.procstat): Add fields for cached read/write bytes --- plugins/inputs/procstat/os_linux.go | 27 ++++++++++++++++++++++++ plugins/inputs/procstat/os_others.go | 4 ++++ plugins/inputs/procstat/os_windows.go | 4 ++++ plugins/inputs/procstat/process.go | 5 +++++ plugins/inputs/procstat/procstat_test.go | 2 -- 5 files changed, 40 insertions(+), 2 deletions(-) diff --git a/plugins/inputs/procstat/os_linux.go b/plugins/inputs/procstat/os_linux.go index 673f910fb122b..b128deefd757e 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 collectCachedReadWrite(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 d9408a1583bbe..e018c17c43064 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 collectCachedReadWrite(_ 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 7f1b298305516..847b56cc18794 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 collectCachedReadWrite(_ 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 74342d50c3e22..d8a7ce0a67791 100644 --- a/plugins/inputs/procstat/process.go +++ b/plugins/inputs/procstat/process.go @@ -104,6 +104,11 @@ func (p *Proc) Metric(prefix string, tagging map[string]bool, solarisMode bool) fields[prefix+"write_bytes"] = io.WriteBytes } + if rc, wc, err := collectCachedReadWrite(p); err == nil { + fields[prefix+"cached_read_bytes"] = rc + fields[prefix+"cached_write_bytes"] = wc + } + 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 922306669463c..3cc02b920efdb 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()) } From 9aef0fb7c3cc72935dd22aa1d274a5926531e09d Mon Sep 17 00:00:00 2001 From: Sven Rebhan Date: Fri, 19 Apr 2024 17:44:22 +0200 Subject: [PATCH 2/3] Correct field naming --- plugins/inputs/procstat/README.md | 2 ++ plugins/inputs/procstat/os_linux.go | 2 +- plugins/inputs/procstat/os_others.go | 2 +- plugins/inputs/procstat/os_windows.go | 2 +- plugins/inputs/procstat/process.go | 10 +++++++--- 5 files changed, 12 insertions(+), 6 deletions(-) diff --git a/plugins/inputs/procstat/README.md b/plugins/inputs/procstat/README.md index 1970c07196938..5217df6f0afdd 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 b128deefd757e..2b25e7be7fe11 100644 --- a/plugins/inputs/procstat/os_linux.go +++ b/plugins/inputs/procstat/os_linux.go @@ -80,7 +80,7 @@ func findByWindowsServices(_ []string) ([]processGroup, error) { return nil, nil } -func collectCachedReadWrite(proc Process) (r, w uint64, err error) { +func collectTotalReadWrite(proc Process) (r, w uint64, err error) { path := procfs.DefaultMountPoint if hp := os.Getenv("HOST_PROC"); hp != "" { path = hp diff --git a/plugins/inputs/procstat/os_others.go b/plugins/inputs/procstat/os_others.go index e018c17c43064..105226940e0f5 100644 --- a/plugins/inputs/procstat/os_others.go +++ b/plugins/inputs/procstat/os_others.go @@ -26,6 +26,6 @@ func findByWindowsServices(_ []string) ([]processGroup, error) { return nil, nil } -func collectCachedReadWrite(_ Process) (r, w uint64, err error) { +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 847b56cc18794..e93bcf58b8f0b 100644 --- a/plugins/inputs/procstat/os_windows.go +++ b/plugins/inputs/procstat/os_windows.go @@ -83,6 +83,6 @@ func findByWindowsServices(services []string) ([]processGroup, error) { return groups, nil } -func collectCachedReadWrite(_ Process) (r, w uint64, err error) { +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 d8a7ce0a67791..e2b227a0e853b 100644 --- a/plugins/inputs/procstat/process.go +++ b/plugins/inputs/procstat/process.go @@ -104,9 +104,13 @@ func (p *Proc) Metric(prefix string, tagging map[string]bool, solarisMode bool) fields[prefix+"write_bytes"] = io.WriteBytes } - if rc, wc, err := collectCachedReadWrite(p); err == nil { - fields[prefix+"cached_read_bytes"] = rc - fields[prefix+"cached_write_bytes"] = wc + // 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 From 4ab2dd82551e28f908a57148411358bf62cef56a Mon Sep 17 00:00:00 2001 From: Sven Rebhan Date: Tue, 23 Apr 2024 16:02:12 +0200 Subject: [PATCH 3/3] Document change in field-semantics --- CHANGELOG.md | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 59eca9832d5e9..0c75a651265a7 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