From e152c69d0a9e72b7a07621fd95f5b1457c9022c1 Mon Sep 17 00:00:00 2001 From: Trey Dockendorf Date: Sun, 23 Feb 2020 19:52:36 -0500 Subject: [PATCH 1/4] Test improvements for main packages --- Makefile | 2 +- cmd/gpfs_exporter/main.go | 4 +- cmd/gpfs_exporter/main_test.go | 77 +++++++++++++++++++++++++++++ cmd/gpfs_mmdf_exporter/main.go | 74 --------------------------- cmd/gpfs_mmdf_exporter/main_test.go | 32 ++++++++++++ 5 files changed, 112 insertions(+), 77 deletions(-) create mode 100644 cmd/gpfs_exporter/main_test.go create mode 100644 cmd/gpfs_mmdf_exporter/main_test.go diff --git a/Makefile b/Makefile index 24b0229..1a81dd1 100644 --- a/Makefile +++ b/Makefile @@ -7,4 +7,4 @@ include Makefile.common DOCKER_IMAGE_NAME ?= gpfs_exporter coverage: - go test -race -coverpkg=./... -coverprofile=coverage.txt -covermode=atomic ./... + go test -race -coverprofile=coverage.txt -covermode=atomic ./... diff --git a/cmd/gpfs_exporter/main.go b/cmd/gpfs_exporter/main.go index a9adba5..c792fa8 100644 --- a/cmd/gpfs_exporter/main.go +++ b/cmd/gpfs_exporter/main.go @@ -29,7 +29,7 @@ var ( disableExporterMetrics = kingpin.Flag("web.disable-exporter-metrics", "Exclude metrics about the exporter (promhttp_*, process_*, go_*)").Default("false").Bool() ) -func gpfsHandler() http.HandlerFunc { +func metricsHandler() http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { registry := prometheus.NewRegistry() @@ -62,7 +62,7 @@ func main() { log.Infoln("Build context", version.BuildContext()) log.Infof("Starting Server: %s", *listenAddr) - http.Handle("/metrics", gpfsHandler()) + http.Handle("/metrics", metricsHandler()) http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { //nolint:errcheck w.Write([]byte(` diff --git a/cmd/gpfs_exporter/main_test.go b/cmd/gpfs_exporter/main_test.go new file mode 100644 index 0000000..16e0c78 --- /dev/null +++ b/cmd/gpfs_exporter/main_test.go @@ -0,0 +1,77 @@ +// Copyright 2020 Trey Dockendorf +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package main + +import ( + "fmt" + "github.com/prometheus/common/log" + kingpin "gopkg.in/alecthomas/kingpin.v2" + "io/ioutil" + "net/http" + "os" + "strings" + "testing" + "time" +) + +const ( + address = "localhost:19303" +) + +func TestMain(m *testing.M) { + if _, err := kingpin.CommandLine.Parse([]string{"--no-collector.mmpmon"}); err != nil { + log.Fatal(err) + } + varTrue := true + disableExporterMetrics = &varTrue + go func() { + http.Handle("/metrics", metricsHandler()) + log.Fatal(http.ListenAndServe(address, nil)) + }() + time.Sleep(1 * time.Second) + + exitVal := m.Run() + + os.Exit(exitVal) +} + +func TestMetricsHandler(t *testing.T) { + _ = log.Base().SetLevel("debug") + body, err := queryExporter() + if err != nil { + t.Fatalf("Unexpected error GET /metrics: %s", err.Error()) + } + log.Debugf("body='%s'", body) + if !strings.Contains(body, "gpfs_exporter_collect_error{collector=\"mount\"} 0") { + t.Errorf("Unexpected value for gpfs_exporter_collect_error") + } +} + +func queryExporter() (string, error) { + resp, err := http.Get(fmt.Sprintf("http://%s/metrics", address)) + if err != nil { + return "", err + } + b, err := ioutil.ReadAll(resp.Body) + if err != nil { + return "", err + } + if err := resp.Body.Close(); err != nil { + return "", err + } + if want, have := http.StatusOK, resp.StatusCode; want != have { + return "", fmt.Errorf("want /metrics status code %d, have %d. Body:\n%s", want, have, b) + } + return string(b), nil +} diff --git a/cmd/gpfs_mmdf_exporter/main.go b/cmd/gpfs_mmdf_exporter/main.go index 0be08a9..60ae17d 100644 --- a/cmd/gpfs_mmdf_exporter/main.go +++ b/cmd/gpfs_mmdf_exporter/main.go @@ -27,80 +27,6 @@ var ( lockFile = kingpin.Flag("lockfile", "Lock file path").Default("/tmp/gpfs_mmdf_exporter.lock").String() ) -/* -func GetMetrics(fs string) (collector.DFMetric, error) { - out, err := collector.Mmdf(fs) - if err != nil { - return collector.DFMetric{}, err - } - dfMetric, err := collector.Parse_mmdf(out) - if err != nil { - return collector.DFMetric{}, err - } - return dfMetric, nil -} - -type Collector struct { - fs string - inodes_used *prometheus.Desc - inodes_free *prometheus.Desc - inodes_allocated *prometheus.Desc - inodes_total *prometheus.Desc - fs_total *prometheus.Desc - fs_free *prometheus.Desc - fs_free_percent *prometheus.Desc - metadata_total *prometheus.Desc - metadata_free *prometheus.Desc - metadata_free_percent *prometheus.Desc -} - -func NewCollector(fs string) *Collector { - return &Collector{ - fs: fs, - inodes_used: collector.Inodes_used, - inodes_free: collector.Inodes_free, - inodes_allocated: collector.Inodes_allocated, - inodes_total: collector.Inodes_total, - fs_total: collector.Fs_total, - fs_free: collector.Fs_free, - fs_free_percent: collector.Fs_free_percent, - metadata_total: collector.Metadata_total, - metadata_free: collector.Metadata_free, - metadata_free_percent: collector.Metadata_free_percent, - } -} - -func (c *Collector) Describe(ch chan<- *prometheus.Desc) { - ch <- c.inodes_used - ch <- c.inodes_free - ch <- c.inodes_allocated - ch <- c.inodes_total - ch <- c.fs_total - ch <- c.fs_free - ch <- c.fs_free_percent - ch <- c.metadata_total - ch <- c.metadata_free - ch <- c.metadata_free_percent -} - -func (c *Collector) Collect(ch chan<- prometheus.Metric) { - metrics, err := GetMetrics(c.fs) - if err != nil { - log.Fatal(err) - } - ch <- prometheus.MustNewConstMetric(c.inodes_used, prometheus.GaugeValue, float64(metrics.InodesUsed), c.fs) - ch <- prometheus.MustNewConstMetric(c.inodes_free, prometheus.GaugeValue, float64(metrics.InodesFree), c.fs) - ch <- prometheus.MustNewConstMetric(c.inodes_allocated, prometheus.GaugeValue, float64(metrics.InodesAllocated), c.fs) - ch <- prometheus.MustNewConstMetric(c.inodes_total, prometheus.GaugeValue, float64(metrics.InodesTotal), c.fs) - ch <- prometheus.MustNewConstMetric(c.fs_total, prometheus.GaugeValue, float64(metrics.FSTotal), c.fs) - ch <- prometheus.MustNewConstMetric(c.fs_free, prometheus.GaugeValue, float64(metrics.FSFree), c.fs) - ch <- prometheus.MustNewConstMetric(c.fs_free_percent, prometheus.GaugeValue, float64(metrics.FSFreePercent), c.fs) - ch <- prometheus.MustNewConstMetric(c.metadata_total, prometheus.GaugeValue, float64(metrics.MetadataTotal), c.fs) - ch <- prometheus.MustNewConstMetric(c.metadata_free, prometheus.GaugeValue, float64(metrics.MetadataFree), c.fs) - ch <- prometheus.MustNewConstMetric(c.metadata_free_percent, prometheus.GaugeValue, float64(metrics.MetadataFreePercent), c.fs) -} -*/ - func collect() { registry := prometheus.NewRegistry() registry.MustRegister(collectors.NewMmdfCollector()) diff --git a/cmd/gpfs_mmdf_exporter/main_test.go b/cmd/gpfs_mmdf_exporter/main_test.go new file mode 100644 index 0000000..b8d274a --- /dev/null +++ b/cmd/gpfs_mmdf_exporter/main_test.go @@ -0,0 +1,32 @@ +// Copyright 2020 Trey Dockendorf +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package main + +import ( + "github.com/prometheus/common/log" + kingpin "gopkg.in/alecthomas/kingpin.v2" + "os" + "testing" +) + +func TestMain(m *testing.M) { + if _, err := kingpin.CommandLine.Parse([]string{"--output=/dne"}); err != nil { + log.Fatal(err) + } + exitVal := m.Run() + os.Exit(exitVal) +} + +func TestCollect(t *testing.T) { +} From 88c4d9f1d587f1a6cbc904832db52d552d43f733 Mon Sep 17 00:00:00 2001 From: Trey Dockendorf Date: Sun, 23 Feb 2020 20:13:24 -0500 Subject: [PATCH 2/4] Update client_golang --- go.mod | 4 ++-- go.sum | 34 ++++++++++++++++++++++++---------- 2 files changed, 26 insertions(+), 12 deletions(-) diff --git a/go.mod b/go.mod index 6d3d0b9..e81e5d7 100644 --- a/go.mod +++ b/go.mod @@ -7,8 +7,8 @@ require ( github.com/c9s/goprocinfo v0.0.0-20191125144613-4acdd056c72d github.com/deniswernert/go-fstab v0.0.0-20141204152952-eb4090f26517 github.com/gofrs/flock v0.7.1 - github.com/prometheus/client_golang v1.3.0 - github.com/prometheus/common v0.8.0 + github.com/prometheus/client_golang v1.4.1 + github.com/prometheus/common v0.9.1 github.com/spf13/afero v1.2.2 // indirect gopkg.in/alecthomas/kingpin.v2 v2.2.6 ) diff --git a/go.sum b/go.sum index bc3b1f4..b1ac0ab 100644 --- a/go.sum +++ b/go.sum @@ -33,13 +33,20 @@ github.com/golang/protobuf v1.3.2 h1:6nsPYzhq5kReh6QImI3k5qWzO4PEbvbIW2cwSfR/6xs github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/google/go-cmp v0.3.1 h1:Xye71clBPdm5HgqGwUkwhbynsUJZhDbS20FvLhQ2izg= github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= +github.com/google/go-cmp v0.4.0 h1:xsAVV57WRhGj6kEIi8ReJzQlHHqcBYCElAvkovg3B/4= +github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= -github.com/json-iterator/go v1.1.8/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= +github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= github.com/konsorten/go-windows-terminal-sequences v1.0.1 h1:mweAR1A6xJ3oS2pRaGiHgQ4OO8tzTaLawm8vnODuwDk= github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= +github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI= +github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= +github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= +github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= +github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/matttproud/golang_protobuf_extensions v1.0.1 h1:4hp9jkHxhMHkqkrB3Ix0jegS5sx/RkqARlsWZ6pIwiU= github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= @@ -53,16 +60,15 @@ github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZb github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= -github.com/prometheus/client_golang v1.3.0 h1:miYCvYqFXtl/J9FIy8eNpBfYthAEFg+Ys0XyUVEcDsc= -github.com/prometheus/client_golang v1.3.0/go.mod h1:hJaj2vgQTGQmVCsAACORcieXFeDPbaTKGT+JTgUa3og= +github.com/prometheus/client_golang v1.4.1 h1:FFSuS004yOQEtDdTq+TAOLP5xUq63KqAFYyOi8zA+Y8= +github.com/prometheus/client_golang v1.4.1/go.mod h1:e9GMxYsXl05ICDXkRhurwBS4Q3OK1iX/F2sw+iXX5zU= github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= -github.com/prometheus/client_model v0.1.0 h1:ElTg5tNp4DqfV7UQjDqv2+RJlNzsDtvNAWccbItceIE= -github.com/prometheus/client_model v0.1.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= +github.com/prometheus/client_model v0.2.0 h1:uq5h0d+GuxiXLJLNABMgp2qUWDPiLvgCzz2dUR+/W/M= +github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= -github.com/prometheus/common v0.7.0/go.mod h1:DjGbpBbp5NYNiECxcL/VnbXCCaQpKd3tt26CguLLsqA= -github.com/prometheus/common v0.8.0 h1:bLkjvFe2ZRX1DpcgZcdf7j/+MnusEps5hktST/FHA34= -github.com/prometheus/common v0.8.0/go.mod h1:PC/OgXc+UN7B4ALwvn1yzVZmVwvhXp5JsbBv6wSv6i0= +github.com/prometheus/common v0.9.1 h1:KOMtN28tlbam3/7ZKEYKHhKoJZYYj3gMH4uc62x7X7U= +github.com/prometheus/common v0.9.1/go.mod h1:yhUN8i9wzaXS3w1O07YhxHEBxD+W35wd8bs7vj7HSQ4= github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= github.com/prometheus/procfs v0.0.8 h1:+fpWZdT24pJBiqJdAwYBjPSk+5YmQzYNPYzQsdzLkt8= @@ -77,6 +83,8 @@ github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+ github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.3.0 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0Q= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= +github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk= +github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -88,15 +96,21 @@ golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5h golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191220142924-d4481acd189f h1:68K/z8GLUxV76xGSqwTWw2gyk/jwn79LUL43rES2g8o= -golang.org/x/sys v0.0.0-20191220142924-d4481acd189f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200122134326-e047566fdf82 h1:ywK/j/KkyTHcdyYSZNXGjMwgmDSfjglYZ3vStQ/gSCU= +golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4= +golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= gopkg.in/alecthomas/kingpin.v2 v2.2.6 h1:jMFz6MfLP0/4fUyZle81rXUoxOBFi19VUFKVDOQfozc= gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo= +gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.4 h1:/eiJrUcujPVeJ3xlSWaiNi3uSVmDGBK1pDHUHAnao1I= gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.5 h1:ymVxjfMaHvXD8RqPRmzHHsB3VvucivSkIAvJFDI5O3c= +gopkg.in/yaml.v2 v2.2.5/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= From 6778d421acfa2ce6d69d9c00ee905c7eb7e04373 Mon Sep 17 00:00:00 2001 From: Trey Dockendorf Date: Sun, 23 Feb 2020 19:53:02 -0500 Subject: [PATCH 3/4] Expand collector tests --- collectors/collector_test.go | 8 +++ collectors/mmces_test.go | 38 +++++++++++- collectors/mmdf.go | 10 ++-- collectors/mmdf_test.go | 73 +++++++++++++++++++++++ collectors/mmdiag_test.go | 54 +++++++++++++++++ collectors/mmhealth_test.go | 43 ++++++++++++++ collectors/mmpmon.go | 1 - collectors/mmpmon_test.go | 43 ++++++++++++++ collectors/mount_test.go | 110 +++++++++++++++++++++++++++++------ collectors/verbs.go | 2 +- collectors/verbs_test.go | 23 ++++++++ go.mod | 2 - go.sum | 4 -- 13 files changed, 379 insertions(+), 32 deletions(-) diff --git a/collectors/collector_test.go b/collectors/collector_test.go index fe9e60f..62c42aa 100644 --- a/collectors/collector_test.go +++ b/collectors/collector_test.go @@ -15,6 +15,7 @@ package collectors import ( "fmt" + "github.com/prometheus/client_golang/prometheus" "os" "os/exec" "strconv" @@ -48,6 +49,13 @@ func TestExecCommandHelper(t *testing.T) { os.Exit(i) } +func setupGatherer(collector Collector) prometheus.Gatherer { + registry := prometheus.NewRegistry() + registry.MustRegister(collector) + gatherers := prometheus.Gatherers{registry} + return gatherers +} + func TestParseMmlsfs(t *testing.T) { execCommand = fakeExecCommand mockedStdout = ` diff --git a/collectors/mmces_test.go b/collectors/mmces_test.go index e02b72f..d697bc4 100644 --- a/collectors/mmces_test.go +++ b/collectors/mmces_test.go @@ -14,7 +14,10 @@ package collectors import ( + "github.com/prometheus/client_golang/prometheus/testutil" + kingpin "gopkg.in/alecthomas/kingpin.v2" "os/exec" + "strings" "testing" ) @@ -22,7 +25,7 @@ func TestParseMmcesStateShow(t *testing.T) { execCommand = fakeExecCommand mockedStdout = ` mmcesstate::HEADER:version:reserved:reserved:NODE:AUTH:BLOCK:NETWORK:AUTH_OBJ:NFS:OBJ:SMB:CES: -mmcesstate::0:1:::ib-protocol01.ten.osc.edu:HEALTHY:DISABLED:HEALTHY:DISABLED:HEALTHY:DISABLED:HEALTHY:HEALTHY: +mmcesstate::0:1:::ib-protocol01.domain:HEALTHY:DISABLED:HEALTHY:DISABLED:HEALTHY:DISABLED:HEALTHY:HEALTHY: ` defer func() { execCommand = exec.Command }() metrics, err := mmces_state_show_parse(mockedStdout) @@ -52,3 +55,36 @@ func TestParseMmcesState(t *testing.T) { t.Errorf("Expected 0 for DEGRADED, got %v", val) } } + +func TestMMcesCollector(t *testing.T) { + if _, err := kingpin.CommandLine.Parse([]string{"--collector.mmces.nodename=ib-protocol01.domain"}); err != nil { + t.Fatal(err) + } + execCommand = fakeExecCommand + mockedStdout = ` +mmcesstate::HEADER:version:reserved:reserved:NODE:AUTH:BLOCK:NETWORK:AUTH_OBJ:NFS:OBJ:SMB:CES: +mmcesstate::0:1:::ib-protocol01.domain:HEALTHY:DISABLED:HEALTHY:DISABLED:HEALTHY:DISABLED:HEALTHY:HEALTHY: +` + defer func() { execCommand = exec.Command }() + metadata := ` + # HELP gpfs_ces_state GPFS CES health status, 1=healthy 0=not healthy + # TYPE gpfs_ces_state gauge` + expected := ` + gpfs_ces_state{service="AUTH",state="HEALTHY"} 1 + gpfs_ces_state{service="AUTH_OBJ",state="DISABLED"} 0 + gpfs_ces_state{service="BLOCK",state="DISABLED"} 0 + gpfs_ces_state{service="CES",state="HEALTHY"} 1 + gpfs_ces_state{service="NETWORK",state="HEALTHY"} 1 + gpfs_ces_state{service="NFS",state="HEALTHY"} 1 + gpfs_ces_state{service="OBJ",state="DISABLED"} 0 + gpfs_ces_state{service="SMB",state="HEALTHY"} 1 + ` + collector := NewMmcesCollector() + gatherers := setupGatherer(collector) + if val := testutil.CollectAndCount(collector); val != 10 { + t.Errorf("Unexpected collection count %d, expected 10", val) + } + if err := testutil.GatherAndCompare(gatherers, strings.NewReader(metadata+expected), "gpfs_ces_state"); err != nil { + t.Errorf("unexpected collecting result:\n%s", err) + } +} diff --git a/collectors/mmdf.go b/collectors/mmdf.go index 94aeb53..b838f04 100644 --- a/collectors/mmdf.go +++ b/collectors/mmdf.go @@ -85,16 +85,16 @@ func NewMmdfCollector() Collector { InodesAllocated: prometheus.NewDesc(prometheus.BuildFQName(namespace, "fs", "inodes_allocated"), "GPFS filesystem inodes allocated", []string{"fs"}, nil), InodesTotal: prometheus.NewDesc(prometheus.BuildFQName(namespace, "fs", "inodes_total"), - "GPFS filesystem inodes total in bytes", []string{"fs"}, nil), - FSTotal: prometheus.NewDesc(prometheus.BuildFQName(namespace, "fs", "total"), + "GPFS filesystem inodes total", []string{"fs"}, nil), + FSTotal: prometheus.NewDesc(prometheus.BuildFQName(namespace, "fs", "total_bytes"), "GPFS filesystem total size in bytes", []string{"fs"}, nil), - FSFree: prometheus.NewDesc(prometheus.BuildFQName(namespace, "fs", "free"), + FSFree: prometheus.NewDesc(prometheus.BuildFQName(namespace, "fs", "free_bytes"), "GPFS filesystem free size in bytes", []string{"fs"}, nil), FSFreePercent: prometheus.NewDesc(prometheus.BuildFQName(namespace, "fs", "free_percent"), "GPFS filesystem free percent", []string{"fs"}, nil), - MetadataTotal: prometheus.NewDesc(prometheus.BuildFQName(namespace, "fs", "metadata_total"), + MetadataTotal: prometheus.NewDesc(prometheus.BuildFQName(namespace, "fs", "metadata_total_bytes"), "GPFS total metadata size in bytes", []string{"fs"}, nil), - MetadataFree: prometheus.NewDesc(prometheus.BuildFQName(namespace, "fs", "metadata_free"), + MetadataFree: prometheus.NewDesc(prometheus.BuildFQName(namespace, "fs", "metadata_free_bytes"), "GPFS metadata free size in bytes", []string{"fs"}, nil), MetadataFreePercent: prometheus.NewDesc(prometheus.BuildFQName(namespace, "fs", "metadata_free_percent"), "GPFS metadata free percent", []string{"fs"}, nil), diff --git a/collectors/mmdf_test.go b/collectors/mmdf_test.go index 23c76e0..07247dd 100644 --- a/collectors/mmdf_test.go +++ b/collectors/mmdf_test.go @@ -14,7 +14,11 @@ package collectors import ( + "github.com/prometheus/client_golang/prometheus/testutil" + "github.com/prometheus/common/log" + kingpin "gopkg.in/alecthomas/kingpin.v2" "os/exec" + "strings" "testing" ) @@ -56,3 +60,72 @@ mmdf:inode:0:1:::430741822:484301506:915043328:1332164000: t.Errorf("Unexpected value for MetadataFreePercent, got %d", dfmetrics.MetadataFreePercent) } } + +func TestMmdfCollector(t *testing.T) { + _ = log.Base().SetLevel("debug") + if _, err := kingpin.CommandLine.Parse([]string{}); err != nil { + t.Fatal(err) + } + filesystems := "project" + configFilesystems = &filesystems + execCommand = fakeExecCommand + mockedStdout = ` +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:fsTotal:0:1:::3661677723648:481202021888:14:12117655064:0: +mmdf:inode:0:1:::430741822:484301506:915043328:1332164000: +` + defer func() { execCommand = exec.Command }() + expected := ` + # 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_percent GPFS filesystem free percent + # TYPE gpfs_fs_free_percent gauge + gpfs_fs_free_percent{fs="project"} 14 + # HELP gpfs_fs_inodes_allocated GPFS filesystem inodes allocated + # TYPE gpfs_fs_inodes_allocated gauge + gpfs_fs_inodes_allocated{fs="project"} 915043328 + # HELP gpfs_fs_inodes_free GPFS filesystem inodes free + # TYPE gpfs_fs_inodes_free gauge + gpfs_fs_inodes_free{fs="project"} 484301506 + # HELP gpfs_fs_inodes_total GPFS filesystem inodes total + # TYPE gpfs_fs_inodes_total gauge + gpfs_fs_inodes_total{fs="project"} 1332164000 + # HELP gpfs_fs_inodes_used GPFS filesystem inodes used + # TYPE gpfs_fs_inodes_used gauge + gpfs_fs_inodes_used{fs="project"} 430741822 + # HELP gpfs_fs_metadata_free_bytes GPFS metadata free size in bytes + # TYPE gpfs_fs_metadata_free_bytes gauge + gpfs_fs_metadata_free_bytes{fs="project"} 6155570511872 + # HELP gpfs_fs_metadata_free_percent GPFS metadata free percent + # TYPE gpfs_fs_metadata_free_percent gauge + gpfs_fs_metadata_free_percent{fs="project"} 43 + # HELP gpfs_fs_metadata_total_bytes GPFS total metadata size in bytes + # TYPE gpfs_fs_metadata_total_bytes gauge + gpfs_fs_metadata_total_bytes{fs="project"} 14224931684352 + # HELP gpfs_fs_total_bytes GPFS filesystem total size in bytes + # TYPE gpfs_fs_total_bytes gauge + gpfs_fs_total_bytes{fs="project"} 3749557989015552 + ` + collector := NewMmdfCollector() + gatherers := setupGatherer(collector) + if val := testutil.CollectAndCount(collector); val != 13 { + t.Errorf("Unexpected collection count %d, expected 13", val) + } + if err := testutil.GatherAndCompare(gatherers, strings.NewReader(expected), + "gpfs_fs_inodes_used", "gpfs_fs_inodes_free", "gpfs_fs_inodes_allocated", "gpfs_fs_inodes_total", + "gpfs_fs_free_bytes", "gpfs_fs_free_percent", "gpfs_fs_total_bytes", + "gpfs_fs_metadata_total_bytes", "gpfs_fs_metadata_free_bytes", "gpfs_fs_metadata_free_percent"); err != nil { + t.Errorf("unexpected collecting result:\n%s", err) + } +} diff --git a/collectors/mmdiag_test.go b/collectors/mmdiag_test.go index 616b40f..c324c17 100644 --- a/collectors/mmdiag_test.go +++ b/collectors/mmdiag_test.go @@ -14,7 +14,10 @@ package collectors import ( + "github.com/prometheus/client_golang/prometheus/testutil" + kingpin "gopkg.in/alecthomas/kingpin.v2" "os/exec" + "strings" "testing" ) @@ -72,3 +75,54 @@ Waiting 0.0002 sec since 10:24:00, monitored, thread 22987 NSDThread: for I/O co t.Errorf("Unexpected waiter thread value %v", val) } } + +func TestMmdiagCollector(t *testing.T) { + if _, err := kingpin.CommandLine.Parse([]string{}); err != nil { + t.Fatal(err) + } + threshold := 30 + configWaiterThreshold = &threshold + configWaiterExclude = &defWaiterExclude + execCommand = fakeExecCommand + mockedStdout = ` +=== mmdiag: waiters === +Waiting 40.4231 sec since 13:08:39, monitored, thread 120656 EventsExporterSenderThread: for poll on sock 1379 +Waiting 64.3890 sec since 17:55:45, monitored, thread 120655 NSDThread: for I/O completion +Waiting 44.3890 sec since 17:55:45, monitored, thread 120656 NSDThread: for I/O completion +Waiting 0.0409 sec since 10:24:00, monitored, thread 23170 NSDThread: for I/O completion +Waiting 0.0259 sec since 10:24:00, monitored, thread 23241 NSDThread: for I/O completion +Waiting 0.0251 sec since 10:24:00, monitored, thread 23243 NSDThread: for I/O completion +Waiting 0.0173 sec since 10:24:00, monitored, thread 22893 NSDThread: for I/O completion +Waiting 0.0158 sec since 10:24:00, monitored, thread 22933 NSDThread: for I/O completion +Waiting 0.0153 sec since 10:24:00, monitored, thread 22953 NSDThread: for I/O completion +Waiting 0.0143 sec since 10:24:00, monitored, thread 22978 NSDThread: for I/O completion +Waiting 0.0139 sec since 10:24:00, monitored, thread 22996 NSDThread: for I/O completion +Waiting 0.0128 sec since 10:24:00, monitored, thread 23025 NSDThread: for I/O completion +Waiting 0.0121 sec since 10:24:00, monitored, thread 23047 NSDThread: for I/O completion +Waiting 0.0114 sec since 10:24:00, monitored, thread 23075 NSDThread: for I/O completion +Waiting 0.0109 sec since 10:24:00, monitored, thread 23097 NSDThread: for I/O completion +Waiting 0.0099 sec since 10:24:00, monitored, thread 23130 NSDThread: for I/O completion +Waiting 0.0069 sec since 10:24:00, monitored, thread 23337 NSDThread: for I/O completion +Waiting 0.0063 sec since 10:24:00, monitored, thread 23227 NSDThread: for I/O completion +Waiting 0.0039 sec since 10:24:00, monitored, thread 23267 NSDThread: for I/O completion +Waiting 0.0023 sec since 10:24:00, monitored, thread 22922 NSDThread: for I/O completion +Waiting 0.0022 sec since 10:24:00, monitored, thread 22931 NSDThread: for I/O completion +Waiting 0.0002 sec since 10:24:00, monitored, thread 22987 NSDThread: for I/O completion +` + defer func() { execCommand = exec.Command }() + metadata := ` + # HELP gpfs_mmdiag_waiter GPFS max waiter in seconds + # TYPE gpfs_mmdiag_waiter gauge` + expected := ` + gpfs_mmdiag_waiter{thread="120655"} 64.3890 + gpfs_mmdiag_waiter{thread="120656"} 44.3890 + ` + collector := NewMmdiagCollector() + gatherers := setupGatherer(collector) + if val := testutil.CollectAndCount(collector); val != 4 { + t.Errorf("Unexpected collection count %d, expected 4", val) + } + if err := testutil.GatherAndCompare(gatherers, strings.NewReader(metadata+expected), "gpfs_mmdiag_waiter"); err != nil { + t.Errorf("unexpected collecting result:\n%s", err) + } +} diff --git a/collectors/mmhealth_test.go b/collectors/mmhealth_test.go index ced7680..d2b7af7 100644 --- a/collectors/mmhealth_test.go +++ b/collectors/mmhealth_test.go @@ -14,7 +14,9 @@ package collectors import ( + "github.com/prometheus/client_golang/prometheus/testutil" "os/exec" + "strings" "testing" ) @@ -105,3 +107,44 @@ func TestParseMmhealthStatus(t *testing.T) { t.Errorf("Expected 0 for DEGRADED, got %v", val) } } + +func TestMmhealthCollector(t *testing.T) { + execCommand = fakeExecCommand + mockedStdout = ` +mmhealth:Event:HEADER:version:reserved:reserved:node:component:entityname:entitytype:event:arguments:activesince:identifier:ishidden: +mmhealth:State:HEADER:version:reserved:reserved:node:component:entityname:entitytype:status:laststatuschange: +mmhealth:State:0:1:::ib-haswell1.example.com:NODE:ib-haswell1.example.com:NODE:TIPS:2020-01-27 09%3A35%3A21.859186 EST: +mmhealth:State:0:1:::ib-haswell1.example.com:GPFS:ib-haswell1.example.com:NODE:TIPS:2020-01-27 09%3A35%3A21.791895 EST: +mmhealth:Event:0:1:::ib-haswell1.example.com:GPFS:ib-haswell1.example.com:NODE:gpfs_pagepool_small::2020-01-07 16%3A47%3A43.892296 EST::no: +mmhealth:State:0:1:::ib-haswell1.example.com:NETWORK:ib-haswell1.example.com:NODE:HEALTHY:2020-01-07 17%3A02%3A40.131272 EST: +mmhealth:State:0:1:::ib-haswell1.example.com:NETWORK:ib0:NIC:HEALTHY:2020-01-07 16%3A47%3A39.397852 EST: +mmhealth:State:0:1:::ib-haswell1.example.com:NETWORK:mlx5_0/1:IB_RDMA:HEALTHY:2020-01-07 17%3A02%3A40.205075 EST: +mmhealth:State:0:1:::ib-haswell1.example.com:FILESYSTEM:ib-haswell1.example.com:NODE:HEALTHY:2020-01-27 09%3A35%3A21.499264 EST: +mmhealth:State:0:1:::ib-haswell1.example.com:FILESYSTEM:project:FILESYSTEM:HEALTHY:2020-01-27 09%3A35%3A21.573978 EST: +mmhealth:State:0:1:::ib-haswell1.example.com:FILESYSTEM:scratch:FILESYSTEM:HEALTHY:2020-01-27 09%3A35%3A21.657798 EST: +mmhealth:State:0:1:::ib-haswell1.example.com:FILESYSTEM:ess:FILESYSTEM:HEALTHY:2020-01-27 09%3A35%3A21.716417 EST: +` + defer func() { execCommand = exec.Command }() + metadata := ` + # HELP gpfs_health_status GPFS health status, 1=healthy 0=not healthy + # TYPE gpfs_health_status gauge` + expected := ` + gpfs_health_status{component="FILESYSTEM",entityname="ib-haswell1.example.com",entitytype="NODE",status="HEALTHY"} 1 + gpfs_health_status{component="FILESYSTEM",entityname="project",entitytype="FILESYSTEM",status="HEALTHY"} 1 + gpfs_health_status{component="FILESYSTEM",entityname="scratch",entitytype="FILESYSTEM",status="HEALTHY"} 1 + gpfs_health_status{component="FILESYSTEM",entityname="ess",entitytype="FILESYSTEM",status="HEALTHY"} 1 + gpfs_health_status{component="GPFS",entityname="ib-haswell1.example.com",entitytype="NODE",status="TIPS"} 0 + gpfs_health_status{component="NETWORK",entityname="ib-haswell1.example.com",entitytype="NODE",status="HEALTHY"} 1 + gpfs_health_status{component="NETWORK",entityname="ib0",entitytype="NIC",status="HEALTHY"} 1 + gpfs_health_status{component="NETWORK",entityname="mlx5_0/1",entitytype="IB_RDMA",status="HEALTHY"} 1 + gpfs_health_status{component="NODE",entityname="ib-haswell1.example.com",entitytype="NODE",status="TIPS"} 0 + ` + collector := NewMmhealthCollector() + gatherers := setupGatherer(collector) + if val := testutil.CollectAndCount(collector); val != 11 { + t.Errorf("Unexpected collection count %d, expected 11", val) + } + if err := testutil.GatherAndCompare(gatherers, strings.NewReader(metadata+expected), "gpfs_health_status"); err != nil { + t.Errorf("unexpected collecting result:\n%s", err) + } +} diff --git a/collectors/mmpmon.go b/collectors/mmpmon.go index e9898ca..79112eb 100644 --- a/collectors/mmpmon.go +++ b/collectors/mmpmon.go @@ -97,7 +97,6 @@ func (c *MmpmonCollector) collect(ch chan<- prometheus.Metric) error { } perfs, err := mmpmon_parse(mmpmon_out) if err != nil { - ch <- prometheus.MustNewConstMetric(collectError, prometheus.GaugeValue, 1, "mmpmon") return err } for _, perf := range perfs { diff --git a/collectors/mmpmon_test.go b/collectors/mmpmon_test.go index a915c6f..9b4db24 100644 --- a/collectors/mmpmon_test.go +++ b/collectors/mmpmon_test.go @@ -14,7 +14,9 @@ package collectors import ( + "github.com/prometheus/client_golang/prometheus/testutil" "os/exec" + "strings" "testing" ) @@ -49,3 +51,44 @@ _fs_io_s_ _n_ 10.22.0.106 _nn_ ib-pitzer-rw02.ten _rc_ 0 _t_ 1579358234 _tu_ 532 t.Errorf("Unexpected ReadBytes got %d", val) } } + +func TestMmpmonCollector(t *testing.T) { + execCommand = fakeExecCommand + mockedStdout = ` +_fs_io_s_ _n_ 10.22.0.106 _nn_ ib-pitzer-rw02.ten _rc_ 0 _t_ 1579358234 _tu_ 53212 _cl_ gpfs.osc.edu _fs_ scratch _d_ 48 _br_ 205607400434 _bw_ 74839282351 _oc_ 2377656 _cc_ 2201576 _rdc_ 59420404 _wc_ 18874626 _dir_ 40971 _iu_ 544768 +_fs_io_s_ _n_ 10.22.0.106 _nn_ ib-pitzer-rw02.ten _rc_ 0 _t_ 1579358234 _tu_ 53212 _cl_ gpfs.osc.edu _fs_ project _d_ 96 _br_ 0 _bw_ 0 _oc_ 513 _cc_ 513 _rdc_ 0 _wc_ 0 _dir_ 0 _iu_ 169 +` + defer func() { execCommand = exec.Command }() + expected := ` + # HELP gpfs_perf_operations GPFS operationgs reported by mmpmon + # TYPE gpfs_perf_operations counter + gpfs_perf_operations{fs="project",nodename="ib-pitzer-rw02.ten",operation="closes"} 513 + gpfs_perf_operations{fs="project",nodename="ib-pitzer-rw02.ten",operation="inode_updates"} 169 + gpfs_perf_operations{fs="project",nodename="ib-pitzer-rw02.ten",operation="opens"} 513 + gpfs_perf_operations{fs="project",nodename="ib-pitzer-rw02.ten",operation="read_dir"} 0 + gpfs_perf_operations{fs="project",nodename="ib-pitzer-rw02.ten",operation="reads"} 0 + gpfs_perf_operations{fs="project",nodename="ib-pitzer-rw02.ten",operation="writes"} 0 + gpfs_perf_operations{fs="scratch",nodename="ib-pitzer-rw02.ten",operation="closes"} 2201576 + gpfs_perf_operations{fs="scratch",nodename="ib-pitzer-rw02.ten",operation="inode_updates"} 544768 + gpfs_perf_operations{fs="scratch",nodename="ib-pitzer-rw02.ten",operation="opens"} 2377656 + gpfs_perf_operations{fs="scratch",nodename="ib-pitzer-rw02.ten",operation="read_dir"} 40971 + gpfs_perf_operations{fs="scratch",nodename="ib-pitzer-rw02.ten",operation="reads"} 59420404 + gpfs_perf_operations{fs="scratch",nodename="ib-pitzer-rw02.ten",operation="writes"} 18874626 + # HELP gpfs_perf_read_bytes GPFS read bytes + # TYPE gpfs_perf_read_bytes counter + gpfs_perf_read_bytes{fs="project",nodename="ib-pitzer-rw02.ten"} 0 + gpfs_perf_read_bytes{fs="scratch",nodename="ib-pitzer-rw02.ten"} 2.05607400434e+11 + # HELP gpfs_perf_write_bytes GPFS write bytes + # TYPE gpfs_perf_write_bytes counter + gpfs_perf_write_bytes{fs="project",nodename="ib-pitzer-rw02.ten"} 0 + gpfs_perf_write_bytes{fs="scratch",nodename="ib-pitzer-rw02.ten"} 74839282351 + ` + collector := NewMmpmonCollector() + gatherers := setupGatherer(collector) + if val := testutil.CollectAndCount(collector); val != 18 { + t.Errorf("Unexpected collection count %d, expected 18", val) + } + if err := testutil.GatherAndCompare(gatherers, strings.NewReader(expected), "gpfs_perf_read_bytes", "gpfs_perf_write_bytes", "gpfs_perf_operations"); err != nil { + t.Errorf("unexpected collecting result:\n%s", err) + } +} diff --git a/collectors/mount_test.go b/collectors/mount_test.go index baa92ad..4a5beb6 100644 --- a/collectors/mount_test.go +++ b/collectors/mount_test.go @@ -14,20 +14,30 @@ package collectors import ( - "github.com/Flaque/filet" + "github.com/prometheus/client_golang/prometheus/testutil" + kingpin "gopkg.in/alecthomas/kingpin.v2" + "io/ioutil" + "os" + "strings" "testing" ) func TestGetGPFSMounts(t *testing.T) { - procMounts = "/tmp/proc-mounts" + tmpDir, err := ioutil.TempDir(os.TempDir(), "proc") + if err != nil { + t.Fatal(err) + } + defer os.RemoveAll(tmpDir) + procMounts = tmpDir + "/mounts" mockedProcMounts := `pitzer_root.ten.osc.edu:/pitzer_root_rhel76_1 / nfs rw,relatime,vers=3,rsize=65536,wsize=65536,namlen=255,acregmin=240,acregmax=240,acdirmin=240,acdirmax=240,hard,nolock,proto=tcp,timeo=600,retrans=2,sec=sys,mountaddr=10.27.2.2,mountvers=3,mountport=635,mountproto=tcp,fsc,local_lock=all,addr=10.27.2.2 0 0 /dev/mapper/vg0-lv_tmp /tmp xfs rw,relatime,attr2,inode64,noquota 0 0 scratch /fs/scratch gpfs rw,relatime 0 0 project /fs/project gpfs rw,relatime 0 0 10.11.200.17:/PZS0710 /users/PZS0710 nfs4 rw,relatime,vers=4.0,rsize=65536,wsize=65536,namlen=255,hard,proto=tcp,timeo=600,retrans=2,sec=sys,clientaddr=10.4.0.102,local_lock=none,addr=10.11.200.17 0 0 ` - filet.File(t, "/tmp/proc-mounts", mockedProcMounts) - defer filet.CleanUp(t) + if err := ioutil.WriteFile(procMounts, []byte(mockedProcMounts), 0644); err != nil { + t.Fatal(err) + } gpfsMounts, err := getGPFSMounts() if err != nil { t.Errorf("Unexpected error: %s", err.Error()) @@ -42,18 +52,82 @@ project /fs/project gpfs rw,relatime 0 0 if val := gpfsMounts[1]; val != "/fs/project" { t.Errorf("Unexpected Path value %s", val) } - /* - if val := gpfsMounts[0].Path ; val != "/fs/scratch" { - t.Errorf("Unexpected Path value %s", val) - } - if val := gpfsMounts[0].Mounted ; !val { - t.Errorf("Unexpected value for Mounted, %v", val) - } - if val := gpfsMounts[1].Path ; val != "/fs/project" { - t.Errorf("Unexpected Path value %s", val) - } - if val := gpfsMounts[1].Mounted ; !val { - t.Errorf("Unexpected value for Mounted, %v", val) - } - */ +} + +func TestGetGPFSMountsFSTab(t *testing.T) { + tmpDir, err := ioutil.TempDir(os.TempDir(), "proc") + if err != nil { + t.Fatal(err) + } + defer os.RemoveAll(tmpDir) + fstabPath = tmpDir + "/fstab" + mockedFstab := ` +LABEL=tmp /tmp xfs defaults 1 2 +project /fs/project gpfs rw,mtime,atime,quota=userquota;groupquota;filesetquota;perfileset,dev=project,noauto 0 0 +scratch /fs/scratch gpfs rw,mtime,atime,quota=userquota;groupquota;filesetquota;perfileset,dev=scratch,noauto 0 0 + ` + if err := ioutil.WriteFile(fstabPath, []byte(mockedFstab), 0644); err != nil { + t.Fatal(err) + } + gpfsMounts, err := getGPFSMountsFSTab() + if err != nil { + t.Errorf("Unexpected error: %s", err.Error()) + return + } + if len(gpfsMounts) != 2 { + t.Errorf("Incorrect number fo GPFS mounts, expected 2, got %d", len(gpfsMounts)) + } + if val := gpfsMounts[0]; val != "/fs/project" { + t.Errorf("Unexpected value %s", val) + } + if val := gpfsMounts[1]; val != "/fs/scratch" { + t.Errorf("Unexpected value %s", val) + } +} + +func TestMountCollector(t *testing.T) { + if _, err := kingpin.CommandLine.Parse([]string{}); err != nil { + t.Fatal(err) + } + mounts := "/fs/project,/fs/scratch,/fs/ess" + configMounts = &mounts + tmpDir, err := ioutil.TempDir(os.TempDir(), "proc") + if err != nil { + t.Fatal(err) + } + defer os.RemoveAll(tmpDir) + procMounts = tmpDir + "/mounts" + fstabPath = tmpDir + "/fstab" + mockedProcMounts := `pitzer_root.ten.osc.edu:/pitzer_root_rhel76_1 / nfs rw,relatime,vers=3,rsize=65536,wsize=65536,namlen=255,acregmin=240,acregmax=240,acdirmin=240,acdirmax=240,hard,nolock,proto=tcp,timeo=600,retrans=2,sec=sys,mountaddr=10.27.2.2,mountvers=3,mountport=635,mountproto=tcp,fsc,local_lock=all,addr=10.27.2.2 0 0 +/dev/mapper/vg0-lv_tmp /tmp xfs rw,relatime,attr2,inode64,noquota 0 0 +scratch /fs/scratch gpfs rw,relatime 0 0 +project /fs/project gpfs rw,relatime 0 0 +10.11.200.17:/PZS0710 /users/PZS0710 nfs4 rw,relatime,vers=4.0,rsize=65536,wsize=65536,namlen=255,hard,proto=tcp,timeo=600,retrans=2,sec=sys,clientaddr=10.4.0.102,local_lock=none,addr=10.11.200.17 0 0 +` + mockedFstab := ` +project /fs/project gpfs rw,mtime,atime,quota=userquota;groupquota;filesetquota;perfileset,dev=project,noauto 0 0 +scratch /fs/scratch gpfs rw,mtime,atime,quota=userquota;groupquota;filesetquota;perfileset,dev=scratch,noauto 0 0 + ` + if err := ioutil.WriteFile(procMounts, []byte(mockedProcMounts), 0644); err != nil { + t.Fatal(err) + } + if err := ioutil.WriteFile(fstabPath, []byte(mockedFstab), 0644); err != nil { + t.Fatal(err) + } + metadata := ` + # HELP gpfs_mount_status Status of GPFS filesystems, 1=mounted 0=not mounted + # TYPE gpfs_mount_status gauge` + expected := ` + gpfs_mount_status{mount="/fs/ess"} 0 + gpfs_mount_status{mount="/fs/project"} 1 + gpfs_mount_status{mount="/fs/scratch"} 1 + ` + collector := NewMountCollector() + gatherers := setupGatherer(collector) + if val := testutil.CollectAndCount(collector); val != 5 { + t.Errorf("Unexpected collection count %d, expected 5", val) + } + if err := testutil.GatherAndCompare(gatherers, strings.NewReader(metadata+expected), "gpfs_mount_status"); err != nil { + t.Errorf("unexpected collecting result:\n%s", err) + } } diff --git a/collectors/verbs.go b/collectors/verbs.go index 0248398..9b4f2c3 100644 --- a/collectors/verbs.go +++ b/collectors/verbs.go @@ -95,7 +95,7 @@ func verbs_parse(out string) (VerbsMetrics, error) { } items := strings.Split(l, ": ") if len(items) == 2 { - metric.Status = items[1] + metric.Status = strings.TrimSuffix(items[1], "\n") break } } diff --git a/collectors/verbs_test.go b/collectors/verbs_test.go index def0cbd..3564334 100644 --- a/collectors/verbs_test.go +++ b/collectors/verbs_test.go @@ -14,7 +14,9 @@ package collectors import ( + "github.com/prometheus/client_golang/prometheus/testutil" "os/exec" + "strings" "testing" ) @@ -49,3 +51,24 @@ VERBS RDMA status: started t.Errorf("Unexpected value for status, expected started, got %s", metric.Status) } } + +func TestVerbsCollector(t *testing.T) { + execCommand = fakeExecCommand + mockedStdout = ` +VERBS RDMA status: started +` + defer func() { execCommand = exec.Command }() + expected := ` + # HELP gpfs_verbs_status GPFS verbs status, 1=started 0=not started + # TYPE gpfs_verbs_status gauge + gpfs_verbs_status 1 + ` + collector := NewVerbsCollector() + gatherers := setupGatherer(collector) + if val := testutil.CollectAndCount(collector); val != 3 { + t.Errorf("Unexpected collection count %d, expected 3", val) + } + if err := testutil.GatherAndCompare(gatherers, strings.NewReader(expected), "gpfs_verbs_status"); err != nil { + t.Errorf("unexpected collecting result:\n%s", err) + } +} diff --git a/go.mod b/go.mod index e81e5d7..e534b19 100644 --- a/go.mod +++ b/go.mod @@ -3,12 +3,10 @@ module github.com/treydock/gpfs_exporter go 1.13 require ( - github.com/Flaque/filet v0.0.0-20190209224823-fc4d33cfcf93 github.com/c9s/goprocinfo v0.0.0-20191125144613-4acdd056c72d github.com/deniswernert/go-fstab v0.0.0-20141204152952-eb4090f26517 github.com/gofrs/flock v0.7.1 github.com/prometheus/client_golang v1.4.1 github.com/prometheus/common v0.9.1 - github.com/spf13/afero v1.2.2 // indirect gopkg.in/alecthomas/kingpin.v2 v2.2.6 ) diff --git a/go.sum b/go.sum index b1ac0ab..ced3137 100644 --- a/go.sum +++ b/go.sum @@ -1,5 +1,3 @@ -github.com/Flaque/filet v0.0.0-20190209224823-fc4d33cfcf93 h1:NnAUCP75PRm8yWE7+MZBIAR6PA9iwsBYEc6ZNYOy+AQ= -github.com/Flaque/filet v0.0.0-20190209224823-fc4d33cfcf93/go.mod h1:TK+jB3mBs+8ZMWhU5BqZKnZWJ1MrLo8etNVg51ueTBo= github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751 h1:JYp7IbQjafoB+tBA3gMyHYHrpOtNuDiK/uB5uXxq5wM= github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= @@ -76,8 +74,6 @@ github.com/prometheus/procfs v0.0.8/go.mod h1:7Qr8sr6344vo1JqZ6HhLceV9o3AJ1Ff+Gx github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= github.com/sirupsen/logrus v1.4.2 h1:SPIRibHv4MatM3XXNO2BJeFLZwZ2LvZgfQ5+UNI2im4= github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= -github.com/spf13/afero v1.2.2 h1:5jhuqJyZCZf2JRofRvN/nIFgIWNzPa3/Vz8mYylgbWc= -github.com/spf13/afero v1.2.2/go.mod h1:9ZxEEn6pIJ8Rxe320qSDBk6AsU0r9pR7Q4OcevTdifk= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= From 7777bfbc0c5c3c3c66c5c31bb89ba548dc4e9258 Mon Sep 17 00:00:00 2001 From: Trey Dockendorf Date: Mon, 24 Feb 2020 14:30:14 -0500 Subject: [PATCH 4/4] Disable codecov comments --- codecov.yml | 1 + 1 file changed, 1 insertion(+) create mode 100644 codecov.yml diff --git a/codecov.yml b/codecov.yml new file mode 100644 index 0000000..69cb760 --- /dev/null +++ b/codecov.yml @@ -0,0 +1 @@ +comment: false