123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237 |
- // Copyright The OpenTelemetry Authors
- // SPDX-License-Identifier: Apache-2.0
- package memoryscraper
- import (
- "context"
- "errors"
- "runtime"
- "testing"
- "github.com/shirou/gopsutil/v3/mem"
- "github.com/stretchr/testify/assert"
- "github.com/stretchr/testify/require"
- "go.opentelemetry.io/collector/component/componenttest"
- "go.opentelemetry.io/collector/pdata/pcommon"
- "go.opentelemetry.io/collector/pdata/pmetric"
- "go.opentelemetry.io/collector/receiver/receivertest"
- "go.opentelemetry.io/collector/receiver/scrapererror"
- "github.com/open-telemetry/opentelemetry-collector-contrib/receiver/hostmetricsreceiver/internal"
- "github.com/open-telemetry/opentelemetry-collector-contrib/receiver/hostmetricsreceiver/internal/scraper/memoryscraper/internal/metadata"
- )
- func TestScrape(t *testing.T) {
- type testCase struct {
- name string
- virtualMemoryFunc func(context.Context) (*mem.VirtualMemoryStat, error)
- expectedErr string
- initializationErr string
- config *Config
- expectedMetricCount int
- bootTimeFunc func(context.Context) (uint64, error)
- }
- testCases := []testCase{
- {
- name: "Standard",
- config: &Config{
- MetricsBuilderConfig: metadata.DefaultMetricsBuilderConfig(),
- },
- expectedMetricCount: 1,
- },
- {
- name: "All metrics enabled",
- config: &Config{
- MetricsBuilderConfig: metadata.MetricsBuilderConfig{
- Metrics: metadata.MetricsConfig{
- SystemMemoryUtilization: metadata.MetricConfig{
- Enabled: true,
- },
- SystemMemoryUsage: metadata.MetricConfig{
- Enabled: true,
- },
- SystemLinuxMemoryAvailable: metadata.MetricConfig{
- Enabled: true,
- },
- },
- },
- },
- expectedMetricCount: func() int {
- if runtime.GOOS == "linux" {
- return 3
- }
- return 2
- }(),
- },
- {
- name: "Error",
- virtualMemoryFunc: func(context.Context) (*mem.VirtualMemoryStat, error) { return nil, errors.New("err1") },
- expectedErr: "err1",
- config: &Config{
- MetricsBuilderConfig: metadata.DefaultMetricsBuilderConfig(),
- },
- expectedMetricCount: 1,
- },
- {
- name: "Error",
- bootTimeFunc: func(context.Context) (uint64, error) { return 100, errors.New("err1") },
- initializationErr: "err1",
- config: &Config{
- MetricsBuilderConfig: metadata.DefaultMetricsBuilderConfig(),
- },
- expectedMetricCount: 1,
- },
- }
- for _, test := range testCases {
- t.Run(test.name, func(t *testing.T) {
- scraper := newMemoryScraper(context.Background(), receivertest.NewNopCreateSettings(), test.config)
- if test.virtualMemoryFunc != nil {
- scraper.virtualMemory = test.virtualMemoryFunc
- }
- if test.bootTimeFunc != nil {
- scraper.bootTime = test.bootTimeFunc
- }
- err := scraper.start(context.Background(), componenttest.NewNopHost())
- if test.initializationErr != "" {
- assert.EqualError(t, err, test.initializationErr)
- return
- }
- require.NoError(t, err, "Failed to initialize memory scraper: %v", err)
- md, err := scraper.scrape(context.Background())
- if test.expectedErr != "" {
- assert.EqualError(t, err, test.expectedErr)
- isPartial := scrapererror.IsPartialScrapeError(err)
- assert.True(t, isPartial)
- if isPartial {
- var scraperErr scrapererror.PartialScrapeError
- require.ErrorAs(t, err, &scraperErr)
- assert.Equal(t, metricsLen, scraperErr.Failed)
- }
- return
- }
- require.NoError(t, err, "Failed to scrape metrics: %v", err)
- assert.Equal(t, test.expectedMetricCount, md.MetricCount())
- metrics := md.ResourceMetrics().At(0).ScopeMetrics().At(0).Metrics()
- memUsageIdx := -1
- for i := 0; i < md.MetricCount(); i++ {
- if metrics.At(i).Name() == "system.memory.usage" {
- memUsageIdx = i
- }
- }
- assert.NotEqual(t, memUsageIdx, -1)
- assertMemoryUsageMetricValid(t, metrics.At(memUsageIdx), "system.memory.usage")
- if runtime.GOOS == "linux" {
- assertMemoryUsageMetricHasLinuxSpecificStateLabels(t, metrics.At(memUsageIdx))
- } else if runtime.GOOS != "windows" {
- internal.AssertSumMetricHasAttributeValue(t, metrics.At(memUsageIdx), 2, "state",
- pcommon.NewValueStr(metadata.AttributeStateInactive.String()))
- }
- internal.AssertSameTimeStampForAllMetrics(t, metrics)
- })
- }
- }
- func TestScrape_MemoryUtilization(t *testing.T) {
- type testCase struct {
- name string
- virtualMemoryFunc func(context.Context) (*mem.VirtualMemoryStat, error)
- expectedErr error
- }
- testCases := []testCase{
- {
- name: "Standard",
- },
- {
- name: "Invalid total memory",
- virtualMemoryFunc: func(context.Context) (*mem.VirtualMemoryStat, error) { return &mem.VirtualMemoryStat{Total: 0}, nil },
- expectedErr: ErrInvalidTotalMem,
- },
- }
- for _, test := range testCases {
- t.Run(test.name, func(t *testing.T) {
- mbc := metadata.DefaultMetricsBuilderConfig()
- mbc.Metrics.SystemMemoryUtilization.Enabled = true
- mbc.Metrics.SystemMemoryUsage.Enabled = false
- scraperConfig := Config{
- MetricsBuilderConfig: mbc,
- }
- scraper := newMemoryScraper(context.Background(), receivertest.NewNopCreateSettings(), &scraperConfig)
- if test.virtualMemoryFunc != nil {
- scraper.virtualMemory = test.virtualMemoryFunc
- }
- err := scraper.start(context.Background(), componenttest.NewNopHost())
- require.NoError(t, err, "Failed to initialize memory scraper: %v", err)
- md, err := scraper.scrape(context.Background())
- if test.expectedErr != nil {
- var partialScrapeErr scrapererror.PartialScrapeError
- assert.ErrorAs(t, err, &partialScrapeErr)
- return
- }
- require.NoError(t, err, "Failed to scrape metrics: %v", err)
- metrics := md.ResourceMetrics().At(0).ScopeMetrics().At(0).Metrics()
- assertMemoryUtilizationMetricValid(t, metrics.At(0), "system.memory.utilization")
- if runtime.GOOS == "linux" {
- assertMemoryUtilizationMetricHasLinuxSpecificStateLabels(t, metrics.At(0))
- } else if runtime.GOOS != "windows" {
- internal.AssertGaugeMetricHasAttributeValue(t, metrics.At(0), 2, "state",
- pcommon.NewValueStr(metadata.AttributeStateInactive.String()))
- }
- internal.AssertSameTimeStampForAllMetrics(t, metrics)
- })
- }
- }
- func assertMemoryUsageMetricValid(t *testing.T, metric pmetric.Metric, expectedName string) {
- assert.Equal(t, expectedName, metric.Name())
- assert.GreaterOrEqual(t, metric.Sum().DataPoints().Len(), 2)
- internal.AssertSumMetricHasAttributeValue(t, metric, 0, "state",
- pcommon.NewValueStr(metadata.AttributeStateUsed.String()))
- internal.AssertSumMetricHasAttributeValue(t, metric, 1, "state",
- pcommon.NewValueStr(metadata.AttributeStateFree.String()))
- }
- func assertMemoryUtilizationMetricValid(t *testing.T, metric pmetric.Metric, expectedName string) {
- assert.Equal(t, expectedName, metric.Name())
- assert.GreaterOrEqual(t, metric.Gauge().DataPoints().Len(), 2)
- internal.AssertGaugeMetricHasAttributeValue(t, metric, 0, "state",
- pcommon.NewValueStr(metadata.AttributeStateUsed.String()))
- internal.AssertGaugeMetricHasAttributeValue(t, metric, 1, "state",
- pcommon.NewValueStr(metadata.AttributeStateFree.String()))
- }
- func assertMemoryUsageMetricHasLinuxSpecificStateLabels(t *testing.T, metric pmetric.Metric) {
- internal.AssertSumMetricHasAttributeValue(t, metric, 2, "state",
- pcommon.NewValueStr(metadata.AttributeStateBuffered.String()))
- internal.AssertSumMetricHasAttributeValue(t, metric, 3, "state",
- pcommon.NewValueStr(metadata.AttributeStateCached.String()))
- internal.AssertSumMetricHasAttributeValue(t, metric, 4, "state",
- pcommon.NewValueStr(metadata.AttributeStateSlabReclaimable.String()))
- internal.AssertSumMetricHasAttributeValue(t, metric, 5, "state",
- pcommon.NewValueStr(metadata.AttributeStateSlabUnreclaimable.String()))
- }
- func assertMemoryUtilizationMetricHasLinuxSpecificStateLabels(t *testing.T, metric pmetric.Metric) {
- internal.AssertGaugeMetricHasAttributeValue(t, metric, 2, "state",
- pcommon.NewValueStr(metadata.AttributeStateBuffered.String()))
- internal.AssertGaugeMetricHasAttributeValue(t, metric, 3, "state",
- pcommon.NewValueStr(metadata.AttributeStateCached.String()))
- internal.AssertGaugeMetricHasAttributeValue(t, metric, 4, "state",
- pcommon.NewValueStr(metadata.AttributeStateSlabReclaimable.String()))
- internal.AssertGaugeMetricHasAttributeValue(t, metric, 5, "state",
- pcommon.NewValueStr(metadata.AttributeStateSlabUnreclaimable.String()))
- }
|