diff --git a/.chloggen/add-process-memory-utilization-metric.yaml b/.chloggen/add-process-memory-utilization-metric.yaml new file mode 100755 index 000000000000..bcbbb60a35de --- /dev/null +++ b/.chloggen/add-process-memory-utilization-metric.yaml @@ -0,0 +1,16 @@ +# One of 'breaking', 'deprecation', 'new_component', 'enhancement', 'bug_fix' +change_type: enhancement + +# The name of the component, or a single word describing the area of concern, (e.g. filelogreceiver) +component: hostmetricsreceiver + +# A brief description of the change. Surround your text with quotes ("") if it needs to start with a backtick (`). +note: Add a new optional metric `process.memory.utilization` to the metrics scraped by the `process` scraper of the `hostmetrics` receiver. + +# One or more tracking issues related to the change +issues: [14084] + +# (Optional) One or more lines of additional information to render under the primary note. +# These lines will be padded with 2 spaces and then inserted directly into the document. +# Use pipe (|) for multiline entries. +subtext: diff --git a/receiver/hostmetricsreceiver/internal/scraper/processscraper/documentation.md b/receiver/hostmetricsreceiver/internal/scraper/processscraper/documentation.md index 4595700b57ba..5855aa5e5d42 100644 --- a/receiver/hostmetricsreceiver/internal/scraper/processscraper/documentation.md +++ b/receiver/hostmetricsreceiver/internal/scraper/processscraper/documentation.md @@ -102,6 +102,14 @@ The amount of physical memory in use. | ---- | ----------- | ---------- | ----------------------- | --------- | | By | Sum | Int | Cumulative | false | +### process.memory.utilization + +Percentage of total physical memory that is used by the process. + +| Unit | Metric Type | Value Type | +| ---- | ----------- | ---------- | +| 1 | Gauge | Double | + ### process.memory.virtual Virtual memory size. diff --git a/receiver/hostmetricsreceiver/internal/scraper/processscraper/internal/metadata/generated_metrics.go b/receiver/hostmetricsreceiver/internal/scraper/processscraper/internal/metadata/generated_metrics.go index 274041d1f857..d8d7810c7f28 100644 --- a/receiver/hostmetricsreceiver/internal/scraper/processscraper/internal/metadata/generated_metrics.go +++ b/receiver/hostmetricsreceiver/internal/scraper/processscraper/internal/metadata/generated_metrics.go @@ -45,6 +45,7 @@ type MetricsSettings struct { ProcessDiskIo MetricSettings `mapstructure:"process.disk.io"` ProcessMemoryPhysicalUsage MetricSettings `mapstructure:"process.memory.physical_usage"` ProcessMemoryUsage MetricSettings `mapstructure:"process.memory.usage"` + ProcessMemoryUtilization MetricSettings `mapstructure:"process.memory.utilization"` ProcessMemoryVirtual MetricSettings `mapstructure:"process.memory.virtual"` ProcessMemoryVirtualUsage MetricSettings `mapstructure:"process.memory.virtual_usage"` ProcessOpenFileDescriptors MetricSettings `mapstructure:"process.open_file_descriptors"` @@ -73,6 +74,9 @@ func DefaultMetricsSettings() MetricsSettings { ProcessMemoryUsage: MetricSettings{ Enabled: false, }, + ProcessMemoryUtilization: MetricSettings{ + Enabled: false, + }, ProcessMemoryVirtual: MetricSettings{ Enabled: false, }, @@ -514,6 +518,55 @@ func newMetricProcessMemoryUsage(settings MetricSettings) metricProcessMemoryUsa return m } +type metricProcessMemoryUtilization struct { + data pmetric.Metric // data buffer for generated metric. + settings MetricSettings // metric settings provided by user. + capacity int // max observed number of data points added to the metric. +} + +// init fills process.memory.utilization metric with initial data. +func (m *metricProcessMemoryUtilization) init() { + m.data.SetName("process.memory.utilization") + m.data.SetDescription("Percentage of total physical memory that is used by the process.") + m.data.SetUnit("1") + m.data.SetEmptyGauge() +} + +func (m *metricProcessMemoryUtilization) recordDataPoint(start pcommon.Timestamp, ts pcommon.Timestamp, val float64) { + if !m.settings.Enabled { + return + } + dp := m.data.Gauge().DataPoints().AppendEmpty() + dp.SetStartTimestamp(start) + dp.SetTimestamp(ts) + dp.SetDoubleValue(val) +} + +// updateCapacity saves max length of data point slices that will be used for the slice capacity. +func (m *metricProcessMemoryUtilization) updateCapacity() { + if m.data.Gauge().DataPoints().Len() > m.capacity { + m.capacity = m.data.Gauge().DataPoints().Len() + } +} + +// emit appends recorded metric data to a metrics slice and prepares it for recording another set of data points. +func (m *metricProcessMemoryUtilization) emit(metrics pmetric.MetricSlice) { + if m.settings.Enabled && m.data.Gauge().DataPoints().Len() > 0 { + m.updateCapacity() + m.data.MoveTo(metrics.AppendEmpty()) + m.init() + } +} + +func newMetricProcessMemoryUtilization(settings MetricSettings) metricProcessMemoryUtilization { + m := metricProcessMemoryUtilization{settings: settings} + if settings.Enabled { + m.data = pmetric.NewMetric() + m.init() + } + return m +} + type metricProcessMemoryVirtual struct { data pmetric.Metric // data buffer for generated metric. settings MetricSettings // metric settings provided by user. @@ -836,6 +889,7 @@ type MetricsBuilder struct { metricProcessDiskIo metricProcessDiskIo metricProcessMemoryPhysicalUsage metricProcessMemoryPhysicalUsage metricProcessMemoryUsage metricProcessMemoryUsage + metricProcessMemoryUtilization metricProcessMemoryUtilization metricProcessMemoryVirtual metricProcessMemoryVirtual metricProcessMemoryVirtualUsage metricProcessMemoryVirtualUsage metricProcessOpenFileDescriptors metricProcessOpenFileDescriptors @@ -873,6 +927,7 @@ func NewMetricsBuilder(ms MetricsSettings, settings receiver.CreateSettings, opt metricProcessDiskIo: newMetricProcessDiskIo(ms.ProcessDiskIo), metricProcessMemoryPhysicalUsage: newMetricProcessMemoryPhysicalUsage(ms.ProcessMemoryPhysicalUsage), metricProcessMemoryUsage: newMetricProcessMemoryUsage(ms.ProcessMemoryUsage), + metricProcessMemoryUtilization: newMetricProcessMemoryUtilization(ms.ProcessMemoryUtilization), metricProcessMemoryVirtual: newMetricProcessMemoryVirtual(ms.ProcessMemoryVirtual), metricProcessMemoryVirtualUsage: newMetricProcessMemoryVirtualUsage(ms.ProcessMemoryVirtualUsage), metricProcessOpenFileDescriptors: newMetricProcessOpenFileDescriptors(ms.ProcessOpenFileDescriptors), @@ -987,6 +1042,7 @@ func (mb *MetricsBuilder) EmitForResource(rmo ...ResourceMetricsOption) { mb.metricProcessDiskIo.emit(ils.Metrics()) mb.metricProcessMemoryPhysicalUsage.emit(ils.Metrics()) mb.metricProcessMemoryUsage.emit(ils.Metrics()) + mb.metricProcessMemoryUtilization.emit(ils.Metrics()) mb.metricProcessMemoryVirtual.emit(ils.Metrics()) mb.metricProcessMemoryVirtualUsage.emit(ils.Metrics()) mb.metricProcessOpenFileDescriptors.emit(ils.Metrics()) @@ -1042,6 +1098,11 @@ func (mb *MetricsBuilder) RecordProcessMemoryUsageDataPoint(ts pcommon.Timestamp mb.metricProcessMemoryUsage.recordDataPoint(mb.startTime, ts, val) } +// RecordProcessMemoryUtilizationDataPoint adds a data point to process.memory.utilization metric. +func (mb *MetricsBuilder) RecordProcessMemoryUtilizationDataPoint(ts pcommon.Timestamp, val float64) { + mb.metricProcessMemoryUtilization.recordDataPoint(mb.startTime, ts, val) +} + // RecordProcessMemoryVirtualDataPoint adds a data point to process.memory.virtual metric. func (mb *MetricsBuilder) RecordProcessMemoryVirtualDataPoint(ts pcommon.Timestamp, val int64) { mb.metricProcessMemoryVirtual.recordDataPoint(mb.startTime, ts, val) diff --git a/receiver/hostmetricsreceiver/internal/scraper/processscraper/internal/metadata/generated_metrics_test.go b/receiver/hostmetricsreceiver/internal/scraper/processscraper/internal/metadata/generated_metrics_test.go index 97bcb78f5b3f..4dc9177f183c 100644 --- a/receiver/hostmetricsreceiver/internal/scraper/processscraper/internal/metadata/generated_metrics_test.go +++ b/receiver/hostmetricsreceiver/internal/scraper/processscraper/internal/metadata/generated_metrics_test.go @@ -35,6 +35,8 @@ func TestDefaultMetrics(t *testing.T) { mb.RecordProcessMemoryUsageDataPoint(ts, 1) + mb.RecordProcessMemoryUtilizationDataPoint(ts, 1) + mb.RecordProcessMemoryVirtualDataPoint(ts, 1) enabledMetrics["process.memory.virtual_usage"] = true @@ -73,6 +75,7 @@ func TestAllMetrics(t *testing.T) { ProcessDiskIo: MetricSettings{Enabled: true}, ProcessMemoryPhysicalUsage: MetricSettings{Enabled: true}, ProcessMemoryUsage: MetricSettings{Enabled: true}, + ProcessMemoryUtilization: MetricSettings{Enabled: true}, ProcessMemoryVirtual: MetricSettings{Enabled: true}, ProcessMemoryVirtualUsage: MetricSettings{Enabled: true}, ProcessOpenFileDescriptors: MetricSettings{Enabled: true}, @@ -93,6 +96,7 @@ func TestAllMetrics(t *testing.T) { mb.RecordProcessDiskIoDataPoint(ts, 1, AttributeDirection(1)) mb.RecordProcessMemoryPhysicalUsageDataPoint(ts, 1) mb.RecordProcessMemoryUsageDataPoint(ts, 1) + mb.RecordProcessMemoryUtilizationDataPoint(ts, 1) mb.RecordProcessMemoryVirtualDataPoint(ts, 1) mb.RecordProcessMemoryVirtualUsageDataPoint(ts, 1) mb.RecordProcessOpenFileDescriptorsDataPoint(ts, 1) @@ -230,6 +234,17 @@ func TestAllMetrics(t *testing.T) { assert.Equal(t, pmetric.NumberDataPointValueTypeInt, dp.ValueType()) assert.Equal(t, int64(1), dp.IntValue()) validatedMetrics["process.memory.usage"] = struct{}{} + case "process.memory.utilization": + assert.Equal(t, pmetric.MetricTypeGauge, ms.At(i).Type()) + assert.Equal(t, 1, ms.At(i).Gauge().DataPoints().Len()) + assert.Equal(t, "Percentage of total physical memory that is used by the process.", ms.At(i).Description()) + assert.Equal(t, "1", ms.At(i).Unit()) + dp := ms.At(i).Gauge().DataPoints().At(0) + assert.Equal(t, start, dp.StartTimestamp()) + assert.Equal(t, ts, dp.Timestamp()) + assert.Equal(t, pmetric.NumberDataPointValueTypeDouble, dp.ValueType()) + assert.Equal(t, float64(1), dp.DoubleValue()) + validatedMetrics["process.memory.utilization"] = struct{}{} case "process.memory.virtual": assert.Equal(t, pmetric.MetricTypeSum, ms.At(i).Type()) assert.Equal(t, 1, ms.At(i).Sum().DataPoints().Len()) @@ -326,6 +341,7 @@ func TestNoMetrics(t *testing.T) { ProcessDiskIo: MetricSettings{Enabled: false}, ProcessMemoryPhysicalUsage: MetricSettings{Enabled: false}, ProcessMemoryUsage: MetricSettings{Enabled: false}, + ProcessMemoryUtilization: MetricSettings{Enabled: false}, ProcessMemoryVirtual: MetricSettings{Enabled: false}, ProcessMemoryVirtualUsage: MetricSettings{Enabled: false}, ProcessOpenFileDescriptors: MetricSettings{Enabled: false}, @@ -345,6 +361,7 @@ func TestNoMetrics(t *testing.T) { mb.RecordProcessDiskIoDataPoint(ts, 1, AttributeDirection(1)) mb.RecordProcessMemoryPhysicalUsageDataPoint(ts, 1) mb.RecordProcessMemoryUsageDataPoint(ts, 1) + mb.RecordProcessMemoryUtilizationDataPoint(ts, 1) mb.RecordProcessMemoryVirtualDataPoint(ts, 1) mb.RecordProcessMemoryVirtualUsageDataPoint(ts, 1) mb.RecordProcessOpenFileDescriptorsDataPoint(ts, 1) diff --git a/receiver/hostmetricsreceiver/internal/scraper/processscraper/metadata.yaml b/receiver/hostmetricsreceiver/internal/scraper/processscraper/metadata.yaml index 9ac66cfde466..8807229c3931 100644 --- a/receiver/hostmetricsreceiver/internal/scraper/processscraper/metadata.yaml +++ b/receiver/hostmetricsreceiver/internal/scraper/processscraper/metadata.yaml @@ -129,6 +129,13 @@ metrics: aggregation: cumulative monotonic: false + process.memory.utilization: + enabled: false + description: Percentage of total physical memory that is used by the process. + unit: 1 + gauge: + value_type: double + process.disk.io: enabled: true description: Disk bytes transferred. diff --git a/receiver/hostmetricsreceiver/internal/scraper/processscraper/process.go b/receiver/hostmetricsreceiver/internal/scraper/processscraper/process.go index e24f4267cb7b..e350469dc993 100644 --- a/receiver/hostmetricsreceiver/internal/scraper/processscraper/process.go +++ b/receiver/hostmetricsreceiver/internal/scraper/processscraper/process.go @@ -91,6 +91,7 @@ type processHandle interface { Times() (*cpu.TimesStat, error) Percent(time.Duration) (float64, error) MemoryInfo() (*process.MemoryInfoStat, error) + MemoryPercent() (float32, error) IOCounters() (*process.IOCountersStat, error) NumThreads() (int32, error) CreateTime() (int64, error) diff --git a/receiver/hostmetricsreceiver/internal/scraper/processscraper/process_scraper.go b/receiver/hostmetricsreceiver/internal/scraper/processscraper/process_scraper.go index 5818f886b43d..994127dbcc73 100644 --- a/receiver/hostmetricsreceiver/internal/scraper/processscraper/process_scraper.go +++ b/receiver/hostmetricsreceiver/internal/scraper/processscraper/process_scraper.go @@ -33,16 +33,17 @@ import ( ) const ( - cpuMetricsLen = 1 - memoryMetricsLen = 2 - diskMetricsLen = 1 - pagingMetricsLen = 1 - threadMetricsLen = 1 - contextSwitchMetricsLen = 1 - fileDescriptorMetricsLen = 1 - signalMetricsLen = 1 - - metricsLen = cpuMetricsLen + memoryMetricsLen + diskMetricsLen + pagingMetricsLen + threadMetricsLen + contextSwitchMetricsLen + fileDescriptorMetricsLen + signalMetricsLen + cpuMetricsLen = 1 + memoryMetricsLen = 2 + memoryUtilizationMetricsLen = 1 + diskMetricsLen = 1 + pagingMetricsLen = 1 + threadMetricsLen = 1 + contextSwitchMetricsLen = 1 + fileDescriptorMetricsLen = 1 + signalMetricsLen = 1 + + metricsLen = cpuMetricsLen + memoryMetricsLen + diskMetricsLen + memoryUtilizationMetricsLen + pagingMetricsLen + threadMetricsLen + contextSwitchMetricsLen + fileDescriptorMetricsLen + signalMetricsLen ) // scraper for Process Metrics @@ -118,6 +119,10 @@ func (s *scraper) scrape(_ context.Context) (pmetric.Metrics, error) { errs.AddPartial(memoryMetricsLen, fmt.Errorf("error reading memory info for process %q (pid %v): %w", md.executable.name, md.pid, err)) } + if err = s.scrapeAndAppendMemoryUtilizationMetric(now, md.handle); err != nil { + errs.AddPartial(memoryUtilizationMetricsLen, fmt.Errorf("error reading memory utilization for process %q (pid %v): %w", md.executable.name, md.pid, err)) + } + if err = s.scrapeAndAppendDiskIOMetric(now, md.handle); err != nil { errs.AddPartial(diskMetricsLen, fmt.Errorf("error reading disk usage for process %q (pid %v): %w", md.executable.name, md.pid, err)) } @@ -254,6 +259,21 @@ func (s *scraper) scrapeAndAppendMemoryUsageMetrics(now pcommon.Timestamp, handl return nil } +func (s *scraper) scrapeAndAppendMemoryUtilizationMetric(now pcommon.Timestamp, handle processHandle) error { + if !s.config.Metrics.ProcessMemoryUtilization.Enabled { + return nil + } + + memoryPercent, err := handle.MemoryPercent() + if err != nil { + return err + } + + s.mb.RecordProcessMemoryUtilizationDataPoint(now, float64(memoryPercent)) + + return nil +} + func (s *scraper) scrapeAndAppendDiskIOMetric(now pcommon.Timestamp, handle processHandle) error { if !s.config.Metrics.ProcessDiskIo.Enabled { return nil diff --git a/receiver/hostmetricsreceiver/internal/scraper/processscraper/process_scraper_test.go b/receiver/hostmetricsreceiver/internal/scraper/processscraper/process_scraper_test.go index e83e80e1967a..5fd200c49eaa 100644 --- a/receiver/hostmetricsreceiver/internal/scraper/processscraper/process_scraper_test.go +++ b/receiver/hostmetricsreceiver/internal/scraper/processscraper/process_scraper_test.go @@ -77,6 +77,12 @@ func TestScrape(t *testing.T) { enableLinuxOnlyMetrics(ms) }, }, + { + name: "Enable memory utilization", + mutateMetricsSettings: func(t *testing.T, ms *metadata.MetricsSettings) { + ms.ProcessMemoryUtilization.Enabled = true + }, + }, } const createTime = 100 @@ -130,6 +136,9 @@ func TestScrape(t *testing.T) { if metricsSettings.ProcessSignalsPending.Enabled { assertSignalsPendingMetricValid(t, md.ResourceMetrics(), expectedStartTime) } + if metricsSettings.ProcessMemoryUtilization.Enabled { + assertMemoryUtilizationMetricValid(t, md.ResourceMetrics(), expectedStartTime) + } if metricsSettings.ProcessThreads.Enabled { assertThreadsCountValid(t, md.ResourceMetrics(), expectedStartTime) } else { @@ -221,6 +230,14 @@ func assertSignalsPendingMetricValid(t *testing.T, resourceMetrics pmetric.Resou } } +func assertMemoryUtilizationMetricValid(t *testing.T, resourceMetrics pmetric.ResourceMetricsSlice, startTime pcommon.Timestamp) { + memoryUtilizationMetric := getMetric(t, "process.memory.utilization", resourceMetrics) + + if startTime != 0 { + internal.AssertGaugeMetricStartTimeEquals(t, memoryUtilizationMetric, startTime) + } +} + func assertThreadsCountValid(t *testing.T, resourceMetrics pmetric.ResourceMetricsSlice, startTime pcommon.Timestamp) { for _, metricName := range []string{"process.threads"} { threadsMetric := getMetric(t, metricName, resourceMetrics) @@ -396,6 +413,11 @@ func (p *processHandleMock) MemoryInfo() (*process.MemoryInfoStat, error) { return args.Get(0).(*process.MemoryInfoStat), args.Error(1) } +func (p *processHandleMock) MemoryPercent() (float32, error) { + args := p.MethodCalled("MemoryPercent") + return args.Get(0).(float32), args.Error(1) +} + func (p *processHandleMock) IOCounters() (*process.IOCountersStat, error) { args := p.MethodCalled("IOCounters") return args.Get(0).(*process.IOCountersStat), args.Error(1) @@ -444,6 +466,7 @@ func newDefaultHandleMock() *processHandleMock { handleMock.On("Times").Return(&cpu.TimesStat{}, nil) handleMock.On("Percent").Return(float64(0), nil) handleMock.On("MemoryInfo").Return(&process.MemoryInfoStat{}, nil) + handleMock.On("MemoryPercent").Return(float32(0), nil) handleMock.On("IOCounters").Return(&process.IOCountersStat{}, nil) handleMock.On("Parent").Return(&process.Process{Pid: 2}, nil) handleMock.On("NumThreads").Return(int32(0), nil) @@ -583,6 +606,7 @@ func TestScrapeMetrics_Filtered(t *testing.T) { } func enableOptionalMetrics(ms *metadata.MetricsSettings) { + ms.ProcessMemoryUtilization.Enabled = true ms.ProcessThreads.Enabled = true ms.ProcessPagingFaults.Enabled = true ms.ProcessContextSwitches.Enabled = true @@ -602,6 +626,7 @@ func TestScrapeMetrics_ProcessErrors(t *testing.T) { cmdlineError error timesError error memoryInfoError error + memoryPercentError error ioCountersError error createTimeError error parentPidError error @@ -650,6 +675,11 @@ func TestScrapeMetrics_ProcessErrors(t *testing.T) { memoryInfoError: errors.New("err6"), expectedError: `error reading memory info for process "test" (pid 1): err6`, }, + { + name: "Memory Percent Error", + memoryPercentError: errors.New("err-mem-percent"), + expectedError: `error reading memory utilization for process "test" (pid 1): err-mem-percent`, + }, { name: "IO Counters Error", ioCountersError: errors.New("err7"), @@ -692,6 +722,7 @@ func TestScrapeMetrics_ProcessErrors(t *testing.T) { createTimeError: errors.New("err4"), timesError: errors.New("err5"), memoryInfoError: errors.New("err6"), + memoryPercentError: errors.New("err-mem-percent"), ioCountersError: errors.New("err7"), pageFaultsError: errors.New("err-paging"), numThreadsError: errors.New("err8"), @@ -703,6 +734,7 @@ func TestScrapeMetrics_ProcessErrors(t *testing.T) { `error reading create time for process "test" (pid 1): err4; ` + `error reading cpu times for process "test" (pid 1): err5; ` + `error reading memory info for process "test" (pid 1): err6; ` + + `error reading memory utilization for process "test" (pid 1): err-mem-percent; ` + `error reading disk usage for process "test" (pid 1): err7; ` + `error reading memory paging info for process "test" (pid 1): err-paging; ` + `error reading thread info for process "test" (pid 1): err8; ` + @@ -740,6 +772,7 @@ func TestScrapeMetrics_ProcessErrors(t *testing.T) { handleMock.On("Times").Return(&cpu.TimesStat{}, test.timesError) handleMock.On("Percent").Return(float64(0), nil) handleMock.On("MemoryInfo").Return(&process.MemoryInfoStat{}, test.memoryInfoError) + handleMock.On("MemoryPercent").Return(float32(0), test.memoryPercentError) handleMock.On("IOCounters").Return(&process.IOCountersStat{}, test.ioCountersError) handleMock.On("CreateTime").Return(int64(0), test.createTimeError) handleMock.On("Parent").Return(&process.Process{Pid: 2}, test.parentPidError) @@ -760,7 +793,7 @@ func TestScrapeMetrics_ProcessErrors(t *testing.T) { md, err := scraper.scrape(context.Background()) - expectedResourceMetricsLen, expectedMetricsLen := getExpectedLengthOfReturnedMetrics(test.nameError, test.exeError, test.timesError, test.memoryInfoError, test.ioCountersError, test.pageFaultsError, test.numThreadsError, test.numCtxSwitchesError, test.numFDsError, test.rlimitError) + expectedResourceMetricsLen, expectedMetricsLen := getExpectedLengthOfReturnedMetrics(test.nameError, test.exeError, test.timesError, test.memoryInfoError, test.memoryPercentError, test.ioCountersError, test.pageFaultsError, test.numThreadsError, test.numCtxSwitchesError, test.numFDsError, test.rlimitError) assert.Equal(t, expectedResourceMetricsLen, md.ResourceMetrics().Len()) assert.Equal(t, expectedMetricsLen, md.MetricCount()) @@ -768,7 +801,7 @@ func TestScrapeMetrics_ProcessErrors(t *testing.T) { isPartial := scrapererror.IsPartialScrapeError(err) assert.True(t, isPartial) if isPartial { - expectedFailures := getExpectedScrapeFailures(test.nameError, test.exeError, test.timesError, test.memoryInfoError, test.ioCountersError, test.pageFaultsError, test.numThreadsError, test.numCtxSwitchesError, test.numFDsError, test.rlimitError) + expectedFailures := getExpectedScrapeFailures(test.nameError, test.exeError, test.timesError, test.memoryInfoError, test.memoryPercentError, test.ioCountersError, test.pageFaultsError, test.numThreadsError, test.numCtxSwitchesError, test.numFDsError, test.rlimitError) var scraperErr scrapererror.PartialScrapeError require.ErrorAs(t, err, &scraperErr) assert.Equal(t, expectedFailures, scraperErr.Failed) @@ -777,7 +810,7 @@ func TestScrapeMetrics_ProcessErrors(t *testing.T) { } } -func getExpectedLengthOfReturnedMetrics(nameError, exeError, timeError, memError, diskError, pageFaultsError, threadError, contextSwitchError, fileDescriptorError error, rlimitError error) (int, int) { +func getExpectedLengthOfReturnedMetrics(nameError, exeError, timeError, memError, memPercentError, diskError, pageFaultsError, threadError, contextSwitchError, fileDescriptorError error, rlimitError error) (int, int) { if nameError != nil || exeError != nil { return 0, 0 } @@ -789,6 +822,9 @@ func getExpectedLengthOfReturnedMetrics(nameError, exeError, timeError, memError if memError == nil { expectedLen += memoryMetricsLen } + if memPercentError == nil { + expectedLen += memoryUtilizationMetricsLen + } if diskError == nil { expectedLen += diskMetricsLen } @@ -814,11 +850,11 @@ func getExpectedLengthOfReturnedMetrics(nameError, exeError, timeError, memError return 1, expectedLen } -func getExpectedScrapeFailures(nameError, exeError, timeError, memError, diskError, pageFaultsError, threadError, contextSwitchError, fileDescriptorError error, rlimitError error) int { +func getExpectedScrapeFailures(nameError, exeError, timeError, memError, memPercentError, diskError, pageFaultsError, threadError, contextSwitchError, fileDescriptorError error, rlimitError error) int { if nameError != nil || exeError != nil { return 1 } - _, expectedMetricsLen := getExpectedLengthOfReturnedMetrics(nameError, exeError, timeError, memError, diskError, pageFaultsError, threadError, contextSwitchError, fileDescriptorError, rlimitError) + _, expectedMetricsLen := getExpectedLengthOfReturnedMetrics(nameError, exeError, timeError, memError, memPercentError, diskError, pageFaultsError, threadError, contextSwitchError, fileDescriptorError, rlimitError) return metricsLen - expectedMetricsLen }