Files
windows_exporter/collector/tcp.go
Michael Allen 380eff24c9 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>
2020-10-07 22:25:58 -07:00

174 lines
4.8 KiB
Go

// +build windows
package collector
import (
"errors"
"github.com/prometheus/client_golang/prometheus"
"github.com/prometheus/common/log"
)
func init() {
registerCollector("tcp", NewTCPCollector, "TCPv4")
}
// A TCPCollector is a Prometheus collector for WMI Win32_PerfRawData_Tcpip_TCPv4 metrics
type TCPCollector struct {
ConnectionFailures *prometheus.Desc
ConnectionsActive *prometheus.Desc
ConnectionsEstablished *prometheus.Desc
ConnectionsPassive *prometheus.Desc
ConnectionsReset *prometheus.Desc
SegmentsTotal *prometheus.Desc
SegmentsReceivedTotal *prometheus.Desc
SegmentsRetransmittedTotal *prometheus.Desc
SegmentsSentTotal *prometheus.Desc
}
// NewTCPCollector ...
func NewTCPCollector() (Collector, error) {
const subsystem = "tcp"
return &TCPCollector{
ConnectionFailures: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "connection_failures"),
"(TCP.ConnectionFailures)",
nil,
nil,
),
ConnectionsActive: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "connections_active"),
"(TCP.ConnectionsActive)",
nil,
nil,
),
ConnectionsEstablished: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "connections_established"),
"(TCP.ConnectionsEstablished)",
nil,
nil,
),
ConnectionsPassive: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "connections_passive"),
"(TCP.ConnectionsPassive)",
nil,
nil,
),
ConnectionsReset: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "connections_reset"),
"(TCP.ConnectionsReset)",
nil,
nil,
),
SegmentsTotal: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "segments_total"),
"(TCP.SegmentsTotal)",
nil,
nil,
),
SegmentsReceivedTotal: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "segments_received_total"),
"(TCP.SegmentsReceivedTotal)",
nil,
nil,
),
SegmentsRetransmittedTotal: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "segments_retransmitted_total"),
"(TCP.SegmentsRetransmittedTotal)",
nil,
nil,
),
SegmentsSentTotal: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "segments_sent_total"),
"(TCP.SegmentsSentTotal)",
nil,
nil,
),
}, nil
}
// 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(ctx, ch); err != nil {
log.Error("failed collecting tcp metrics:", desc, err)
return err
}
return nil
}
// Win32_PerfRawData_Tcpip_TCPv4 docs
// - https://msdn.microsoft.com/en-us/library/aa394341(v=vs.85).aspx
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(ctx *ScrapeContext, ch chan<- prometheus.Metric) (*prometheus.Desc, error) {
var dst []tcp
if err := unmarshalObject(ctx.perfObjects["TCPv4"], &dst); err != nil {
return nil, err
}
if len(dst) == 0 {
return nil, errors.New("TCPv4 performance object not available")
}
// Counters
ch <- prometheus.MustNewConstMetric(
c.ConnectionFailures,
prometheus.CounterValue,
dst[0].ConnectionFailures,
)
ch <- prometheus.MustNewConstMetric(
c.ConnectionsActive,
prometheus.CounterValue,
dst[0].ConnectionsActive,
)
ch <- prometheus.MustNewConstMetric(
c.ConnectionsEstablished,
prometheus.GaugeValue,
dst[0].ConnectionsEstablished,
)
ch <- prometheus.MustNewConstMetric(
c.ConnectionsPassive,
prometheus.CounterValue,
dst[0].ConnectionsPassive,
)
ch <- prometheus.MustNewConstMetric(
c.ConnectionsReset,
prometheus.CounterValue,
dst[0].ConnectionsReset,
)
ch <- prometheus.MustNewConstMetric(
c.SegmentsTotal,
prometheus.CounterValue,
dst[0].SegmentsPersec,
)
ch <- prometheus.MustNewConstMetric(
c.SegmentsReceivedTotal,
prometheus.CounterValue,
dst[0].SegmentsReceivedPersec,
)
ch <- prometheus.MustNewConstMetric(
c.SegmentsRetransmittedTotal,
prometheus.CounterValue,
dst[0].SegmentsRetransmittedPersec,
)
ch <- prometheus.MustNewConstMetric(
c.SegmentsSentTotal,
prometheus.CounterValue,
dst[0].SegmentsSentPersec,
)
return nil, nil
}