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.
This commit is contained in:
parent
dde59014b8
commit
f29f3873ea
10 changed files with 678 additions and 0 deletions
109
collector/zfs.go
Normal file
109
collector/zfs.go
Normal file
|
|
@ -0,0 +1,109 @@
|
|||
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,
|
||||
)
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue