From 7ab593e7cda0e9af9a4ca78e758a009eaca827dd Mon Sep 17 00:00:00 2001 From: Akash Suresh Date: Thu, 24 Sep 2020 22:07:09 -0400 Subject: [PATCH] hostmetricsreceiver: (filesystems scraper) Collect additional labels from partitions Issue: https://github.com/open-telemetry/opentelemetry-collector/issues/1852 --- .../filesystemscraper/filesystem_metadata.go | 7 ++- .../filesystemscraper/filesystem_scraper.go | 50 +++++++++++-------- .../filesystem_scraper_others.go | 4 +- .../filesystem_scraper_test.go | 25 ++++------ .../filesystem_scraper_unix.go | 10 ++-- 5 files changed, 53 insertions(+), 43 deletions(-) diff --git a/receiver/hostmetricsreceiver/internal/scraper/filesystemscraper/filesystem_metadata.go b/receiver/hostmetricsreceiver/internal/scraper/filesystemscraper/filesystem_metadata.go index d7b32e4e778..00ca5e3bc46 100644 --- a/receiver/hostmetricsreceiver/internal/scraper/filesystemscraper/filesystem_metadata.go +++ b/receiver/hostmetricsreceiver/internal/scraper/filesystemscraper/filesystem_metadata.go @@ -21,8 +21,11 @@ import ( // labels const ( - deviceLabelName = "device" - stateLabelName = "state" + deviceLabelName = "device" + filesystemTypeLabelName = "fs.type" + mountModeLabelName = "mount.mode" + mountPointLabelName = "mount.point" + stateLabelName = "state" ) // state label values diff --git a/receiver/hostmetricsreceiver/internal/scraper/filesystemscraper/filesystem_scraper.go b/receiver/hostmetricsreceiver/internal/scraper/filesystemscraper/filesystem_scraper.go index bff133ac5cb..0a44c795ffb 100644 --- a/receiver/hostmetricsreceiver/internal/scraper/filesystemscraper/filesystem_scraper.go +++ b/receiver/hostmetricsreceiver/internal/scraper/filesystemscraper/filesystem_scraper.go @@ -17,6 +17,7 @@ package filesystemscraper import ( "context" "fmt" + "strings" "time" "github.com/shirou/gopsutil/disk" @@ -39,8 +40,8 @@ type scraper struct { } type deviceUsage struct { - deviceName string - usage *disk.UsageStat + partition disk.PartitionStat + usage *disk.UsageStat } // newFileSystemScraper creates a FileSystem Scraper @@ -91,18 +92,14 @@ func (s *scraper) ScrapeMetrics(_ context.Context) (pdata.MetricSlice, error) { var errors []error usages := make([]*deviceUsage, 0, len(partitions)) for _, partition := range partitions { - // Skip partition stats having more than one mount point for the same device - if deviceUsageAlreadySet(partition.Device, usages) { - continue - } - + // TODO: Add filters to include/exclude mount points usage, err := s.usage(partition.Mountpoint) if err != nil { errors = append(errors, err) continue } - usages = append(usages, &deviceUsage{partition.Device, usage}) + usages = append(usages, &deviceUsage{partition, usage}) } // filter devices by name @@ -118,15 +115,6 @@ func (s *scraper) ScrapeMetrics(_ context.Context) (pdata.MetricSlice, error) { return metrics, componenterror.CombineErrors(errors) } -func deviceUsageAlreadySet(device string, usages []*deviceUsage) bool { - for _, usage := range usages { - if device == usage.deviceName { - return true - } - } - return false -} - func initializeFileSystemUsageMetric(metric pdata.Metric, now pdata.TimestampUnixNano, deviceUsages []*deviceUsage) { fileSystemUsageDescriptor.CopyTo(metric) @@ -137,14 +125,36 @@ func initializeFileSystemUsageMetric(metric pdata.Metric, now pdata.TimestampUni } } -func initializeFileSystemUsageDataPoint(dataPoint pdata.IntDataPoint, now pdata.TimestampUnixNano, deviceLabel string, stateLabel string, value int64) { +func initializeFileSystemUsageDataPoint(dataPoint pdata.IntDataPoint, now pdata.TimestampUnixNano, partition disk.PartitionStat, stateLabel string, value int64) { labelsMap := dataPoint.LabelsMap() - labelsMap.Insert(deviceLabelName, deviceLabel) + labelsMap.Insert(deviceLabelName, partition.Device) + labelsMap.Insert(filesystemTypeLabelName, partition.Fstype) + labelsMap.Insert(mountModeLabelName, getMountMode(partition.Opts)) + labelsMap.Insert(mountPointLabelName, partition.Mountpoint) labelsMap.Insert(stateLabelName, stateLabel) dataPoint.SetTimestamp(now) dataPoint.SetValue(value) } +func getMountMode(opts string) string { + splitOptions := strings.Split(opts, ",") + if exists(splitOptions, "rw") { + return "rw" + } else if exists(splitOptions, "ro") { + return "ro" + } + return "unknown" +} + +func exists(options []string, opt string) bool { + for _, o := range options { + if o == opt { + return true + } + } + return false +} + func (s *scraper) filterByDevice(usages []*deviceUsage) []*deviceUsage { if s.includeFS == nil && s.excludeFS == nil { return usages @@ -152,7 +162,7 @@ func (s *scraper) filterByDevice(usages []*deviceUsage) []*deviceUsage { filteredUsages := make([]*deviceUsage, 0, len(usages)) for _, usage := range usages { - if s.includeDevice(usage.deviceName) { + if s.includeDevice(usage.partition.Device) { filteredUsages = append(filteredUsages, usage) } } diff --git a/receiver/hostmetricsreceiver/internal/scraper/filesystemscraper/filesystem_scraper_others.go b/receiver/hostmetricsreceiver/internal/scraper/filesystemscraper/filesystem_scraper_others.go index e2f6067be14..f8365a5be97 100644 --- a/receiver/hostmetricsreceiver/internal/scraper/filesystemscraper/filesystem_scraper_others.go +++ b/receiver/hostmetricsreceiver/internal/scraper/filesystemscraper/filesystem_scraper_others.go @@ -23,8 +23,8 @@ import ( const fileSystemStatesLen = 2 func appendFileSystemUsageStateDataPoints(idps pdata.IntDataPointSlice, startIdx int, now pdata.TimestampUnixNano, deviceUsage *deviceUsage) { - initializeFileSystemUsageDataPoint(idps.At(startIdx+0), now, deviceUsage.deviceName, usedLabelValue, int64(deviceUsage.usage.Used)) - initializeFileSystemUsageDataPoint(idps.At(startIdx+1), now, deviceUsage.deviceName, freeLabelValue, int64(deviceUsage.usage.Free)) + initializeFileSystemUsageDataPoint(idps.At(startIdx+0), now, deviceUsage.partition, usedLabelValue, int64(deviceUsage.usage.Used)) + initializeFileSystemUsageDataPoint(idps.At(startIdx+1), now, deviceUsage.partition, freeLabelValue, int64(deviceUsage.usage.Free)) } const systemSpecificMetricsLen = 0 diff --git a/receiver/hostmetricsreceiver/internal/scraper/filesystemscraper/filesystem_scraper_test.go b/receiver/hostmetricsreceiver/internal/scraper/filesystemscraper/filesystem_scraper_test.go index d0070d588c8..c465990ea20 100644 --- a/receiver/hostmetricsreceiver/internal/scraper/filesystemscraper/filesystem_scraper_test.go +++ b/receiver/hostmetricsreceiver/internal/scraper/filesystemscraper/filesystem_scraper_test.go @@ -58,20 +58,6 @@ func TestScrapeMetrics(t *testing.T) { expectMetrics: true, expectedDeviceDataPoints: 1, }, - { - name: "No duplicate metrics for devices having many mount point", - partitionsFunc: func(bool) ([]disk.PartitionStat, error) { - return []disk.PartitionStat{ - {Device: "a", Mountpoint: "/mnt/a1"}, - {Device: "a", Mountpoint: "/mnt/a2"}, - }, nil - }, - usageFunc: func(string) (*disk.UsageStat, error) { - return &disk.UsageStat{}, nil - }, - expectMetrics: true, - expectedDeviceDataPoints: 1, - }, { name: "Include Filter that matches nothing", config: Config{Include: MatchConfig{filterset.Config{MatchType: "strict"}, []string{"@*^#&*$^#)"}}}, @@ -141,6 +127,7 @@ func TestScrapeMetrics(t *testing.T) { assertFileSystemUsageMetricValid(t, metrics.At(1), fileSystemINodesUsageDescriptor, test.expectedDeviceDataPoints*2) } + assertFileSystemUsageCommonMetricLabels(t, metrics) internal.AssertSameTimeStampForAllMetrics(t, metrics) }) } @@ -157,6 +144,16 @@ func assertFileSystemUsageMetricValid(t *testing.T, metric pdata.Metric, descrip internal.AssertIntSumMetricLabelHasValue(t, metric, 1, stateLabelName, freeLabelValue) } +func assertFileSystemUsageCommonMetricLabels(t *testing.T, metrics pdata.MetricSlice) { + for i := 0; i < metrics.Len(); i++ { + for j := 0; j < metrics.At(i).IntSum().DataPoints().Len(); j++ { + for _, label := range []string{deviceLabelName, filesystemTypeLabelName, mountModeLabelName, mountPointLabelName} { + internal.AssertIntSumMetricLabelExists(t, metrics.At(i), j, label) + } + } + } +} + func assertFileSystemUsageMetricHasUnixSpecificStateLabels(t *testing.T, metric pdata.Metric) { internal.AssertIntSumMetricLabelHasValue(t, metric, 2, stateLabelName, reservedLabelValue) } diff --git a/receiver/hostmetricsreceiver/internal/scraper/filesystemscraper/filesystem_scraper_unix.go b/receiver/hostmetricsreceiver/internal/scraper/filesystemscraper/filesystem_scraper_unix.go index ec251a1f702..fafe5ec8264 100644 --- a/receiver/hostmetricsreceiver/internal/scraper/filesystemscraper/filesystem_scraper_unix.go +++ b/receiver/hostmetricsreceiver/internal/scraper/filesystemscraper/filesystem_scraper_unix.go @@ -23,9 +23,9 @@ import ( const fileSystemStatesLen = 3 func appendFileSystemUsageStateDataPoints(idps pdata.IntDataPointSlice, startIdx int, now pdata.TimestampUnixNano, deviceUsage *deviceUsage) { - initializeFileSystemUsageDataPoint(idps.At(startIdx+0), now, deviceUsage.deviceName, usedLabelValue, int64(deviceUsage.usage.Used)) - initializeFileSystemUsageDataPoint(idps.At(startIdx+1), now, deviceUsage.deviceName, freeLabelValue, int64(deviceUsage.usage.Free)) - initializeFileSystemUsageDataPoint(idps.At(startIdx+2), now, deviceUsage.deviceName, reservedLabelValue, int64(deviceUsage.usage.Total-deviceUsage.usage.Used-deviceUsage.usage.Free)) + initializeFileSystemUsageDataPoint(idps.At(startIdx+0), now, deviceUsage.partition, usedLabelValue, int64(deviceUsage.usage.Used)) + initializeFileSystemUsageDataPoint(idps.At(startIdx+1), now, deviceUsage.partition, freeLabelValue, int64(deviceUsage.usage.Free)) + initializeFileSystemUsageDataPoint(idps.At(startIdx+2), now, deviceUsage.partition, reservedLabelValue, int64(deviceUsage.usage.Total-deviceUsage.usage.Used-deviceUsage.usage.Free)) } const systemSpecificMetricsLen = 1 @@ -38,7 +38,7 @@ func appendSystemSpecificMetrics(metrics pdata.MetricSlice, startIdx int, now pd idps.Resize(2 * len(deviceUsages)) for idx, deviceUsage := range deviceUsages { startIndex := 2 * idx - initializeFileSystemUsageDataPoint(idps.At(startIndex+0), now, deviceUsage.deviceName, usedLabelValue, int64(deviceUsage.usage.InodesUsed)) - initializeFileSystemUsageDataPoint(idps.At(startIndex+1), now, deviceUsage.deviceName, freeLabelValue, int64(deviceUsage.usage.InodesFree)) + initializeFileSystemUsageDataPoint(idps.At(startIndex+0), now, deviceUsage.partition, usedLabelValue, int64(deviceUsage.usage.InodesUsed)) + initializeFileSystemUsageDataPoint(idps.At(startIndex+1), now, deviceUsage.partition, freeLabelValue, int64(deviceUsage.usage.InodesFree)) } }