protect against emtpy wmi query result sets

If an WMI query were to return an empty result set, trying to access the
first element in the result set would result in a `panic: runtime error:
index out of range` error.

add logic to explicitly check if the result set size is 0 and return an
error rather.

Fixes https://github.com/martinlindhe/wmi_exporter/issues/240
This commit is contained in:
Steve Zook
2018-08-07 15:42:16 -04:00
parent 832771b4a2
commit c156f2bcbe
9 changed files with 1110 additions and 1060 deletions

View File

@@ -3,6 +3,8 @@
package collector package collector
import ( import (
"errors"
"github.com/StackExchange/wmi" "github.com/StackExchange/wmi"
"github.com/prometheus/client_golang/prometheus" "github.com/prometheus/client_golang/prometheus"
"github.com/prometheus/common/log" "github.com/prometheus/common/log"
@@ -616,6 +618,9 @@ func (c *ADCollector) collect(ch chan<- prometheus.Metric) (*prometheus.Desc, er
if err := wmi.Query(q, &dst); err != nil { if err := wmi.Query(q, &dst); err != nil {
return nil, err return nil, err
} }
if len(dst) == 0 {
return nil, errors.New("WMI query returned empty result set")
}
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.AddressBookOperationsTotal, c.AddressBookOperationsTotal,

View File

@@ -4,6 +4,8 @@
package collector package collector
import ( import (
"errors"
"github.com/StackExchange/wmi" "github.com/StackExchange/wmi"
"github.com/prometheus/client_golang/prometheus" "github.com/prometheus/client_golang/prometheus"
"github.com/prometheus/common/log" "github.com/prometheus/common/log"
@@ -60,6 +62,9 @@ func (c *CSCollector) collect(ch chan<- prometheus.Metric) (*prometheus.Desc, er
if err := wmi.Query(q, &dst); err != nil { if err := wmi.Query(q, &dst); err != nil {
return nil, err return nil, err
} }
if len(dst) == 0 {
return nil, errors.New("WMI query returned empty result set")
}
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.LogicalProcessors, c.LogicalProcessors,

View File

@@ -4,6 +4,8 @@
package collector package collector
import ( import (
"errors"
"github.com/StackExchange/wmi" "github.com/StackExchange/wmi"
"github.com/prometheus/client_golang/prometheus" "github.com/prometheus/client_golang/prometheus"
"github.com/prometheus/common/log" "github.com/prometheus/common/log"
@@ -237,6 +239,9 @@ func (c *DNSCollector) collect(ch chan<- prometheus.Metric) (*prometheus.Desc, e
if err := wmi.Query(q, &dst); err != nil { if err := wmi.Query(q, &dst); err != nil {
return nil, err return nil, err
} }
if len(dst) == 0 {
return nil, errors.New("WMI query returned empty result set")
}
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.ZoneTransferRequestsReceived, c.ZoneTransferRequestsReceived,

View File

@@ -7,6 +7,7 @@
package collector package collector
import ( import (
"errors"
"fmt" "fmt"
"regexp" "regexp"
@@ -1738,7 +1739,10 @@ func (c *IISCollector) collect(ch chan<- prometheus.Metric) (*prometheus.Desc, e
return nil, err return nil, err
} }
if len(dst_cache) > 0 { if len(dst_cache) == 0 {
return nil, errors.New("WMI query returned empty result set")
}
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.ServiceCache_ActiveFlushedEntries, c.ServiceCache_ActiveFlushedEntries,
prometheus.GaugeValue, prometheus.GaugeValue,
@@ -1947,7 +1951,6 @@ func (c *IISCollector) collect(ch chan<- prometheus.Metric) (*prometheus.Desc, e
prometheus.CounterValue, prometheus.CounterValue,
float64(dst_cache[0].OutputCacheTotalFlushes), float64(dst_cache[0].OutputCacheTotalFlushes),
) )
}
return nil, nil return nil, nil
} }

View File

@@ -1769,7 +1769,10 @@ func (c *MSSQLCollector) collectAccessMethods(ch chan<- prometheus.Metric, sqlIn
return nil, err return nil, err
} }
if len(dst) > 0 { if len(dst) == 0 {
return nil, errors.New("WMI query returned empty result set")
}
v := dst[0] v := dst[0]
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.AccessMethodsAUcleanupbatches, c.AccessMethodsAUcleanupbatches,
@@ -2071,7 +2074,6 @@ func (c *MSSQLCollector) collectAccessMethods(ch chan<- prometheus.Metric, sqlIn
float64(v.WorktablesFromCacheRatio), float64(v.WorktablesFromCacheRatio),
sqlInstance, sqlInstance,
) )
}
return nil, nil return nil, nil
} }
@@ -2201,8 +2203,10 @@ func (c *MSSQLCollector) collectBufferManager(ch chan<- prometheus.Metric, sqlIn
if err := wmi.Query(q, &dst); err != nil { if err := wmi.Query(q, &dst); err != nil {
return nil, err return nil, err
} }
if len(dst) == 0 {
return nil, errors.New("WMI query returned empty result set")
}
if len(dst) > 0 {
v := dst[0] v := dst[0]
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
@@ -2358,7 +2362,7 @@ func (c *MSSQLCollector) collectBufferManager(ch chan<- prometheus.Metric, sqlIn
float64(v.Targetpages), float64(v.Targetpages),
sqlInstance, sqlInstance,
) )
}
return nil, nil return nil, nil
} }
@@ -2998,8 +3002,10 @@ func (c *MSSQLCollector) collectGeneralStatistics(ch chan<- prometheus.Metric, s
if err := wmi.Query(q, &dst); err != nil { if err := wmi.Query(q, &dst); err != nil {
return nil, err return nil, err
} }
if len(dst) == 0 {
return nil, errors.New("WMI query returned empty result set")
}
if len(dst) > 0 {
v := dst[0] v := dst[0]
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.GenStatsActiveTempTables, c.GenStatsActiveTempTables,
@@ -3168,7 +3174,7 @@ func (c *MSSQLCollector) collectGeneralStatistics(ch chan<- prometheus.Metric, s
float64(v.UserConnections), float64(v.UserConnections),
sqlInstance, sqlInstance,
) )
}
return nil, nil return nil, nil
} }
@@ -3280,8 +3286,10 @@ func (c *MSSQLCollector) collectMemoryManager(ch chan<- prometheus.Metric, sqlIn
if err := wmi.Query(q, &dst); err != nil { if err := wmi.Query(q, &dst); err != nil {
return nil, err return nil, err
} }
if len(dst) == 0 {
return nil, errors.New("WMI query returned empty result set")
}
if len(dst) > 0 {
v := dst[0] v := dst[0]
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
@@ -3423,7 +3431,7 @@ func (c *MSSQLCollector) collectMemoryManager(ch chan<- prometheus.Metric, sqlIn
float64(v.TotalServerMemoryKB*1024), float64(v.TotalServerMemoryKB*1024),
sqlInstance, sqlInstance,
) )
}
return nil, nil return nil, nil
} }
@@ -3451,7 +3459,10 @@ func (c *MSSQLCollector) collectSQLStats(ch chan<- prometheus.Metric, sqlInstanc
return nil, err return nil, err
} }
if len(dst) > 0 { if len(dst) == 0 {
return nil, errors.New("WMI query returned empty result set")
}
v := dst[0] v := dst[0]
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
@@ -3530,6 +3541,6 @@ func (c *MSSQLCollector) collectSQLStats(ch chan<- prometheus.Metric, sqlInstanc
float64(v.UnsafeAutoParamsPersec), float64(v.UnsafeAutoParamsPersec),
sqlInstance, sqlInstance,
) )
}
return nil, nil return nil, nil
} }

View File

@@ -4,6 +4,7 @@
package collector package collector
import ( import (
"errors"
"time" "time"
"github.com/StackExchange/wmi" "github.com/StackExchange/wmi"
@@ -142,6 +143,10 @@ func (c *OSCollector) collect(ch chan<- prometheus.Metric) (*prometheus.Desc, er
return nil, err return nil, err
} }
if len(dst) == 0 {
return nil, errors.New("WMI query returned empty result set")
}
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.PhysicalMemoryFreeBytes, c.PhysicalMemoryFreeBytes,
prometheus.GaugeValue, prometheus.GaugeValue,

View File

@@ -4,6 +4,7 @@
package collector package collector
import ( import (
"errors"
"github.com/StackExchange/wmi" "github.com/StackExchange/wmi"
"github.com/prometheus/client_golang/prometheus" "github.com/prometheus/client_golang/prometheus"
"github.com/prometheus/common/log" "github.com/prometheus/common/log"
@@ -94,6 +95,9 @@ func (c *SystemCollector) collect(ch chan<- prometheus.Metric) (*prometheus.Desc
if err := wmi.Query(q, &dst); err != nil { if err := wmi.Query(q, &dst); err != nil {
return nil, err return nil, err
} }
if len(dst) == 0 {
return nil, errors.New("WMI query returned empty result set")
}
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.ContextSwitchesTotal, c.ContextSwitchesTotal,

View File

@@ -5,6 +5,7 @@
package collector package collector
import ( import (
"errors"
"github.com/StackExchange/wmi" "github.com/StackExchange/wmi"
"github.com/prometheus/client_golang/prometheus" "github.com/prometheus/client_golang/prometheus"
"github.com/prometheus/common/log" "github.com/prometheus/common/log"
@@ -118,6 +119,9 @@ func (c *TCPCollector) collect(ch chan<- prometheus.Metric) (*prometheus.Desc, e
if err := wmi.Query(q, &dst); err != nil { if err := wmi.Query(q, &dst); err != nil {
return nil, err return nil, err
} }
if len(dst) == 0 {
return nil, errors.New("WMI query returned empty result set")
}
// Counters // Counters
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(

View File

@@ -2,6 +2,8 @@
package collector package collector
import ( import (
"errors"
"github.com/StackExchange/wmi" "github.com/StackExchange/wmi"
"github.com/prometheus/client_golang/prometheus" "github.com/prometheus/client_golang/prometheus"
"github.com/prometheus/common/log" "github.com/prometheus/common/log"
@@ -201,6 +203,9 @@ func (c *VmwareCollector) collectMem(ch chan<- prometheus.Metric) (*prometheus.D
if err := wmi.Query(q, &dst); err != nil { if err := wmi.Query(q, &dst); err != nil {
return nil, err return nil, err
} }
if len(dst) == 0 {
return nil, errors.New("WMI query returned empty result set")
}
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.MemActive, c.MemActive,
@@ -287,6 +292,9 @@ func (c *VmwareCollector) collectCpu(ch chan<- prometheus.Metric) (*prometheus.D
if err := wmi.Query(q, &dst); err != nil { if err := wmi.Query(q, &dst); err != nil {
return nil, err return nil, err
} }
if len(dst) == 0 {
return nil, errors.New("WMI query returned empty result set")
}
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
c.CpuLimitMHz, c.CpuLimitMHz,