diff --git a/CHANGELOG.md b/CHANGELOG.md index 74328f9..e562151 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,9 @@ +## Unreleased + +### Bug fixes + +* Do not produce errors if no metadata is reported by mmdf + ## 1.1.1 / 2021-03-31 ### Bug fixes diff --git a/collectors/mmdf.go b/collectors/mmdf.go index eb9899d..1f7a284 100644 --- a/collectors/mmdf.go +++ b/collectors/mmdf.go @@ -55,6 +55,7 @@ type DFMetric struct { InodesTotal float64 FSTotal float64 FSFree float64 + Metadata bool MetadataTotal float64 MetadataFree float64 } @@ -159,8 +160,10 @@ func (c *MmdfCollector) Collect(ch chan<- prometheus.Metric) { ch <- prometheus.MustNewConstMetric(c.InodesTotal, prometheus.GaugeValue, metric.InodesTotal, fs) ch <- prometheus.MustNewConstMetric(c.FSTotal, prometheus.GaugeValue, metric.FSTotal, fs) ch <- prometheus.MustNewConstMetric(c.FSFree, prometheus.GaugeValue, metric.FSFree, fs) - ch <- prometheus.MustNewConstMetric(c.MetadataTotal, prometheus.GaugeValue, metric.MetadataTotal, fs) - ch <- prometheus.MustNewConstMetric(c.MetadataFree, prometheus.GaugeValue, metric.MetadataFree, fs) + if metric.Metadata { + ch <- prometheus.MustNewConstMetric(c.MetadataTotal, prometheus.GaugeValue, metric.MetadataTotal, fs) + ch <- prometheus.MustNewConstMetric(c.MetadataFree, prometheus.GaugeValue, metric.MetadataFree, fs) + } ch <- prometheus.MustNewConstMetric(lastExecution, prometheus.GaugeValue, float64(time.Now().Unix()), label) }(fs) } @@ -205,7 +208,7 @@ func mmdf(fs string, ctx context.Context) (string, error) { } func parse_mmdf(out string, logger log.Logger) (DFMetric, error) { - var dfMetrics DFMetric + dfMetrics := DFMetric{Metadata: true} headers := make(map[string][]string) values := make(map[string][]string) lines := strings.Split(out, "\n") @@ -230,8 +233,13 @@ func parse_mmdf(out string, logger log.Logger) (DFMetric, error) { s := ps.Elem() // struct for k, vals := range headers { if _, ok := values[k]; !ok { - level.Error(logger).Log("msg", "Header section missing from values", "header", k) - return dfMetrics, fmt.Errorf("Header section missing from values: %s", k) + if k == "metadata" { + dfMetrics.Metadata = false + continue + } else { + level.Error(logger).Log("msg", "Header section missing from values", "header", k) + return dfMetrics, fmt.Errorf("Header section missing from values: %s", k) + } } if len(vals) != len(values[k]) { level.Error(logger).Log("msg", "Length of headers does not equal length of values", "header", k, "values", len(values[k]), "headers", len(vals)) diff --git a/collectors/mmdf_test.go b/collectors/mmdf_test.go index 845dd4a..437479a 100644 --- a/collectors/mmdf_test.go +++ b/collectors/mmdf_test.go @@ -42,7 +42,7 @@ mmdf:metadata:0:1:::13891534848:6011299328:43:58139768:0: mmdf:fsTotal:0:1:::3661677723648:481202021888:14:12117655064:0: mmdf:inode:0:1:::430741822:484301506:915043328:1332164000: ` - mmdfStdoutErrValues = ` + mmdfStdoutMissingMetadata = ` mmdf:nsd:HEADER:version:reserved:reserved:nsdName:storagePool:diskSize:failureGroup:metadata:data:freeBlocks:freeBlocksPct:freeFragments:freeFragmentsPct:diskAvailableForAlloc: mmdf:poolTotal:HEADER:version:reserved:reserved:poolName:poolSize:freeBlocks:freeBlocksPct:freeFragments:freeFragmentsPct:maxDiskSize: mmdf:data:HEADER:version:reserved:reserved:totalData:freeBlocks:freeBlocksPct:freeFragments:freeFragmentsPct: @@ -55,6 +55,20 @@ mmdf:poolTotal:0:1:::data:3647786188800:475190722560:13:12059515296:0:3860104580 mmdf:data:0:1:::3647786188800:475190722560:13:12059515296:0: mmdf:fsTotal:0:1:::3661677723648:481202021888:14:12117655064:0: mmdf:inode:0:1:::430741822:484301506:915043328:1332164000: +` + mmdfStdoutMissingValues = ` +mmdf:nsd:HEADER:version:reserved:reserved:nsdName:storagePool:diskSize:failureGroup:metadata:data:freeBlocks:freeBlocksPct:freeFragments:freeFragmentsPct:diskAvailableForAlloc: +mmdf:poolTotal:HEADER:version:reserved:reserved:poolName:poolSize:freeBlocks:freeBlocksPct:freeFragments:freeFragmentsPct:maxDiskSize: +mmdf:data:HEADER:version:reserved:reserved:totalData:freeBlocks:freeBlocksPct:freeFragments:freeFragmentsPct: +mmdf:metadata:HEADER:version:reserved:reserved:totalMetadata:freeBlocks:freeBlocksPct:freeFragments:freeFragmentsPct: +mmdf:fsTotal:HEADER:version:reserved:reserved:fsSize:freeBlocks:freeBlocksPct:freeFragments:freeFragmentsPct: +mmdf:inode:HEADER:version:reserved:reserved:usedInodes:freeInodes:allocatedInodes:maxInodes: +mmdf:nsd:0:1:::P_META_VD102:system:771751936:300:Yes:No:320274944:41:5005384:1:: +mmdf:nsd:0:1:::P_DATA_VD02:data:46766489600:200:No:Yes:6092915712:13:154966272:0:: +mmdf:poolTotal:0:1:::data:3647786188800:475190722560:13:12059515296:0:3860104580096: +mmdf:data:0:1:::3647786188800:475190722560:13:12059515296:0: +mmdf:metadata:0:1:::13891534848:6011299328:43:58139768:0: +mmdf:inode:0:1:::430741822:484301506:915043328:1332164000: ` mmdfStdoutErrLen = ` mmdf:nsd:HEADER:version:reserved:reserved:nsdName:storagePool:diskSize:failureGroup:metadata:data:freeBlocks:freeBlocksPct:freeFragments:freeFragmentsPct:diskAvailableForAlloc: @@ -133,13 +147,30 @@ func TestParseMmdf(t *testing.T) { if dfmetrics.FSTotal != 3749557989015552 { t.Errorf("Unexpected value for FSTotal, got %v", dfmetrics.FSTotal) } + if dfmetrics.Metadata != true { + t.Errorf("Unexpected value for Metadata, got %v", dfmetrics.Metadata) + } if dfmetrics.MetadataTotal != 14224931684352 { t.Errorf("Unexpected value for MetadataTotal, got %v", dfmetrics.MetadataTotal) } + dfmetrics, err = parse_mmdf(mmdfStdoutMissingMetadata, log.NewNopLogger()) + if err != nil { + t.Errorf("Unexpected error: %s", err.Error()) + return + } + if dfmetrics.InodesFree != 484301506 { + t.Errorf("Unexpected value for InodesFree, got %v", dfmetrics.InodesFree) + } + if dfmetrics.FSTotal != 3749557989015552 { + t.Errorf("Unexpected value for FSTotal, got %v", dfmetrics.FSTotal) + } + if dfmetrics.Metadata != false { + t.Errorf("Unexpected value for Metadata, got %v", dfmetrics.Metadata) + } } func TestParseMmdfErrors(t *testing.T) { - _, err := parse_mmdf(mmdfStdoutErrValues, log.NewNopLogger()) + _, err := parse_mmdf(mmdfStdoutMissingValues, log.NewNopLogger()) if err == nil { t.Errorf("Expected error") return @@ -201,6 +232,50 @@ func TestMmdfCollector(t *testing.T) { } } +func TestMmdfCollectorNoMetadata(t *testing.T) { + if _, err := kingpin.CommandLine.Parse([]string{}); err != nil { + t.Fatal(err) + } + filesystems := "project" + configFilesystems = &filesystems + MmdfExec = func(fs string, ctx context.Context) (string, error) { + return mmdfStdoutMissingMetadata, nil + } + expected := ` + # HELP gpfs_fs_allocated_inodes GPFS filesystem inodes allocated + # TYPE gpfs_fs_allocated_inodes gauge + gpfs_fs_allocated_inodes{fs="project"} 915043328 + # HELP gpfs_fs_free_bytes GPFS filesystem free size in bytes + # TYPE gpfs_fs_free_bytes gauge + gpfs_fs_free_bytes{fs="project"} 492750870413312 + # HELP gpfs_fs_free_inodes GPFS filesystem inodes free + # TYPE gpfs_fs_free_inodes gauge + gpfs_fs_free_inodes{fs="project"} 484301506 + # HELP gpfs_fs_inodes GPFS filesystem inodes total + # TYPE gpfs_fs_inodes gauge + gpfs_fs_inodes{fs="project"} 1332164000 + # HELP gpfs_fs_size_bytes GPFS filesystem total size in bytes + # TYPE gpfs_fs_size_bytes gauge + gpfs_fs_size_bytes{fs="project"} 3749557989015552 + # HELP gpfs_fs_used_inodes GPFS filesystem inodes used + # TYPE gpfs_fs_used_inodes gauge + gpfs_fs_used_inodes{fs="project"} 430741822 + ` + collector := NewMmdfCollector(log.NewNopLogger()) + gatherers := setupGatherer(collector) + if val, err := testutil.GatherAndCount(gatherers); err != nil { + t.Errorf("Unexpected error: %v", err) + } else if val != 10 { + t.Errorf("Unexpected collection count %d, expected 10", val) + } + if err := testutil.GatherAndCompare(gatherers, strings.NewReader(expected), + "gpfs_fs_used_inodes", "gpfs_fs_free_inodes", "gpfs_fs_allocated_inodes", "gpfs_fs_inodes", + "gpfs_fs_free_bytes", "gpfs_fs_free_percent", "gpfs_fs_size_bytes", + "gpfs_fs_metadata_size_bytes", "gpfs_fs_metadata_free_bytes", "gpfs_fs_metadata_free_percent"); err != nil { + t.Errorf("unexpected collecting result:\n%s", err) + } +} + func TestMmdfCollectorMmlsfs(t *testing.T) { if _, err := kingpin.CommandLine.Parse([]string{}); err != nil { t.Fatal(err)