Use include/exclude flags for ethtool filtering (#2165)
Use the same flag pattern as netdev to make filtering methods the same. * Move SanitizeMetricName to helper.go Signed-off-by: Ben Kochie <superq@gmail.com>pull/2139/head^2
parent
68a6c78c0d
commit
f61be48d94
|
@ -39,11 +39,11 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
ethtoolIgnoredDevices = kingpin.Flag("collector.ethtool.ignored-devices", "Regexp of net devices to ignore for ethtool collector.").Default("^$").String()
|
ethtoolDeviceInclude = kingpin.Flag("collector.ethtool.device-include", "Regexp of ethtool devices to include (mutually exclusive to device-exclude).").String()
|
||||||
|
ethtoolDeviceExclude = kingpin.Flag("collector.ethtool.device-exclude", "Regexp of ethtool devices to exclude (mutually exclusive to device-include).").String()
|
||||||
ethtoolIncludedMetrics = kingpin.Flag("collector.ethtool.metrics-include", "Regexp of ethtool stats to include.").Default(".*").String()
|
ethtoolIncludedMetrics = kingpin.Flag("collector.ethtool.metrics-include", "Regexp of ethtool stats to include.").Default(".*").String()
|
||||||
metricNameRegex = regexp.MustCompile(`_*[^0-9A-Za-z_]+_*`)
|
ethtoolReceivedRegex = regexp.MustCompile(`(^|_)rx(_|$)`)
|
||||||
receivedRegex = regexp.MustCompile(`(^|_)rx(_|$)`)
|
ethtoolTransmitRegex = regexp.MustCompile(`(^|_)tx(_|$)`)
|
||||||
transmittedRegex = regexp.MustCompile(`(^|_)tx(_|$)`)
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type Ethtool interface {
|
type Ethtool interface {
|
||||||
|
@ -64,13 +64,13 @@ func (e *ethtoolLibrary) Stats(intf string) (map[string]uint64, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
type ethtoolCollector struct {
|
type ethtoolCollector struct {
|
||||||
fs sysfs.FS
|
fs sysfs.FS
|
||||||
entries map[string]*prometheus.Desc
|
entries map[string]*prometheus.Desc
|
||||||
ethtool Ethtool
|
ethtool Ethtool
|
||||||
ignoredDevicesPattern *regexp.Regexp
|
deviceFilter netDevFilter
|
||||||
infoDesc *prometheus.Desc
|
infoDesc *prometheus.Desc
|
||||||
metricsPattern *regexp.Regexp
|
metricsPattern *regexp.Regexp
|
||||||
logger log.Logger
|
logger log.Logger
|
||||||
}
|
}
|
||||||
|
|
||||||
// makeEthtoolCollector is the internal constructor for EthtoolCollector.
|
// makeEthtoolCollector is the internal constructor for EthtoolCollector.
|
||||||
|
@ -89,11 +89,11 @@ func makeEthtoolCollector(logger log.Logger) (*ethtoolCollector, error) {
|
||||||
|
|
||||||
// Pre-populate some common ethtool metrics.
|
// Pre-populate some common ethtool metrics.
|
||||||
return ðtoolCollector{
|
return ðtoolCollector{
|
||||||
fs: fs,
|
fs: fs,
|
||||||
ethtool: ðtoolLibrary{e},
|
ethtool: ðtoolLibrary{e},
|
||||||
ignoredDevicesPattern: regexp.MustCompile(*ethtoolIgnoredDevices),
|
deviceFilter: newNetDevFilter(*ethtoolDeviceExclude, *ethtoolDeviceInclude),
|
||||||
metricsPattern: regexp.MustCompile(*ethtoolIncludedMetrics),
|
metricsPattern: regexp.MustCompile(*ethtoolIncludedMetrics),
|
||||||
logger: logger,
|
logger: logger,
|
||||||
entries: map[string]*prometheus.Desc{
|
entries: map[string]*prometheus.Desc{
|
||||||
"rx_bytes": prometheus.NewDesc(
|
"rx_bytes": prometheus.NewDesc(
|
||||||
prometheus.BuildFQName(namespace, "ethtool", "received_bytes_total"),
|
prometheus.BuildFQName(namespace, "ethtool", "received_bytes_total"),
|
||||||
|
@ -143,26 +143,11 @@ func init() {
|
||||||
registerCollector("ethtool", defaultDisabled, NewEthtoolCollector)
|
registerCollector("ethtool", defaultDisabled, NewEthtoolCollector)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Sanitize the given metric name by replacing invalid characters by underscores.
|
|
||||||
//
|
|
||||||
// OpenMetrics and the Prometheus exposition format require the metric name
|
|
||||||
// to consist only of alphanumericals and "_", ":" and they must not start
|
|
||||||
// with digits. Since colons in MetricFamily are reserved to signal that the
|
|
||||||
// MetricFamily is the result of a calculation or aggregation of a general
|
|
||||||
// purpose monitoring system, colons will be replaced as well.
|
|
||||||
//
|
|
||||||
// Note: If not subsequently prepending a namespace and/or subsystem (e.g.,
|
|
||||||
// with prometheus.BuildFQName), the caller must ensure that the supplied
|
|
||||||
// metricName does not begin with a digit.
|
|
||||||
func SanitizeMetricName(metricName string) string {
|
|
||||||
return metricNameRegex.ReplaceAllString(metricName, "_")
|
|
||||||
}
|
|
||||||
|
|
||||||
// Generate the fully-qualified metric name for the ethool metric.
|
// Generate the fully-qualified metric name for the ethool metric.
|
||||||
func buildEthtoolFQName(metric string) string {
|
func buildEthtoolFQName(metric string) string {
|
||||||
metricName := strings.TrimLeft(strings.ToLower(SanitizeMetricName(metric)), "_")
|
metricName := strings.TrimLeft(strings.ToLower(SanitizeMetricName(metric)), "_")
|
||||||
metricName = receivedRegex.ReplaceAllString(metricName, "${1}received${2}")
|
metricName = ethtoolReceivedRegex.ReplaceAllString(metricName, "${1}received${2}")
|
||||||
metricName = transmittedRegex.ReplaceAllString(metricName, "${1}transmitted${2}")
|
metricName = ethtoolTransmitRegex.ReplaceAllString(metricName, "${1}transmitted${2}")
|
||||||
return prometheus.BuildFQName(namespace, "ethtool", metricName)
|
return prometheus.BuildFQName(namespace, "ethtool", metricName)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -189,7 +174,7 @@ func (c *ethtoolCollector) Update(ch chan<- prometheus.Metric) error {
|
||||||
var stats map[string]uint64
|
var stats map[string]uint64
|
||||||
var err error
|
var err error
|
||||||
|
|
||||||
if c.ignoredDevicesPattern.MatchString(device) {
|
if c.deviceFilter.ignored(device) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -121,24 +121,6 @@ func NewEthtoolTestCollector(logger log.Logger) (Collector, error) {
|
||||||
return collector, nil
|
return collector, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestSanitizeMetricName(t *testing.T) {
|
|
||||||
testcases := map[string]string{
|
|
||||||
"": "",
|
|
||||||
"rx_errors": "rx_errors",
|
|
||||||
"Queue[0] AllocFails": "Queue_0_AllocFails",
|
|
||||||
"Tx LPI entry count": "Tx_LPI_entry_count",
|
|
||||||
"port.VF_admin_queue_requests": "port_VF_admin_queue_requests",
|
|
||||||
"[3]: tx_bytes": "_3_tx_bytes",
|
|
||||||
}
|
|
||||||
|
|
||||||
for metricName, expected := range testcases {
|
|
||||||
got := SanitizeMetricName(metricName)
|
|
||||||
if expected != got {
|
|
||||||
t.Errorf("Expected '%s' but got '%s'", expected, got)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestBuildEthtoolFQName(t *testing.T) {
|
func TestBuildEthtoolFQName(t *testing.T) {
|
||||||
testcases := map[string]string{
|
testcases := map[string]string{
|
||||||
"rx_errors": "node_ethtool_received_errors",
|
"rx_errors": "node_ethtool_received_errors",
|
||||||
|
@ -174,7 +156,6 @@ func TestEthtoolCollector(t *testing.T) {
|
||||||
prometheus.NewDesc("node_ethtool_transmitted_packets_total", "Network interface packets sent", []string{"device"}, nil).String(),
|
prometheus.NewDesc("node_ethtool_transmitted_packets_total", "Network interface packets sent", []string{"device"}, nil).String(),
|
||||||
}
|
}
|
||||||
|
|
||||||
*ethtoolIgnoredDevices = "^$"
|
|
||||||
*sysPath = "fixtures/sys"
|
*sysPath = "fixtures/sys"
|
||||||
|
|
||||||
collector, err := NewEthtoolTestCollector(log.NewNopLogger())
|
collector, err := NewEthtoolTestCollector(log.NewNopLogger())
|
||||||
|
|
|
@ -16,6 +16,7 @@ package collector
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
|
"regexp"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
)
|
)
|
||||||
|
@ -44,3 +45,20 @@ func bytesToString(byteArray []byte) string {
|
||||||
}
|
}
|
||||||
return string(byteArray[:n])
|
return string(byteArray[:n])
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var metricNameRegex = regexp.MustCompile(`_*[^0-9A-Za-z_]+_*`)
|
||||||
|
|
||||||
|
// Sanitize the given metric name by replacing invalid characters by underscores.
|
||||||
|
//
|
||||||
|
// OpenMetrics and the Prometheus exposition format require the metric name
|
||||||
|
// to consist only of alphanumericals and "_", ":" and they must not start
|
||||||
|
// with digits. Since colons in MetricFamily are reserved to signal that the
|
||||||
|
// MetricFamily is the result of a calculation or aggregation of a general
|
||||||
|
// purpose monitoring system, colons will be replaced as well.
|
||||||
|
//
|
||||||
|
// Note: If not subsequently prepending a namespace and/or subsystem (e.g.,
|
||||||
|
// with prometheus.BuildFQName), the caller must ensure that the supplied
|
||||||
|
// metricName does not begin with a digit.
|
||||||
|
func SanitizeMetricName(metricName string) string {
|
||||||
|
return metricNameRegex.ReplaceAllString(metricName, "_")
|
||||||
|
}
|
||||||
|
|
|
@ -61,3 +61,21 @@ func TestBytesToString(t *testing.T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestSanitizeMetricName(t *testing.T) {
|
||||||
|
testcases := map[string]string{
|
||||||
|
"": "",
|
||||||
|
"rx_errors": "rx_errors",
|
||||||
|
"Queue[0] AllocFails": "Queue_0_AllocFails",
|
||||||
|
"Tx LPI entry count": "Tx_LPI_entry_count",
|
||||||
|
"port.VF_admin_queue_requests": "port_VF_admin_queue_requests",
|
||||||
|
"[3]: tx_bytes": "_3_tx_bytes",
|
||||||
|
}
|
||||||
|
|
||||||
|
for metricName, expected := range testcases {
|
||||||
|
got := SanitizeMetricName(metricName)
|
||||||
|
if expected != got {
|
||||||
|
t.Errorf("Expected '%s' but got '%s'", expected, got)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue