feat(inputs.procstat): Report consistent I/O on Linux (#15186)

This commit is contained in:
Sven Rebhan 2024-04-23 10:50:36 -04:00 committed by GitHub
parent bfda888453
commit 46dbab0c0d
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
7 changed files with 56 additions and 2 deletions

View File

@ -1,6 +1,16 @@
<!-- markdownlint-disable MD024 -->
# 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

View File

@ -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)

View File

@ -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
}

View File

@ -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
}

View File

@ -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
}

View File

@ -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

View File

@ -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())
}