From 2b74cf7498d61b68d07a0373c483397232ae9b79 Mon Sep 17 00:00:00 2001 From: stuart nelson Date: Wed, 28 Sep 2016 21:08:52 +0200 Subject: [PATCH 1/3] Export devstat for dragonfly --- collector/devstat_dragonfly.go | 232 +++++++++++++++++++++++++++++++++ 1 file changed, 232 insertions(+) create mode 100644 collector/devstat_dragonfly.go diff --git a/collector/devstat_dragonfly.go b/collector/devstat_dragonfly.go new file mode 100644 index 0000000..383460a --- /dev/null +++ b/collector/devstat_dragonfly.go @@ -0,0 +1,232 @@ +// Copyright 2016 The Prometheus Authors +// 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. + +// +build !nodevstat + +package collector + +import ( + "errors" + "fmt" + + "github.com/prometheus/client_golang/prometheus" +) + +/* +#cgo LDFLAGS: -ldevstat +#include +#include +#include + +typedef struct { + char device[DEVSTAT_NAME_LEN]; + int unit; + uint64_t bytes; + uint64_t transfers; + uint64_t blocks; + double kb_per_transfer; + double transfers_per_second; + double mb_per_second; + double blocks_per_second; + double ms_per_transaction; +} Stats; + +int _get_ndevs() { + struct statinfo current; + int num_devices; + + current.dinfo = (struct devinfo *)calloc(1, sizeof(struct devinfo)); + if (current.dinfo == NULL) + return -2; + + checkversion(); + + if (getdevs(¤t) == -1) + return -1; + + return current.dinfo->numdevs; +} + +Stats _get_stats(int i) { + struct statinfo current; + int num_devices; + + current.dinfo = (struct devinfo *)calloc(1, sizeof(struct devinfo)); + getdevs(¤t); + + num_devices = current.dinfo->numdevs; + Stats stats; + + uint64_t total_bytes, total_transfers, total_blocks; + long double kb_per_transfer, transfers_per_second, mb_per_second, blocks_per_second, ms_per_transaction; + + strcpy(stats.device, current.dinfo->devices[i].device_name); + stats.unit = current.dinfo->devices[i].unit_number; + compute_stats(¤t.dinfo->devices[i], + NULL, + 1.0, + &total_bytes, + &total_transfers, + &total_blocks, + &kb_per_transfer, + &transfers_per_second, + &mb_per_second, + &blocks_per_second, + &ms_per_transaction); + + stats.bytes = total_bytes; + stats.transfers = total_transfers; + stats.blocks = total_blocks; + stats.kb_per_transfer = kb_per_transfer; + stats.transfers_per_second = transfers_per_second; + stats.mb_per_second = mb_per_second; + stats.blocks_per_second = blocks_per_second; + stats.ms_per_transaction = ms_per_transaction; + + return stats; +} +*/ +import "C" + +const ( + devstatSubsystem = "devstat" +) + +type devstatCollector struct { + bytes_total *prometheus.CounterVec + transfers_total *prometheus.CounterVec + blocks_total *prometheus.CounterVec + bytes_per_transfer *prometheus.GaugeVec + transfers_per_second *prometheus.GaugeVec + bytes_per_second *prometheus.GaugeVec + blocks_per_second *prometheus.GaugeVec + seconds_per_transaction *prometheus.GaugeVec +} + +func init() { + Factories["devstat"] = NewDevstatCollector +} + +// Takes a prometheus registry and returns a new Collector exposing +// Device stats. +func NewDevstatCollector() (Collector, error) { + return &devstatCollector{ + bytes_total: prometheus.NewCounterVec( + prometheus.CounterOpts{ + Namespace: Namespace, + Subsystem: devstatSubsystem, + Name: "bytes_total", + Help: "The total number of bytes transferred for reads and writes on the device.", + }, + []string{"device"}, + ), + transfers_total: prometheus.NewCounterVec( + prometheus.CounterOpts{ + Namespace: Namespace, + Subsystem: devstatSubsystem, + Name: "transfers_total", + Help: "The total number of transactions completed.", + }, + []string{"device"}, + ), + blocks_total: prometheus.NewCounterVec( + prometheus.CounterOpts{ + Namespace: Namespace, + Subsystem: devstatSubsystem, + Name: "blocks_total", + Help: "The total number of bytes given in terms of the devices blocksize.", + }, + []string{"device"}, + ), + bytes_per_transfer: prometheus.NewGaugeVec( + prometheus.GaugeOpts{ + Namespace: Namespace, + Subsystem: devstatSubsystem, + Name: "bytes_per_transfer", + Help: "The average number of bytes per transfer.", + }, + []string{"device"}, + ), + transfers_per_second: prometheus.NewGaugeVec( + prometheus.GaugeOpts{ + Namespace: Namespace, + Subsystem: devstatSubsystem, + Name: "transfers_per_second", + Help: "The average number of transfers per second.", + }, + []string{"device"}, + ), + bytes_per_second: prometheus.NewGaugeVec( + prometheus.GaugeOpts{ + Namespace: Namespace, + Subsystem: devstatSubsystem, + Name: "bytes_per_second", + Help: "The average bytes per second.", + }, + []string{"device"}, + ), + blocks_per_second: prometheus.NewGaugeVec( + prometheus.GaugeOpts{ + Namespace: Namespace, + Subsystem: devstatSubsystem, + Name: "blocks_per_second", + Help: "The average blocks per second.", + }, + []string{"device"}, + ), + seconds_per_transaction: prometheus.NewGaugeVec( + prometheus.GaugeOpts{ + Namespace: Namespace, + Subsystem: devstatSubsystem, + Name: "seconds_per_transaction", + Help: "The average number of seconds per transaction.", + }, + []string{"device"}, + ), + }, nil +} + +func (c *devstatCollector) Update(ch chan<- prometheus.Metric) (err error) { + count := C._get_ndevs() + if count == -1 { + return errors.New("getdevs() failed") + } + if count == -2 { + return errors.New("calloc() failed") + } + + for i := C.int(0); i < count; i++ { + stats := C._get_stats(i) + device := fmt.Sprintf("%s%d", C.GoString(&stats.device[0]), stats.unit) + + c.bytes_total.With(prometheus.Labels{"device": device}).Set(float64(stats.bytes)) + c.transfers_total.With(prometheus.Labels{"device": device}).Set(float64(stats.transfers)) + c.blocks_total.With(prometheus.Labels{"device": device}).Set(float64(stats.blocks)) + c.bytes_per_transfer.With(prometheus.Labels{"device": device}).Set(float64(stats.kb_per_transfer) * 1000) + c.bytes_per_second.With(prometheus.Labels{"device": device}).Set(float64(stats.mb_per_second) * 1000000) + c.transfers_per_second.With(prometheus.Labels{"device": device}).Set(float64(stats.transfers_per_second)) + c.blocks_per_second.With(prometheus.Labels{"device": device}).Set(float64(stats.blocks_per_second)) + c.seconds_per_transaction.With(prometheus.Labels{"device": device}).Set(float64(stats.ms_per_transaction) / 1000) + } + + c.bytes_total.Collect(ch) + c.transfers_total.Collect(ch) + c.blocks_total.Collect(ch) + c.bytes_per_transfer.Collect(ch) + c.bytes_per_second.Collect(ch) + c.transfers_per_second.Collect(ch) + c.blocks_per_second.Collect(ch) + c.seconds_per_transaction.Collect(ch) + + return err +} From 08bc709c3525143e7cdeca93f52496c0f3272167 Mon Sep 17 00:00:00 2001 From: stuart nelson Date: Fri, 7 Oct 2016 18:40:33 +0200 Subject: [PATCH 2/3] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index d2e9c56..334a488 100644 --- a/README.md +++ b/README.md @@ -41,7 +41,7 @@ vmstat | Exposes statistics from `/proc/vmstat`. | Linux Name | Description | OS ---------|-------------|---- bonding | Exposes the number of configured and active slaves of Linux bonding interfaces. | Linux -devstat | Exposes device statistics | FreeBSD +devstat | Exposes device statistics | Dragonfly, FreeBSD gmond | Exposes statistics from Ganglia. | _any_ interrupts | Exposes detailed interrupts statistics. | Linux, OpenBSD ipvs | Exposes IPVS status from `/proc/net/ip_vs` and stats from `/proc/net/ip_vs_stats`. | Linux From e589a2b8afbb710f540e5a8f8af097fdc23ab9d4 Mon Sep 17 00:00:00 2001 From: stuart nelson Date: Wed, 19 Oct 2016 17:42:22 +0200 Subject: [PATCH 3/3] Remove gauges and convert to NewConstMetric format --- collector/devstat_dragonfly.go | 122 +++++---------------------------- 1 file changed, 18 insertions(+), 104 deletions(-) diff --git a/collector/devstat_dragonfly.go b/collector/devstat_dragonfly.go index 383460a..13aa1a5 100644 --- a/collector/devstat_dragonfly.go +++ b/collector/devstat_dragonfly.go @@ -34,11 +34,6 @@ typedef struct { uint64_t bytes; uint64_t transfers; uint64_t blocks; - double kb_per_transfer; - double transfers_per_second; - double mb_per_second; - double blocks_per_second; - double ms_per_transaction; } Stats; int _get_ndevs() { @@ -87,11 +82,6 @@ Stats _get_stats(int i) { stats.bytes = total_bytes; stats.transfers = total_transfers; stats.blocks = total_blocks; - stats.kb_per_transfer = kb_per_transfer; - stats.transfers_per_second = transfers_per_second; - stats.mb_per_second = mb_per_second; - stats.blocks_per_second = blocks_per_second; - stats.ms_per_transaction = ms_per_transaction; return stats; } @@ -103,14 +93,9 @@ const ( ) type devstatCollector struct { - bytes_total *prometheus.CounterVec - transfers_total *prometheus.CounterVec - blocks_total *prometheus.CounterVec - bytes_per_transfer *prometheus.GaugeVec - transfers_per_second *prometheus.GaugeVec - bytes_per_second *prometheus.GaugeVec - blocks_per_second *prometheus.GaugeVec - seconds_per_transaction *prometheus.GaugeVec + bytesDesc *prometheus.Desc + transfersDesc *prometheus.Desc + blocksDesc *prometheus.Desc } func init() { @@ -121,77 +106,20 @@ func init() { // Device stats. func NewDevstatCollector() (Collector, error) { return &devstatCollector{ - bytes_total: prometheus.NewCounterVec( - prometheus.CounterOpts{ - Namespace: Namespace, - Subsystem: devstatSubsystem, - Name: "bytes_total", - Help: "The total number of bytes transferred for reads and writes on the device.", - }, - []string{"device"}, + bytesDesc: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, devstatSubsystem, "bytes_total"), + "The total number of bytes transferred for reads and writes on the device.", + []string{"device"}, nil, ), - transfers_total: prometheus.NewCounterVec( - prometheus.CounterOpts{ - Namespace: Namespace, - Subsystem: devstatSubsystem, - Name: "transfers_total", - Help: "The total number of transactions completed.", - }, - []string{"device"}, + transfersDesc: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, devstatSubsystem, "transfers_total"), + "The total number of transactions completed.", + []string{"device"}, nil, ), - blocks_total: prometheus.NewCounterVec( - prometheus.CounterOpts{ - Namespace: Namespace, - Subsystem: devstatSubsystem, - Name: "blocks_total", - Help: "The total number of bytes given in terms of the devices blocksize.", - }, - []string{"device"}, - ), - bytes_per_transfer: prometheus.NewGaugeVec( - prometheus.GaugeOpts{ - Namespace: Namespace, - Subsystem: devstatSubsystem, - Name: "bytes_per_transfer", - Help: "The average number of bytes per transfer.", - }, - []string{"device"}, - ), - transfers_per_second: prometheus.NewGaugeVec( - prometheus.GaugeOpts{ - Namespace: Namespace, - Subsystem: devstatSubsystem, - Name: "transfers_per_second", - Help: "The average number of transfers per second.", - }, - []string{"device"}, - ), - bytes_per_second: prometheus.NewGaugeVec( - prometheus.GaugeOpts{ - Namespace: Namespace, - Subsystem: devstatSubsystem, - Name: "bytes_per_second", - Help: "The average bytes per second.", - }, - []string{"device"}, - ), - blocks_per_second: prometheus.NewGaugeVec( - prometheus.GaugeOpts{ - Namespace: Namespace, - Subsystem: devstatSubsystem, - Name: "blocks_per_second", - Help: "The average blocks per second.", - }, - []string{"device"}, - ), - seconds_per_transaction: prometheus.NewGaugeVec( - prometheus.GaugeOpts{ - Namespace: Namespace, - Subsystem: devstatSubsystem, - Name: "seconds_per_transaction", - Help: "The average number of seconds per transaction.", - }, - []string{"device"}, + blocksDesc: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, devstatSubsystem, "blocks_total"), + "The total number of bytes given in terms of the devices blocksize.", + []string{"device"}, nil, ), }, nil } @@ -209,24 +137,10 @@ func (c *devstatCollector) Update(ch chan<- prometheus.Metric) (err error) { stats := C._get_stats(i) device := fmt.Sprintf("%s%d", C.GoString(&stats.device[0]), stats.unit) - c.bytes_total.With(prometheus.Labels{"device": device}).Set(float64(stats.bytes)) - c.transfers_total.With(prometheus.Labels{"device": device}).Set(float64(stats.transfers)) - c.blocks_total.With(prometheus.Labels{"device": device}).Set(float64(stats.blocks)) - c.bytes_per_transfer.With(prometheus.Labels{"device": device}).Set(float64(stats.kb_per_transfer) * 1000) - c.bytes_per_second.With(prometheus.Labels{"device": device}).Set(float64(stats.mb_per_second) * 1000000) - c.transfers_per_second.With(prometheus.Labels{"device": device}).Set(float64(stats.transfers_per_second)) - c.blocks_per_second.With(prometheus.Labels{"device": device}).Set(float64(stats.blocks_per_second)) - c.seconds_per_transaction.With(prometheus.Labels{"device": device}).Set(float64(stats.ms_per_transaction) / 1000) + ch <- prometheus.MustNewConstMetric(c.bytesDesc, prometheus.CounterValue, float64(stats.bytes), device) + ch <- prometheus.MustNewConstMetric(c.transfersDesc, prometheus.CounterValue, float64(stats.transfers), device) + ch <- prometheus.MustNewConstMetric(c.blocksDesc, prometheus.CounterValue, float64(stats.blocks), device) } - c.bytes_total.Collect(ch) - c.transfers_total.Collect(ch) - c.blocks_total.Collect(ch) - c.bytes_per_transfer.Collect(ch) - c.bytes_per_second.Collect(ch) - c.transfers_per_second.Collect(ch) - c.blocks_per_second.Collect(ch) - c.seconds_per_transaction.Collect(ch) - return err }