Add flag to aggr ipvs metrics to avoid high cardinality metrics (#1709)
Fixes #1708 Signed-off-by: Wing924 <weihe924stephen@gmail.com>
This commit is contained in:
parent
b7cb72adeb
commit
0253277121
5 changed files with 345 additions and 81 deletions
|
|
@ -18,22 +18,53 @@ package collector
|
|||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"sort"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/go-kit/kit/log"
|
||||
"github.com/go-kit/kit/log/level"
|
||||
"github.com/prometheus/client_golang/prometheus"
|
||||
"github.com/prometheus/procfs"
|
||||
kingpin "gopkg.in/alecthomas/kingpin.v2"
|
||||
)
|
||||
|
||||
type ipvsCollector struct {
|
||||
Collector
|
||||
fs procfs.FS
|
||||
backendLabels []string
|
||||
backendConnectionsActive, backendConnectionsInact, backendWeight typedDesc
|
||||
connections, incomingPackets, outgoingPackets, incomingBytes, outgoingBytes typedDesc
|
||||
logger log.Logger
|
||||
}
|
||||
|
||||
type ipvsBackendStatus struct {
|
||||
ActiveConn uint64
|
||||
InactConn uint64
|
||||
Weight uint64
|
||||
}
|
||||
|
||||
const (
|
||||
ipvsLabelLocalAddress = "local_address"
|
||||
ipvsLabelLocalPort = "local_port"
|
||||
ipvsLabelRemoteAddress = "remote_address"
|
||||
ipvsLabelRemotePort = "remote_port"
|
||||
ipvsLabelProto = "proto"
|
||||
ipvsLabelLocalMark = "local_mark"
|
||||
)
|
||||
|
||||
var (
|
||||
fullIpvsBackendLabels = []string{
|
||||
ipvsLabelLocalAddress,
|
||||
ipvsLabelLocalPort,
|
||||
ipvsLabelRemoteAddress,
|
||||
ipvsLabelRemotePort,
|
||||
ipvsLabelProto,
|
||||
ipvsLabelLocalMark,
|
||||
}
|
||||
ipvsLabels = kingpin.Flag("collector.ipvs.backend-labels", "Comma separated list for IPVS backend stats labels.").Default(strings.Join(fullIpvsBackendLabels, ",")).String()
|
||||
)
|
||||
|
||||
func init() {
|
||||
registerCollector("ipvs", defaultEnabled, NewIPVSCollector)
|
||||
}
|
||||
|
|
@ -46,19 +77,15 @@ func NewIPVSCollector(logger log.Logger) (Collector, error) {
|
|||
|
||||
func newIPVSCollector(logger log.Logger) (*ipvsCollector, error) {
|
||||
var (
|
||||
ipvsBackendLabelNames = []string{
|
||||
"local_address",
|
||||
"local_port",
|
||||
"remote_address",
|
||||
"remote_port",
|
||||
"proto",
|
||||
"local_mark",
|
||||
}
|
||||
c ipvsCollector
|
||||
err error
|
||||
subsystem = "ipvs"
|
||||
)
|
||||
|
||||
if c.backendLabels, err = c.parseIpvsLabels(*ipvsLabels); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
c.logger = logger
|
||||
c.fs, err = procfs.NewFS(*procPath)
|
||||
if err != nil {
|
||||
|
|
@ -93,17 +120,17 @@ func newIPVSCollector(logger log.Logger) (*ipvsCollector, error) {
|
|||
c.backendConnectionsActive = typedDesc{prometheus.NewDesc(
|
||||
prometheus.BuildFQName(namespace, subsystem, "backend_connections_active"),
|
||||
"The current active connections by local and remote address.",
|
||||
ipvsBackendLabelNames, nil,
|
||||
c.backendLabels, nil,
|
||||
), prometheus.GaugeValue}
|
||||
c.backendConnectionsInact = typedDesc{prometheus.NewDesc(
|
||||
prometheus.BuildFQName(namespace, subsystem, "backend_connections_inactive"),
|
||||
"The current inactive connections by local and remote address.",
|
||||
ipvsBackendLabelNames, nil,
|
||||
c.backendLabels, nil,
|
||||
), prometheus.GaugeValue}
|
||||
c.backendWeight = typedDesc{prometheus.NewDesc(
|
||||
prometheus.BuildFQName(namespace, subsystem, "backend_weight"),
|
||||
"The current backend weight by local and remote address.",
|
||||
ipvsBackendLabelNames, nil,
|
||||
c.backendLabels, nil,
|
||||
), prometheus.GaugeValue}
|
||||
|
||||
return &c, nil
|
||||
|
|
@ -130,22 +157,74 @@ func (c *ipvsCollector) Update(ch chan<- prometheus.Metric) error {
|
|||
return fmt.Errorf("could not get backend status: %s", err)
|
||||
}
|
||||
|
||||
sums := map[string]ipvsBackendStatus{}
|
||||
labelValues := map[string][]string{}
|
||||
for _, backend := range backendStats {
|
||||
localAddress := ""
|
||||
if backend.LocalAddress.String() != "<nil>" {
|
||||
localAddress = backend.LocalAddress.String()
|
||||
}
|
||||
labelValues := []string{
|
||||
localAddress,
|
||||
strconv.FormatUint(uint64(backend.LocalPort), 10),
|
||||
backend.RemoteAddress.String(),
|
||||
strconv.FormatUint(uint64(backend.RemotePort), 10),
|
||||
backend.Proto,
|
||||
backend.LocalMark,
|
||||
kv := make([]string, len(c.backendLabels))
|
||||
for i, label := range c.backendLabels {
|
||||
var labelValue string
|
||||
switch label {
|
||||
case ipvsLabelLocalAddress:
|
||||
labelValue = localAddress
|
||||
case ipvsLabelLocalPort:
|
||||
labelValue = strconv.FormatUint(uint64(backend.LocalPort), 10)
|
||||
case ipvsLabelRemoteAddress:
|
||||
labelValue = backend.RemoteAddress.String()
|
||||
case ipvsLabelRemotePort:
|
||||
labelValue = strconv.FormatUint(uint64(backend.RemotePort), 10)
|
||||
case ipvsLabelProto:
|
||||
labelValue = backend.Proto
|
||||
case ipvsLabelLocalMark:
|
||||
labelValue = backend.LocalMark
|
||||
}
|
||||
kv[i] = labelValue
|
||||
}
|
||||
ch <- c.backendConnectionsActive.mustNewConstMetric(float64(backend.ActiveConn), labelValues...)
|
||||
ch <- c.backendConnectionsInact.mustNewConstMetric(float64(backend.InactConn), labelValues...)
|
||||
ch <- c.backendWeight.mustNewConstMetric(float64(backend.Weight), labelValues...)
|
||||
key := strings.Join(kv, "-")
|
||||
status := sums[key]
|
||||
status.ActiveConn += backend.ActiveConn
|
||||
status.InactConn += backend.InactConn
|
||||
status.Weight += backend.Weight
|
||||
sums[key] = status
|
||||
labelValues[key] = kv
|
||||
}
|
||||
for key, status := range sums {
|
||||
kv := labelValues[key]
|
||||
ch <- c.backendConnectionsActive.mustNewConstMetric(float64(status.ActiveConn), kv...)
|
||||
ch <- c.backendConnectionsInact.mustNewConstMetric(float64(status.InactConn), kv...)
|
||||
ch <- c.backendWeight.mustNewConstMetric(float64(status.Weight), kv...)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *ipvsCollector) parseIpvsLabels(labelString string) ([]string, error) {
|
||||
labels := strings.Split(labelString, ",")
|
||||
labelSet := make(map[string]bool, len(labels))
|
||||
results := make([]string, 0, len(labels))
|
||||
for _, label := range labels {
|
||||
if label != "" {
|
||||
labelSet[label] = true
|
||||
}
|
||||
}
|
||||
|
||||
for _, label := range fullIpvsBackendLabels {
|
||||
if labelSet[label] {
|
||||
results = append(results, label)
|
||||
}
|
||||
delete(labelSet, label)
|
||||
}
|
||||
|
||||
if len(labelSet) > 0 {
|
||||
keys := make([]string, 0, len(labelSet))
|
||||
for label := range labelSet {
|
||||
keys = append(keys, label)
|
||||
}
|
||||
sort.Strings(keys)
|
||||
return nil, fmt.Errorf("unknown IPVS backend labels: %q", strings.Join(keys, ", "))
|
||||
}
|
||||
|
||||
return results, nil
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue