Convert the tcp collector to use perflib instead of WMI

Using perflib is substantially faster and more reliable than using WMI to
retrieve Windows performance counter data.

Signed-off-by: Michael Allen <MAllen@laserfiche.com>
This commit is contained in:
Michael Allen 2020-10-07 22:25:58 -07:00
parent 922c08b85b
commit 380eff24c9

View File

@ -4,13 +4,13 @@ package collector
import (
"errors"
"github.com/StackExchange/wmi"
"github.com/prometheus/client_golang/prometheus"
"github.com/prometheus/common/log"
)
func init() {
registerCollector("tcp", NewTCPCollector)
registerCollector("tcp", NewTCPCollector, "TCPv4")
}
// A TCPCollector is a Prometheus collector for WMI Win32_PerfRawData_Tcpip_TCPv4 metrics
@ -91,7 +91,7 @@ func NewTCPCollector() (Collector, error) {
// Collect sends the metric values for each metric
// to the provided prometheus Metric channel.
func (c *TCPCollector) Collect(ctx *ScrapeContext, ch chan<- prometheus.Metric) error {
if desc, err := c.collect(ch); err != nil {
if desc, err := c.collect(ctx, ch); err != nil {
log.Error("failed collecting tcp metrics:", desc, err)
return err
}
@ -100,74 +100,73 @@ func (c *TCPCollector) Collect(ctx *ScrapeContext, ch chan<- prometheus.Metric)
// Win32_PerfRawData_Tcpip_TCPv4 docs
// - https://msdn.microsoft.com/en-us/library/aa394341(v=vs.85).aspx
type Win32_PerfRawData_Tcpip_TCPv4 struct {
ConnectionFailures uint64
ConnectionsActive uint64
ConnectionsEstablished uint64
ConnectionsPassive uint64
ConnectionsReset uint64
SegmentsPersec uint64
SegmentsReceivedPersec uint64
SegmentsRetransmittedPersec uint64
SegmentsSentPersec uint64
type tcp struct {
ConnectionFailures float64 `perflib:"Connection Failures"`
ConnectionsActive float64 `perflib:"Connections Active"`
ConnectionsEstablished float64 `perflib:"Connections Established"`
ConnectionsPassive float64 `perflib:"Connections Passive"`
ConnectionsReset float64 `perflib:"Connections Reset"`
SegmentsPersec float64 `perflib:"Segments/sec"`
SegmentsReceivedPersec float64 `perflib:"Segments Received/sec"`
SegmentsRetransmittedPersec float64 `perflib:"Segments Retransmitted/sec"`
SegmentsSentPersec float64 `perflib:"Segments Sent/sec"`
}
func (c *TCPCollector) collect(ch chan<- prometheus.Metric) (*prometheus.Desc, error) {
var dst []Win32_PerfRawData_Tcpip_TCPv4
func (c *TCPCollector) collect(ctx *ScrapeContext, ch chan<- prometheus.Metric) (*prometheus.Desc, error) {
var dst []tcp
q := queryAll(&dst)
if err := wmi.Query(q, &dst); err != nil {
if err := unmarshalObject(ctx.perfObjects["TCPv4"], &dst); err != nil {
return nil, err
}
if len(dst) == 0 {
return nil, errors.New("WMI query returned empty result set")
return nil, errors.New("TCPv4 performance object not available")
}
// Counters
ch <- prometheus.MustNewConstMetric(
c.ConnectionFailures,
prometheus.CounterValue,
float64(dst[0].ConnectionFailures),
dst[0].ConnectionFailures,
)
ch <- prometheus.MustNewConstMetric(
c.ConnectionsActive,
prometheus.CounterValue,
float64(dst[0].ConnectionsActive),
dst[0].ConnectionsActive,
)
ch <- prometheus.MustNewConstMetric(
c.ConnectionsEstablished,
prometheus.GaugeValue,
float64(dst[0].ConnectionsEstablished),
dst[0].ConnectionsEstablished,
)
ch <- prometheus.MustNewConstMetric(
c.ConnectionsPassive,
prometheus.CounterValue,
float64(dst[0].ConnectionsPassive),
dst[0].ConnectionsPassive,
)
ch <- prometheus.MustNewConstMetric(
c.ConnectionsReset,
prometheus.CounterValue,
float64(dst[0].ConnectionsReset),
dst[0].ConnectionsReset,
)
ch <- prometheus.MustNewConstMetric(
c.SegmentsTotal,
prometheus.CounterValue,
float64(dst[0].SegmentsPersec),
dst[0].SegmentsPersec,
)
ch <- prometheus.MustNewConstMetric(
c.SegmentsReceivedTotal,
prometheus.CounterValue,
float64(dst[0].SegmentsReceivedPersec),
dst[0].SegmentsReceivedPersec,
)
ch <- prometheus.MustNewConstMetric(
c.SegmentsRetransmittedTotal,
prometheus.CounterValue,
float64(dst[0].SegmentsRetransmittedPersec),
dst[0].SegmentsRetransmittedPersec,
)
ch <- prometheus.MustNewConstMetric(
c.SegmentsSentTotal,
prometheus.CounterValue,
float64(dst[0].SegmentsSentPersec),
dst[0].SegmentsSentPersec,
)
return nil, nil