From a2b67d9a20026f19f29516cb3fc49fa6042788bd Mon Sep 17 00:00:00 2001 From: Tristan Colgate-McFarlane Date: Wed, 9 Oct 2024 12:33:15 +0100 Subject: [PATCH] fix(hostmetricsreceiver): do not duplicate mountpoint metrics (#34635) Mountpoints can be reported multiple times for each mount into a namespace. This causes duplicate metrics which causes issues with some exporters. Each instance of the mountpoint will have identical metrics, so it is safe to ignore repeated mountpoints. Closes #34512 **Description:** **Link to tracking Issue:** **Testing:** **Documentation:** --- ...eceiever-ignore-duplicate-filesystems.yaml | 16 +++++++++ .../filesystemscraper/filesystem_scraper.go | 16 +++++++++ .../filesystem_scraper_test.go | 35 +++++++++++++++++++ 3 files changed, 67 insertions(+) create mode 100644 .chloggen/hostmetrics-receiever-ignore-duplicate-filesystems.yaml diff --git a/.chloggen/hostmetrics-receiever-ignore-duplicate-filesystems.yaml b/.chloggen/hostmetrics-receiever-ignore-duplicate-filesystems.yaml new file mode 100644 index 000000000000..f9a06931e74c --- /dev/null +++ b/.chloggen/hostmetrics-receiever-ignore-duplicate-filesystems.yaml @@ -0,0 +1,16 @@ +# One of 'breaking', 'deprecation', 'new_component', 'enhancement', 'bug_fix' +change_type: 'bug_fix' + +# The name of the component, or a single word describing the area of concern, (e.g. operator, target allocator, github action) +component: hostmetrics receiver + +# A brief description of the change. Surround your text with quotes ("") if it needs to start with a backtick (`). +note: "Fix duplicate filesystem metrics" + +# One or more tracking issues related to the change +issues: [34635, 34512] + +# (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: "The hostmetrics exposes duplicate metrics of identical mounts exposed in namespaces. The duplication causes errors in exporters that are sensitive to duplicate metrics. We can safely drop the duplicates as the metrics should be exactly the same." diff --git a/receiver/hostmetricsreceiver/internal/scraper/filesystemscraper/filesystem_scraper.go b/receiver/hostmetricsreceiver/internal/scraper/filesystemscraper/filesystem_scraper.go index 809d44c8f717..005a506befe5 100644 --- a/receiver/hostmetricsreceiver/internal/scraper/filesystemscraper/filesystem_scraper.go +++ b/receiver/hostmetricsreceiver/internal/scraper/filesystemscraper/filesystem_scraper.go @@ -91,7 +91,23 @@ func (s *scraper) scrape(ctx context.Context) (pmetric.Metrics, error) { } usages := make([]*deviceUsage, 0, len(partitions)) + + type mountKey struct { + mountpoint string + device string + } + seen := map[mountKey]struct{}{} + for _, partition := range partitions { + key := mountKey{ + mountpoint: partition.Mountpoint, + device: partition.Device, + } + if _, ok := seen[key]; partition.Mountpoint != "" && ok { + continue + } + seen[key] = struct{}{} + if !s.fsFilter.includePartition(partition) { continue } diff --git a/receiver/hostmetricsreceiver/internal/scraper/filesystemscraper/filesystem_scraper_test.go b/receiver/hostmetricsreceiver/internal/scraper/filesystemscraper/filesystem_scraper_test.go index d438357c58e0..250ec060ec2e 100644 --- a/receiver/hostmetricsreceiver/internal/scraper/filesystemscraper/filesystem_scraper_test.go +++ b/receiver/hostmetricsreceiver/internal/scraper/filesystemscraper/filesystem_scraper_test.go @@ -347,6 +347,41 @@ func TestScrape(t *testing.T) { usageFunc: func(context.Context, string) (*disk.UsageStat, error) { return nil, errors.New("err2") }, expectedErr: "err2", }, + { + name: "Do not report duplicate mount points", + config: Config{ + MetricsBuilderConfig: metadata.DefaultMetricsBuilderConfig(), + }, + usageFunc: func(context.Context, string) (*disk.UsageStat, error) { + return &disk.UsageStat{ + Fstype: "fs_type_a", + }, nil + }, + partitionsFunc: func(context.Context, bool) ([]disk.PartitionStat, error) { + return []disk.PartitionStat{ + { + Device: "device_a", + Mountpoint: "mount_point_a", + Fstype: "fs_type_a", + }, + { + Device: "device_a", + Mountpoint: "mount_point_a", + Fstype: "fs_type_a", + }, + }, nil + }, + expectMetrics: true, + expectedDeviceDataPoints: 1, + expectedDeviceAttributes: []map[string]pcommon.Value{ + { + "device": pcommon.NewValueStr("device_a"), + "mountpoint": pcommon.NewValueStr("mount_point_a"), + "type": pcommon.NewValueStr("fs_type_a"), + "mode": pcommon.NewValueStr("unknown"), + }, + }, + }, } for _, test := range testCases {