Compare commits

...

11 Commits

Author SHA1 Message Date
tunaman
f3072bb4f3 Add extra HyperV VM classes (#202)
add two extra new HyperV VM classes
2018-05-17 23:46:13 -07:00
Calle Pettersson
17072bf257 Merge pull request #198 from martinlindhe/service-status
Add status metric for service-collector
2018-05-17 11:05:07 -07:00
Calle Pettersson
d3d8537201 Merge pull request #200 from martinlindhe/textfile-carriage-return
Strip carriage-returns from textfile input
2018-05-16 05:18:54 -07:00
Calle Pettersson
2951a9ef80 Strip carriage-returns from textfile input 2018-05-15 20:58:58 +02:00
Calle Pettersson
3141fc3ed3 Add status metric for service-collector 2018-05-12 09:49:29 +02:00
Calle Pettersson
a0333ee256 Merge pull request #195 from martinlindhe/totals-as-gauges-help-string
Fix wrong metric types in system collector, improve help-strings
2018-04-30 09:29:00 +02:00
Calle Pettersson
c9fc76de4c Merge pull request #194 from martinlindhe/exporter-start-time
Add process_start_time_seconds for the exporter itself
2018-04-30 09:28:43 +02:00
Calle Pettersson
3752a547d5 Merge pull request #193 from martinlindhe/hyperv-network-labels
Fix missing label on HyperVLegacyNetworkAdapter
2018-04-30 09:28:30 +02:00
Calle Pettersson
0ab6c191be Fix wrong metric types in system collector, improve help-strings 2018-04-29 17:14:53 +02:00
Calle Pettersson
467e83722a Add process_start_time_seconds for the exporter itself 2018-04-29 16:53:34 +02:00
Calle Pettersson
7fe8ca8554 Fix missing label on HyperVLegacyNetworkAdapter 2018-04-29 16:09:18 +02:00
6 changed files with 354 additions and 15 deletions

View File

@@ -92,6 +92,22 @@ type HyperVCollector struct {
AdapterFramesDropped *prometheus.Desc AdapterFramesDropped *prometheus.Desc
AdapterFramesReceived *prometheus.Desc AdapterFramesReceived *prometheus.Desc
AdapterFramesSent *prometheus.Desc AdapterFramesSent *prometheus.Desc
// Win32_PerfRawData_Counters_HyperVVirtualStorageDevice
VMStorageErrorCount *prometheus.Desc
VMStorageQueueLength *prometheus.Desc
VMStorageReadBytes *prometheus.Desc
VMStorageReadOperations *prometheus.Desc
VMStorageWriteBytes *prometheus.Desc
VMStorageWriteOperations *prometheus.Desc
// Win32_PerfRawData_NvspNicStats_HyperVVirtualNetworkAdapter
VMNetworkBytesReceived *prometheus.Desc
VMNetworkBytesSent *prometheus.Desc
VMNetworkDroppedPacketsIncoming *prometheus.Desc
VMNetworkDroppedPacketsOutgoing *prometheus.Desc
VMNetworkPacketsReceived *prometheus.Desc
VMNetworkPacketsSent *prometheus.Desc
} }
// NewHyperVCollector ... // NewHyperVCollector ...
@@ -463,37 +479,115 @@ func NewHyperVCollector() (Collector, error) {
AdapterBytesDropped: prometheus.NewDesc( AdapterBytesDropped: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, buildSubsystemName("ethernet"), "bytes_dropped"), prometheus.BuildFQName(Namespace, buildSubsystemName("ethernet"), "bytes_dropped"),
"Bytes Dropped is the number of bytes dropped on the network adapter", "Bytes Dropped is the number of bytes dropped on the network adapter",
nil, []string{"adapter"},
nil, nil,
), ),
AdapterBytesReceived: prometheus.NewDesc( AdapterBytesReceived: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, buildSubsystemName("ethernet"), "bytes_received"), prometheus.BuildFQName(Namespace, buildSubsystemName("ethernet"), "bytes_received"),
"Bytes received is the number of bytes received on the network adapter", "Bytes received is the number of bytes received on the network adapter",
nil, []string{"adapter"},
nil, nil,
), ),
AdapterBytesSent: prometheus.NewDesc( AdapterBytesSent: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, buildSubsystemName("ethernet"), "bytes_sent"), prometheus.BuildFQName(Namespace, buildSubsystemName("ethernet"), "bytes_sent"),
"Bytes sent is the number of bytes sent over the network adapter", "Bytes sent is the number of bytes sent over the network adapter",
nil, []string{"adapter"},
nil, nil,
), ),
AdapterFramesDropped: prometheus.NewDesc( AdapterFramesDropped: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, buildSubsystemName("ethernet"), "frames_dropped"), prometheus.BuildFQName(Namespace, buildSubsystemName("ethernet"), "frames_dropped"),
"Frames Dropped is the number of frames dropped on the network adapter", "Frames Dropped is the number of frames dropped on the network adapter",
nil, []string{"adapter"},
nil, nil,
), ),
AdapterFramesReceived: prometheus.NewDesc( AdapterFramesReceived: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, buildSubsystemName("ethernet"), "frames_received"), prometheus.BuildFQName(Namespace, buildSubsystemName("ethernet"), "frames_received"),
"Frames received is the number of frames received on the network adapter", "Frames received is the number of frames received on the network adapter",
nil, []string{"adapter"},
nil, nil,
), ),
AdapterFramesSent: prometheus.NewDesc( AdapterFramesSent: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, buildSubsystemName("ethernet"), "frames_sent"), prometheus.BuildFQName(Namespace, buildSubsystemName("ethernet"), "frames_sent"),
"Frames sent is the number of frames sent over the network adapter", "Frames sent is the number of frames sent over the network adapter",
[]string{"adapter"},
nil, nil,
),
//
VMStorageErrorCount: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, buildSubsystemName("vm_device"), "error_count"),
"This counter represents the total number of errors that have occurred on this virtual device",
[]string{"vm_device"},
nil,
),
VMStorageQueueLength: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, buildSubsystemName("vm_device"), "queue_length"),
"This counter represents the current queue length on this virtual device",
[]string{"vm_device"},
nil,
),
VMStorageReadBytes: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, buildSubsystemName("vm_device"), "bytes_read"),
"This counter represents the total number of bytes that have been read per second on this virtual device",
[]string{"vm_device"},
nil,
),
VMStorageReadOperations: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, buildSubsystemName("vm_device"), "operations_read"),
"This counter represents the number of read operations that have occurred per second on this virtual device",
[]string{"vm_device"},
nil,
),
VMStorageWriteBytes: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, buildSubsystemName("vm_device"), "bytes_written"),
"This counter represents the total number of bytes that have been written per second on this virtual device",
[]string{"vm_device"},
nil,
),
VMStorageWriteOperations: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, buildSubsystemName("vm_device"), "operations_written"),
"This counter represents the number of write operations that have occurred per second on this virtual device",
[]string{"vm_device"},
nil,
),
//
VMNetworkBytesReceived: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, buildSubsystemName("vm_interface"), "bytes_received"),
"This counter represents the total number of bytes received per second by the network adapter",
[]string{"vm_interface"},
nil,
),
VMNetworkBytesSent: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, buildSubsystemName("vm_interface"), "bytes_sent"),
"This counter represents the total number of bytes sent per second by the network adapter",
[]string{"vm_interface"},
nil,
),
VMNetworkDroppedPacketsIncoming: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, buildSubsystemName("vm_interface"), "packets_incoming_dropped"),
"This counter represents the total number of dropped packets per second in the incoming direction of the network adapter",
[]string{"vm_interface"},
nil,
),
VMNetworkDroppedPacketsOutgoing: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, buildSubsystemName("vm_interface"), "packets_outgoing_dropped"),
"This counter represents the total number of dropped packets per second in the outgoing direction of the network adapter",
[]string{"vm_interface"},
nil,
),
VMNetworkPacketsReceived: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, buildSubsystemName("vm_interface"), "packets_received"),
"This counter represents the total number of packets received per second by the network adapter",
[]string{"vm_interface"},
nil,
),
VMNetworkPacketsSent: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, buildSubsystemName("vm_interface"), "packets_sent"),
"This counter represents the total number of packets sent per second by the network adapter",
[]string{"vm_interface"},
nil, nil,
), ),
}, nil }, nil
@@ -541,6 +635,17 @@ func (c *HyperVCollector) Collect(ch chan<- prometheus.Metric) error {
log.Error("failed collecting hyperV ethernet metrics:", desc, err) log.Error("failed collecting hyperV ethernet metrics:", desc, err)
return err return err
} }
if desc, err := c.collectVmStorage(ch); err != nil {
log.Error("failed collecting hyperV virtual storage metrics:", desc, err)
return err
}
if desc, err := c.collectVmNetwork(ch); err != nil {
log.Error("failed collecting hyperV virtual network metrics:", desc, err)
return err
}
return nil return nil
} }
@@ -1168,3 +1273,139 @@ func (c *HyperVCollector) collectVmEthernet(ch chan<- prometheus.Metric) (*prome
return nil, nil return nil, nil
} }
// Win32_PerfRawData_Counters_HyperVVirtualStorageDevice ...
type Win32_PerfRawData_Counters_HyperVVirtualStorageDevice struct {
Name string
ErrorCount uint64
QueueLength uint32
ReadBytesPersec uint64
ReadOperationsPerSec uint64
WriteBytesPersec uint64
WriteOperationsPerSec uint64
}
func (c *HyperVCollector) collectVmStorage(ch chan<- prometheus.Metric) (*prometheus.Desc, error) {
var dst []Win32_PerfRawData_Counters_HyperVVirtualStorageDevice
if err := wmi.Query(wmi.CreateQuery(&dst, ""), &dst); err != nil {
return nil, err
}
for _, obj := range dst {
if strings.Contains(obj.Name, "_Total") {
continue
}
ch <- prometheus.MustNewConstMetric(
c.VMStorageErrorCount,
prometheus.CounterValue,
float64(obj.ErrorCount),
obj.Name,
)
ch <- prometheus.MustNewConstMetric(
c.VMStorageQueueLength,
prometheus.CounterValue,
float64(obj.QueueLength),
obj.Name,
)
ch <- prometheus.MustNewConstMetric(
c.VMStorageReadBytes,
prometheus.CounterValue,
float64(obj.ReadBytesPersec),
obj.Name,
)
ch <- prometheus.MustNewConstMetric(
c.VMStorageReadOperations,
prometheus.CounterValue,
float64(obj.ReadOperationsPerSec),
obj.Name,
)
ch <- prometheus.MustNewConstMetric(
c.VMStorageWriteBytes,
prometheus.CounterValue,
float64(obj.WriteBytesPersec),
obj.Name,
)
ch <- prometheus.MustNewConstMetric(
c.VMStorageWriteOperations,
prometheus.CounterValue,
float64(obj.WriteOperationsPerSec),
obj.Name,
)
}
return nil, nil
}
// Win32_PerfRawData_NvspNicStats_HyperVVirtualNetworkAdapter ...
type Win32_PerfRawData_NvspNicStats_HyperVVirtualNetworkAdapter struct {
Name string
BytesReceivedPersec uint64
BytesSentPersec uint64
DroppedPacketsIncomingPersec uint64
DroppedPacketsOutgoingPersec uint64
PacketsReceivedPersec uint64
PacketsSentPersec uint64
}
func (c *HyperVCollector) collectVmNetwork(ch chan<- prometheus.Metric) (*prometheus.Desc, error) {
var dst []Win32_PerfRawData_NvspNicStats_HyperVVirtualNetworkAdapter
if err := wmi.Query(wmi.CreateQuery(&dst, ""), &dst); err != nil {
return nil, err
}
for _, obj := range dst {
if strings.Contains(obj.Name, "_Total") {
continue
}
ch <- prometheus.MustNewConstMetric(
c.VMNetworkBytesReceived,
prometheus.CounterValue,
float64(obj.BytesReceivedPersec),
obj.Name,
)
ch <- prometheus.MustNewConstMetric(
c.VMNetworkBytesSent,
prometheus.CounterValue,
float64(obj.BytesSentPersec),
obj.Name,
)
ch <- prometheus.MustNewConstMetric(
c.VMNetworkDroppedPacketsIncoming,
prometheus.CounterValue,
float64(obj.DroppedPacketsIncomingPersec),
obj.Name,
)
ch <- prometheus.MustNewConstMetric(
c.VMNetworkDroppedPacketsOutgoing,
prometheus.CounterValue,
float64(obj.DroppedPacketsOutgoingPersec),
obj.Name,
)
ch <- prometheus.MustNewConstMetric(
c.VMNetworkPacketsReceived,
prometheus.CounterValue,
float64(obj.PacketsReceivedPersec),
obj.Name,
)
ch <- prometheus.MustNewConstMetric(
c.VMNetworkPacketsSent,
prometheus.CounterValue,
float64(obj.PacketsSentPersec),
obj.Name,
)
}
return nil, nil
}

View File

@@ -27,6 +27,7 @@ var (
type serviceCollector struct { type serviceCollector struct {
State *prometheus.Desc State *prometheus.Desc
StartMode *prometheus.Desc StartMode *prometheus.Desc
Status *prometheus.Desc
queryWhereClause string queryWhereClause string
} }
@@ -56,6 +57,12 @@ func NewserviceCollector() (Collector, error) {
[]string{"name", "start_mode"}, []string{"name", "start_mode"},
nil, nil,
), ),
Status: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "status"),
"The status of the service (Status)",
[]string{"name", "status"},
nil,
),
queryWhereClause: wc.String(), queryWhereClause: wc.String(),
}, nil }, nil
} }
@@ -73,6 +80,7 @@ func (c *serviceCollector) Collect(ch chan<- prometheus.Metric) error {
type Win32_Service struct { type Win32_Service struct {
Name string Name string
State string State string
Status string
StartMode string StartMode string
} }
@@ -94,6 +102,20 @@ var (
"manual", "manual",
"disabled", "disabled",
} }
allStatuses = []string{
"ok",
"error",
"degraded",
"unknown",
"pred fail",
"starting",
"stopping",
"service",
"stressed",
"nonrecover",
"no contact",
"lost comm",
}
) )
func (c *serviceCollector) collect(ch chan<- prometheus.Metric) (*prometheus.Desc, error) { func (c *serviceCollector) collect(ch chan<- prometheus.Metric) (*prometheus.Desc, error) {
@@ -131,6 +153,20 @@ func (c *serviceCollector) collect(ch chan<- prometheus.Metric) (*prometheus.Des
startMode, startMode,
) )
} }
for _, status := range allStatuses {
isCurrentStatus := 0.0
if status == strings.ToLower(service.Status) {
isCurrentStatus = 1.0
}
ch <- prometheus.MustNewConstMetric(
c.Status,
prometheus.GaugeValue,
isCurrentStatus,
strings.ToLower(service.Name),
status,
)
}
} }
return nil, nil return nil, nil
} }

View File

@@ -30,37 +30,37 @@ func NewSystemCollector() (Collector, error) {
return &SystemCollector{ return &SystemCollector{
ContextSwitchesTotal: prometheus.NewDesc( ContextSwitchesTotal: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "context_switches_total"), prometheus.BuildFQName(Namespace, subsystem, "context_switches_total"),
"PerfOS_System.ContextSwitchesPersec", "Total number of context switches (WMI source: PerfOS_System.ContextSwitchesPersec)",
nil, nil,
nil, nil,
), ),
ExceptionDispatchesTotal: prometheus.NewDesc( ExceptionDispatchesTotal: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "exception_dispatches_total"), prometheus.BuildFQName(Namespace, subsystem, "exception_dispatches_total"),
"PerfOS_System.ExceptionDispatchesPersec", "Total number of exceptions dispatched (WMI source: PerfOS_System.ExceptionDispatchesPersec)",
nil, nil,
nil, nil,
), ),
ProcessorQueueLength: prometheus.NewDesc( ProcessorQueueLength: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "processor_queue_length"), prometheus.BuildFQName(Namespace, subsystem, "processor_queue_length"),
"PerfOS_System.ProcessorQueueLength", "Length of processor queue (WMI source: PerfOS_System.ProcessorQueueLength)",
nil, nil,
nil, nil,
), ),
SystemCallsTotal: prometheus.NewDesc( SystemCallsTotal: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "system_calls_total"), prometheus.BuildFQName(Namespace, subsystem, "system_calls_total"),
"PerfOS_System.SystemCallsPersec", "Total number of system calls (WMI source: PerfOS_System.SystemCallsPersec)",
nil, nil,
nil, nil,
), ),
SystemUpTime: prometheus.NewDesc( SystemUpTime: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "system_up_time"), prometheus.BuildFQName(Namespace, subsystem, "system_up_time"),
"SystemUpTime/Frequency_Object", "System boot time (WMI source: PerfOS_System.SystemUpTime)",
nil, nil,
nil, nil,
), ),
Threads: prometheus.NewDesc( Threads: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "threads"), prometheus.BuildFQName(Namespace, subsystem, "threads"),
"PerfOS_System.Threads", "Current number of threads (WMI source: PerfOS_System.Threads)",
nil, nil,
nil, nil,
), ),
@@ -96,12 +96,12 @@ func (c *SystemCollector) collect(ch chan<- prometheus.Metric) (*prometheus.Desc
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.ContextSwitchesTotal, c.ContextSwitchesTotal,
prometheus.GaugeValue, prometheus.CounterValue,
float64(dst[0].ContextSwitchesPersec), float64(dst[0].ContextSwitchesPersec),
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.ExceptionDispatchesTotal, c.ExceptionDispatchesTotal,
prometheus.GaugeValue, prometheus.CounterValue,
float64(dst[0].ExceptionDispatchesPersec), float64(dst[0].ExceptionDispatchesPersec),
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
@@ -111,7 +111,7 @@ func (c *SystemCollector) collect(ch chan<- prometheus.Metric) (*prometheus.Desc
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.SystemCallsTotal, c.SystemCallsTotal,
prometheus.GaugeValue, prometheus.CounterValue,
float64(dst[0].SystemCallsPersec), float64(dst[0].SystemCallsPersec),
) )
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(

View File

@@ -17,6 +17,7 @@ package collector
import ( import (
"fmt" "fmt"
"io"
"io/ioutil" "io/ioutil"
"os" "os"
"path/filepath" "path/filepath"
@@ -185,6 +186,30 @@ func (c *textFileCollector) exportMTimes(mtimes map[string]time.Time, ch chan<-
} }
} }
type carriageReturnFilteringReader struct {
r io.Reader
}
// Read returns data from the underlying io.Reader, but with \r filtered out
func (cr carriageReturnFilteringReader) Read(p []byte) (int, error) {
buf := make([]byte, len(p))
n, err := cr.r.Read(buf)
if err != nil && err != io.EOF {
return n, err
}
pi := 0
for i := 0; i < n; i++ {
if buf[i] != '\r' {
p[pi] = buf[i]
pi++
}
}
return pi, err
}
// Update implements the Collector interface. // Update implements the Collector interface.
func (c *textFileCollector) Collect(ch chan<- prometheus.Metric) error { func (c *textFileCollector) Collect(ch chan<- prometheus.Metric) error {
error := 0.0 error := 0.0
@@ -203,6 +228,7 @@ fileLoop:
continue continue
} }
path := filepath.Join(c.path, f.Name()) path := filepath.Join(c.path, f.Name())
log.Debugf("Processing file %q", path)
file, err := os.Open(path) file, err := os.Open(path)
if err != nil { if err != nil {
log.Errorf("Error opening %q: %v", path, err) log.Errorf("Error opening %q: %v", path, err)
@@ -210,7 +236,7 @@ fileLoop:
continue continue
} }
var parser expfmt.TextParser var parser expfmt.TextParser
parsedFamilies, err := parser.TextToMetricFamilies(file) parsedFamilies, err := parser.TextToMetricFamilies(carriageReturnFilteringReader{r: file})
file.Close() file.Close()
if err != nil { if err != nil {
log.Errorf("Error parsing %q: %v", path, err) log.Errorf("Error parsing %q: %v", path, err)

View File

@@ -0,0 +1,20 @@
package collector
import (
"testing"
"strings"
"io/ioutil"
)
func TestCRFilter(t *testing.T) {
sr := strings.NewReader("line 1\r\nline 2")
cr := carriageReturnFilteringReader{ r: sr }
b, err := ioutil.ReadAll(cr)
if err != nil {
t.Error(err)
}
if string(b) != "line 1\nline 2" {
t.Errorf("Unexpected output %q", b)
}
}

View File

@@ -44,6 +44,16 @@ var (
[]string{"collector"}, []string{"collector"},
nil, nil,
) )
// This can be removed when client_golang exposes this on Windows
// (See https://github.com/prometheus/client_golang/issues/376)
startTime = float64(time.Now().Unix())
startTimeDesc = prometheus.NewDesc(
"process_start_time_seconds",
"Start time of the process since unix epoch in seconds.",
nil,
nil,
)
) )
// Describe sends all the descriptors of the collectors included to // Describe sends all the descriptors of the collectors included to
@@ -65,6 +75,12 @@ func (coll WmiCollector) Collect(ch chan<- prometheus.Metric) {
wg.Done() wg.Done()
}(name, c) }(name, c)
} }
ch <- prometheus.MustNewConstMetric(
startTimeDesc,
prometheus.CounterValue,
startTime,
)
wg.Wait() wg.Wait()
} }