diff --git a/NOTICE.txt b/NOTICE.txt index 31edf7da9e5a..1f38d7842f56 100644 --- a/NOTICE.txt +++ b/NOTICE.txt @@ -10941,11 +10941,11 @@ SOFTWARE -------------------------------------------------------------------------------- Dependency : github.com/elastic/elastic-agent-libs -Version: v0.26.2 +Version: v0.28.0 Licence type (autodetected): Apache-2.0 -------------------------------------------------------------------------------- -Contents of probable licence file $GOMODCACHE/github.com/elastic/elastic-agent-libs@v0.26.2/LICENSE: +Contents of probable licence file $GOMODCACHE/github.com/elastic/elastic-agent-libs@v0.28.0/LICENSE: Apache License Version 2.0, January 2004 @@ -11152,11 +11152,11 @@ Contents of probable licence file $GOMODCACHE/github.com/elastic/elastic-agent-l -------------------------------------------------------------------------------- Dependency : github.com/elastic/elastic-agent-system-metrics -Version: v0.13.4 +Version: v0.13.5 Licence type (autodetected): Apache-2.0 -------------------------------------------------------------------------------- -Contents of probable licence file $GOMODCACHE/github.com/elastic/elastic-agent-system-metrics@v0.13.4/LICENSE.txt: +Contents of probable licence file $GOMODCACHE/github.com/elastic/elastic-agent-system-metrics@v0.13.5/LICENSE.txt: Apache License Version 2.0, January 2004 @@ -30674,13 +30674,13 @@ Contents of probable licence file $GOMODCACHE/go.uber.org/mock@v0.5.0/LICENSE: -------------------------------------------------------------------------------- Dependency : go.uber.org/zap -Version: v1.27.0 +Version: v1.27.1 Licence type (autodetected): MIT -------------------------------------------------------------------------------- -Contents of probable licence file $GOMODCACHE/go.uber.org/zap@v1.27.0/LICENSE: +Contents of probable licence file $GOMODCACHE/go.uber.org/zap@v1.27.1/LICENSE: -Copyright (c) 2016-2017 Uber Technologies, Inc. +Copyright (c) 2016-2024 Uber Technologies, Inc. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/changelog/fragments/1765878935-metricbeat-cgroup-memory-pressure.yaml b/changelog/fragments/1765878935-metricbeat-cgroup-memory-pressure.yaml new file mode 100644 index 000000000000..24d32552676c --- /dev/null +++ b/changelog/fragments/1765878935-metricbeat-cgroup-memory-pressure.yaml @@ -0,0 +1,45 @@ +# REQUIRED +# Kind can be one of: +# - breaking-change: a change to previously-documented behavior +# - deprecation: functionality that is being removed in a later release +# - bug-fix: fixes a problem in a previous version +# - enhancement: extends functionality but does not break or fix existing behavior +# - feature: new functionality +# - known-issue: problems that we are aware of in a given version +# - security: impacts on the security of a product or a user’s deployment. +# - upgrade: important information for someone upgrading from a prior version +# - other: does not fit into any of the other categories +kind: enhancement + +# REQUIRED for all kinds +# Change summary; a 80ish characters long description of the change. +summary: Report memory pressure stall information (PSI) for cgroup v2 + +# REQUIRED for breaking-change, deprecation, known-issue +# Long description; in case the summary is not enough to describe the change +# this field accommodate a description without length limits. +description: "Add memory PSI metrics to system.process.cgroup, complementing existing CPU and IO pressure metrics for cgroupv2" + +# REQUIRED for breaking-change, deprecation, known-issue +# impact: + +# REQUIRED for breaking-change, deprecation, known-issue +# action: + +# REQUIRED for all kinds +# Affected component; usually one of "elastic-agent", "fleet-server", "filebeat", "metricbeat", "auditbeat", "all", etc. +component: metricbeat + +# AUTOMATED +# OPTIONAL to manually add other PR URLs +# PR URL: A link the PR that added the changeset. +# If not present is automatically filled by the tooling finding the PR where this changelog fragment has been added. +# NOTE: the tooling supports backports, so it's able to fill the original PR number instead of the backport PR number. +# Please provide it if you are adding a fragment for a different PR. +# pr: https://github.com/owner/repo/1234 + +# AUTOMATED +# OPTIONAL to manually add other issue URLs +# Issue URL; optional; the GitHub issue related to this changeset (either closes or is part of). +# If not present is automatically filled by the tooling with the issue linked to the PR number. +# issue: https://github.com/owner/repo/1234 diff --git a/docs/reference/metricbeat/exported-fields-system.md b/docs/reference/metricbeat/exported-fields-system.md index 6a7696e1d860..2b0ac446efd5 100644 --- a/docs/reference/metricbeat/exported-fields-system.md +++ b/docs/reference/metricbeat/exported-fields-system.md @@ -1811,6 +1811,90 @@ number of times the controller tripped a given usage level format: bytes +## pressure [_pressure] + +```{applies_to} +stack: ga 9.3.0 +``` + +Pressure (resource contention) stats. + +## some [_some] + +```{applies_to} +stack: ga 9.3.0 +``` + +Share of time in which at least some tasks are stalled on a given resource + +**`system.process.cgroup.memory.pressure.some.10.pct`** +: Pressure over 10 seconds + + type: float + + format: percent + + +**`system.process.cgroup.memory.pressure.some.60.pct`** +: Pressure over 60 seconds + + type: float + + format: percent + + +**`system.process.cgroup.memory.pressure.some.300.pct`** +: Pressure over 300 seconds + + type: float + + format: percent + + +**`system.process.cgroup.memory.pressure.some.total`** +: total Some pressure time + + type: long + + +## full [_full] + +```{applies_to} +stack: ga 9.3.0 +``` + +Share of time in which all non-idle tasks are stalled on a given resource simultaneously + +**`system.process.cgroup.memory.pressure.full.10.pct`** +: Pressure over 10 seconds + + type: float + + format: percent + + +**`system.process.cgroup.memory.pressure.full.60.pct`** +: Pressure over 60 seconds + + type: float + + format: percent + + +**`system.process.cgroup.memory.pressure.full.300.pct`** +: Pressure over 300 seconds + + type: float + + format: percent + + +**`system.process.cgroup.memory.pressure.full.total`** +: total Full pressure time + + type: long + + ## blkio [_blkio] Block IO metrics. diff --git a/docs/reference/metricbeat/metricbeat-metricset-system-process.md b/docs/reference/metricbeat/metricbeat-metricset-system-process.md index 2c6367508227..a95f6a5e92e7 100644 --- a/docs/reference/metricbeat/metricbeat-metricset-system-process.md +++ b/docs/reference/metricbeat/metricbeat-metricset-system-process.md @@ -325,6 +325,32 @@ Here is an example document generated by this metricset: "workingset_refault_file": 0, "workingset_restore_anon": 0, "workingset_restore_file": 0 + }, + "pressure": { + "full": { + "10": { + "pct": 0 + }, + "300": { + "pct": 0 + }, + "60": { + "pct": 0 + }, + "total": 0 + }, + "some": { + "10": { + "pct": 0 + }, + "300": { + "pct": 0 + }, + "60": { + "pct": 0 + }, + "total": 0 + } } }, "path": "/user.slice/user-1000.slice/session-426.scope" diff --git a/go.mod b/go.mod index d6100e98a835..4f0a451c98dc 100644 --- a/go.mod +++ b/go.mod @@ -120,7 +120,7 @@ require ( go.elastic.co/go-licence-detector v0.7.0 go.etcd.io/bbolt v1.4.0 go.uber.org/multierr v1.11.0 // indirect - go.uber.org/zap v1.27.0 + go.uber.org/zap v1.27.1 golang.org/x/crypto v0.45.0 golang.org/x/mod v0.29.0 golang.org/x/net v0.47.0 @@ -172,8 +172,8 @@ require ( github.com/elastic/bayeux v1.0.5 github.com/elastic/ebpfevents v0.8.0 github.com/elastic/elastic-agent-autodiscover v0.10.0 - github.com/elastic/elastic-agent-libs v0.26.2 - github.com/elastic/elastic-agent-system-metrics v0.13.4 + github.com/elastic/elastic-agent-libs v0.28.0 + github.com/elastic/elastic-agent-system-metrics v0.13.5 github.com/elastic/go-elasticsearch/v8 v8.19.0 github.com/elastic/go-freelru v0.16.0 github.com/elastic/go-quark v0.3.0 diff --git a/go.sum b/go.sum index e93585742a1e..cb16569bee87 100644 --- a/go.sum +++ b/go.sum @@ -374,10 +374,10 @@ github.com/elastic/elastic-agent-autodiscover v0.10.0 h1:WJ4zl9uSfk1kHmn2B/0byQB github.com/elastic/elastic-agent-autodiscover v0.10.0/go.mod h1:Nf3zh9FcJ9nTTswTwDTUAqXmvQllOrNliM6xmORSxwE= github.com/elastic/elastic-agent-client/v7 v7.15.0 h1:nDB7v8TBoNuD6IIzC3z7Q0y+7bMgXoT2DsHfolO2CHE= github.com/elastic/elastic-agent-client/v7 v7.15.0/go.mod h1:6h+f9QdIr3GO2ODC0Y8+aEXRwzbA5W4eV4dd/67z7nI= -github.com/elastic/elastic-agent-libs v0.26.2 h1:zwytPWmTWSJG80oa9/5FJ6zue47ysI23eMo15LfeWy0= -github.com/elastic/elastic-agent-libs v0.26.2/go.mod h1:fc2noLqosmQorIGbatJfVeh4CL77yiP8ot16/5umeoM= -github.com/elastic/elastic-agent-system-metrics v0.13.4 h1:gX8VdlQyakPcPKFpD7uHv2QLRDyguuKfZgu0LE27V7c= -github.com/elastic/elastic-agent-system-metrics v0.13.4/go.mod h1:lB8veYWYBlA9eF6TahmPN87G1IEgWlbep7QSqLSW90U= +github.com/elastic/elastic-agent-libs v0.28.0 h1:UDL9aSxgjqC9TrHAEHgI8gtuhRYPM/1gSfh7ztHWWLw= +github.com/elastic/elastic-agent-libs v0.28.0/go.mod h1:0xUg7alsNE/WhY9DZRIdTYW75nqSHC1octIAg//j/PQ= +github.com/elastic/elastic-agent-system-metrics v0.13.5 h1:VPTkk3C0ixsgqhAS2S++0/BKe+X6tYn+GzHbBLVuiO4= +github.com/elastic/elastic-agent-system-metrics v0.13.5/go.mod h1:JNfnZrC0viAjlJRUzQKKuMpDlXgjXBn4WdWEXQF7jcA= github.com/elastic/elastic-transport-go/v8 v8.7.0 h1:OgTneVuXP2uip4BA658Xi6Hfw+PeIOod2rY3GVMGoVE= github.com/elastic/elastic-transport-go/v8 v8.7.0/go.mod h1:YLHer5cj0csTzNFXoNQ8qhtGY1GTvSqPnKWKaqQE3Hk= github.com/elastic/fsevents v0.0.0-20181029231046-e1d381a4d270 h1:cWPqxlPtir4RoQVCpGSRXmLqjEHpJKbR60rxh1nQZY4= @@ -1238,8 +1238,8 @@ go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN8 go.uber.org/ratelimit v0.3.1 h1:K4qVE+byfv/B3tC+4nYWP7v/6SimcO7HzHekoMNBma0= go.uber.org/ratelimit v0.3.1/go.mod h1:6euWsTB6U/Nb3X++xEUXA8ciPJvr19Q/0h1+oDcJhRk= go.uber.org/zap v1.24.0/go.mod h1:2kMP+WWQ8aoFoedH3T2sq6iJ2yDWpHbP0f6MQbS9Gkg= -go.uber.org/zap v1.27.0 h1:aJMhYGrd5QSmlpLMr2MftRKl7t8J8PTZPA732ud/XR8= -go.uber.org/zap v1.27.0/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E= +go.uber.org/zap v1.27.1 h1:08RqriUEv8+ArZRYSTXy1LeBScaMpVSTBhCeaZYfMYc= +go.uber.org/zap v1.27.1/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E= go.yaml.in/yaml/v2 v2.4.3 h1:6gvOSjQoTB3vt1l+CU+tSyi/HOjfOjRLJ4YwYZGwRO0= go.yaml.in/yaml/v2 v2.4.3/go.mod h1:zSxWcmIDjOzPXpjlTTbAsKokqkDNAVtZO0WOMiT90s8= go.yaml.in/yaml/v3 v3.0.4 h1:tfq32ie2Jv2UxXFdLJdh3jXuOzWiL1fo0bu/FbuKpbc= diff --git a/metricbeat/module/system/fields.go b/metricbeat/module/system/fields.go index 5ea6bd8b91ae..c2a546fbdf21 100644 --- a/metricbeat/module/system/fields.go +++ b/metricbeat/module/system/fields.go @@ -32,5 +32,5 @@ func init() { // AssetSystem returns asset data. // This is the base64 encoded zlib format compressed contents of module/system. func AssetSystem() string { - return "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" + return "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" } diff --git a/metricbeat/module/system/process/_meta/data.json b/metricbeat/module/system/process/_meta/data.json index 06d29b3d1556..f0c83bb11edd 100644 --- a/metricbeat/module/system/process/_meta/data.json +++ b/metricbeat/module/system/process/_meta/data.json @@ -218,6 +218,32 @@ "workingset_refault_file": 0, "workingset_restore_anon": 0, "workingset_restore_file": 0 + }, + "pressure": { + "full": { + "10": { + "pct": 0 + }, + "300": { + "pct": 0 + }, + "60": { + "pct": 0 + }, + "total": 0 + }, + "some": { + "10": { + "pct": 0 + }, + "300": { + "pct": 0 + }, + "60": { + "pct": 0 + }, + "total": 0 + } } }, "path": "/user.slice/user-1000.slice/session-426.scope" diff --git a/metricbeat/module/system/process/_meta/fields.yml b/metricbeat/module/system/process/_meta/fields.yml index f0dad4095208..890fb52e5fd4 100644 --- a/metricbeat/module/system/process/_meta/fields.yml +++ b/metricbeat/module/system/process/_meta/fields.yml @@ -693,6 +693,55 @@ description: > Memory that cannot be reclaimed, in bytes. + - name: pressure + type: group + description: Pressure (resource contention) stats. + version: + ga: 9.3.0 + fields: + - name: some + type: group + description: Share of time in which at least some tasks are stalled on a given resource + version: + ga: 9.3.0 + fields: + - name: 10.pct + type: float + format: percent + description: Pressure over 10 seconds + - name: 60.pct + type: float + format: percent + description: Pressure over 60 seconds + - name: 300.pct + type: float + format: percent + description: Pressure over 300 seconds + - name: total + type: long + description: total Some pressure time + - name: full + type: group + description: Share of time in which all non-idle tasks are stalled on a given resource simultaneously + version: + ga: 9.3.0 + fields: + - name: 10.pct + type: float + format: percent + description: Pressure over 10 seconds + - name: 60.pct + type: float + format: percent + description: Pressure over 60 seconds + - name: 300.pct + type: float + format: percent + description: Pressure over 300 seconds + - name: total + type: long + description: total Full pressure time + - name: blkio type: group description: Block IO metrics. diff --git a/metricbeat/module/system/process/process_test.go b/metricbeat/module/system/process/process_test.go index df558bb0d656..2e7c84da47ef 100644 --- a/metricbeat/module/system/process/process_test.go +++ b/metricbeat/module/system/process/process_test.go @@ -20,16 +20,20 @@ package process import ( + "errors" "os" "runtime" + "strconv" "testing" "time" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" "github.com/elastic/beats/v7/metricbeat/mb" mbtest "github.com/elastic/beats/v7/metricbeat/mb/testing" _ "github.com/elastic/beats/v7/metricbeat/module/system" + "github.com/elastic/elastic-agent-libs/mapstr" "github.com/elastic/elastic-agent-system-metrics/metric/system/process" ) @@ -79,15 +83,14 @@ func TestFetchDegradeOnPartial(t *testing.T) { } func TestFetchSinglePid(t *testing.T) { - cfg := getConfig() cfg["process.pid"] = os.Getpid() f := mbtest.NewReportingMetricSetV2Error(t, cfg) events, errs := mbtest.ReportingFetchV2Error(f) assert.Empty(t, errs) - assert.NotEmpty(t, events) - assert.Equal(t, os.Getpid(), events[0].RootFields["process"].(map[string]interface{})["pid"]) + require.NotEmpty(t, events) + assert.Equal(t, os.Getpid(), requireGetSubMap(t, events[0].RootFields, "process")["pid"]) assert.NotEmpty(t, events[0].MetricSetFields["cpu"]) } @@ -104,8 +107,115 @@ func TestData(t *testing.T) { } } -func getConfig() map[string]interface{} { - return map[string]interface{}{ +func TestCgroupPressure(t *testing.T) { + if runtime.GOOS != "linux" { + t.Skip("cgroup stats are only available on Linux") + } + + cfg := getConfig() + cfg["process.pid"] = getTestPid(t) + + f := mbtest.NewReportingMetricSetV2Error(t, cfg) + events, errs := mbtest.ReportingFetchV2Error(f) + assert.Empty(t, errs) + require.NotEmpty(t, events) + + // Get cgroup data from the event + event := events[0] + t.Logf("%s/%s event: %+v", f.Module().Name(), f.Name(), event) + cgroupData, err := event.MetricSetFields.GetValue("cgroup") + if errors.Is(err, mapstr.ErrKeyNotFound) { + t.Skip("cgroup data not available") + } + require.NoError(t, err) + + cgroup, ok := cgroupData.(map[string]any) + require.Truef(t, ok, "unexpected cgroup data type: %T", cgroupData) + + subsystems := []string{"cpu", "memory", "io"} + if cgroup["path"] == "/" { + // Sanity check: verify our assertion that the / cgroup result in no subsystem data. If these checks fail, it + // means a change in expected behavior and this test should be adjusted. + // Example command to test with / cgroup: + // sleep 60 & + // pid=$! + // sudo sh -c "echo $pid > /sys/fs/cgroup/cgroup.procs" + // cat /proc/$pid/cgroup + // MONITOR_PID=$pid go test -run TestCgroupPressure -v ./metricbeat/module/system/process + for _, subsystem := range subsystems { + assert.NotContains(t, cgroup, subsystem) + } + t.Skip("Process in / cgroup, skipping because of IgnoreRootCgroups") + } + + for _, subsystem := range subsystems { + t.Run(subsystem, func(t *testing.T) { + // Subsystem might not exist depending on cgroup configuration. + // For example, io accounting is disabled by default in systemd: + // https://www.freedesktop.org/software/systemd/man/latest/systemd-system.conf.html#DefaultMemoryAccounting= + if _, ok := cgroup[subsystem]; !ok { + t.Skipf("%s subsystem not available in this cgroup", subsystem) + } + controller := requireGetSubMap(t, cgroup, subsystem) + t.Run("pressure", func(t *testing.T) { + // Pressure might not exist, be nil, or be empty depending on kernel configuration + if _, ok := controller["pressure"]; !ok { + t.Skip("pressure data not available on this cgroup") + } + pressure := requireGetSubMap(t, controller, "pressure") + if pressure == nil { + // See https://github.com/elastic/elastic-agent-system-metrics/pull/276 + require.Equal(t, "io", subsystem, "only the io subsystem returns nil when unavailable") + t.Skip("pressure data not available on this cgroup") + } + for _, stall := range []string{"some", "full"} { + t.Run(stall, func(t *testing.T) { + checkPressure(t, pressure, stall) + }) + } + }) + }) + } +} + +func checkPressure(t *testing.T, pressure map[string]any, stall string) { + // Verify pressure structure has expected fields + stallMap := requireGetSubMap(t, pressure, stall) + + // Check for time window fields (10, 60, 300 seconds) + for _, window := range []string{"10", "60", "300"} { + windowMap := requireGetSubMap(t, stallMap, window) + + // Check for pct field + assert.Contains(t, windowMap, "pct", "expected pressure.%s.%s.pct to exist", stall, window) + } + + // Check for total field + assert.Contains(t, stallMap, "total", "expected pressure.%s.total to exist", stall) +} + +func requireGetSubMap(t *testing.T, m map[string]any, key string) map[string]any { + t.Helper() + require.Contains(t, m, key) + rawValue := m[key] + require.IsType(t, rawValue, map[string]any{}) + subMap, ok := rawValue.(map[string]any) + require.True(t, ok) + return subMap +} + +func getTestPid(t *testing.T) int { + t.Helper() + if targetPid := os.Getenv("MONITOR_PID"); targetPid != "" { + intPid, err := strconv.ParseInt(targetPid, 10, 32) + require.NoError(t, err, "error parsing MONITOR_PID") + return int(intPid) + } + return os.Getpid() +} + +func getConfig() map[string]any { + return map[string]any{ "module": "system", "metricsets": []string{"process"}, "processes": []string{".*"}, // in case we want a prettier looking example for data.json