node_exporter/collector/zfs.go
Christian Schwarz f29f3873ea Add a collector for ZFS, currently focussed on ARC stats.
It is tested on FreeBSD 10.2-RELEASE and Linux (ZFS on Linux 0.6.5.4).

On FreeBSD, Solaris, etc. ZFS metrics are exposed through sysctls.
ZFS on Linux exposes the same metrics through procfs `/proc/spl/...`.

In addition to sysctl metrics, 'computed metrics' are exposed by
the collector, which are based on several sysctl values.
There is some conditional logic involved in computing these metrics
which cannot be easily mapped to PromQL.

Not all 92 ARC sysctls are exposed right now but this can be changed
with one additional LOC each.
2017-01-08 10:23:58 -06:00

110 lines
2.1 KiB
Go

package collector
// +build linux freebsd
// +build !nozfs
import (
"errors"
"strings"
"github.com/prometheus/client_golang/prometheus"
"github.com/prometheus/common/log"
)
type zfsMetricValue int
const zfsErrorValue = zfsMetricValue(-1)
var zfsNotAvailableError = errors.New("ZFS / ZFS statistics are not available")
type zfsSysctl string
type zfsSubsystemName string
const (
arc = zfsSubsystemName("zfsArc")
zpoolSubsystem = zfsSubsystemName("zfsPool")
)
// Metrics
type zfsMetric struct {
subsystem zfsSubsystemName // The Prometheus subsystem name.
name string // The Prometheus name of the metric.
sysctl zfsSysctl // The sysctl of the ZFS metric.
}
type datasetMetric struct {
subsystem zfsSubsystemName
name string
}
// Collector
func init() {
Factories["zfs"] = NewZFSCollector
}
type zfsCollector struct {
zfsMetrics []zfsMetric
}
func NewZFSCollector() (Collector, error) {
return &zfsCollector{}, nil
}
func (c *zfsCollector) Update(ch chan<- prometheus.Metric) (err error) {
err = c.zfsAvailable()
switch {
case err == zfsNotAvailableError:
log.Debug(err)
return nil
case err != nil:
return err
}
// Arcstats
err = c.updateArcstats(ch)
if err != nil {
return err
}
// Pool stats
return c.updatePoolStats(ch)
}
func (s zfsSysctl) metricName() string {
parts := strings.Split(string(s), ".")
return parts[len(parts)-1]
}
func (c *zfsCollector) ConstSysctlMetric(subsystem zfsSubsystemName, sysctl zfsSysctl, value zfsMetricValue) prometheus.Metric {
metricName := sysctl.metricName()
return prometheus.MustNewConstMetric(
prometheus.NewDesc(
prometheus.BuildFQName(Namespace, string(subsystem), metricName),
string(sysctl),
nil,
nil,
),
prometheus.UntypedValue,
float64(value),
)
}
func (c *zfsCollector) ConstZpoolMetric(pool, name string, value float64) prometheus.Metric {
return prometheus.MustNewConstMetric(
prometheus.NewDesc(
prometheus.BuildFQName(Namespace, string(zpoolSubsystem), name),
name,
[]string{"pool"},
nil,
),
prometheus.UntypedValue,
float64(value),
pool,
)
}