Added feature to allow metrics collection every X iterations in specified objects.

This commit is contained in:
Rune Darrud 2016-01-31 15:06:57 +01:00
parent 042cf517b2
commit 64ada49377
2 changed files with 92 additions and 66 deletions

View File

@ -59,6 +59,13 @@ Example: `Counters = ["% Idle Time", "% Disk Read Time", "% Disk Write Time"]`
This must be specified for every counter you want the results of, This must be specified for every counter you want the results of,
it is not possible to ask for all counters in the ObjectName. it is not possible to ask for all counters in the ObjectName.
### GetMetricEvery
*Optional*
This parameter can be used where you only want to read an object on every X iteration, say every 10 iterations of whatever the interval is set for in Telegraf. If Telegraf fetches its data every 10s, it translates to only getting the data for this metric every 100s. Useful if the metric you are obtaining is expensive to get back.
Example `GetMetricEvery = 10`
### Measurement ### Measurement
*Optional* *Optional*

View File

@ -84,13 +84,14 @@ type Win_PerfCounters struct {
} }
type perfobject struct { type perfobject struct {
ObjectName string ObjectName string
Counters []string Counters []string
Instances []string Instances []string
Measurement string GetMetricEvery int
WarnOnMissing bool Measurement string
FailOnMissing bool WarnOnMissing bool
IncludeTotal bool FailOnMissing bool
IncludeTotal bool
} }
// Parsed configuration ends up here after it has been validated for valid // Parsed configuration ends up here after it has been validated for valid
@ -100,19 +101,24 @@ type itemList struct {
} }
type item struct { type item struct {
query string query string
objectName string objectName string
counter string counter string
instance string instance string
measurement string getmetricevery int
include_total bool metriccounter int
handle win.PDH_HQUERY measurement string
counterHandle win.PDH_HCOUNTER include_total bool
handle win.PDH_HQUERY
counterHandle win.PDH_HCOUNTER
} }
func (m *Win_PerfCounters) AddItem(metrics *itemList, query string, objectName string, counter string, instance string, func (m *Win_PerfCounters) AddItem(metrics *itemList, query string,
objectName string, counter string, instance string, getmetricevery int,
measurement string, include_total bool) { measurement string, include_total bool) {
var metriccounter int = 1
var handle win.PDH_HQUERY var handle win.PDH_HQUERY
var counterHandle win.PDH_HCOUNTER var counterHandle win.PDH_HCOUNTER
ret := win.PdhOpenQuery(0, 0, &handle) ret := win.PdhOpenQuery(0, 0, &handle)
@ -120,8 +126,9 @@ func (m *Win_PerfCounters) AddItem(metrics *itemList, query string, objectName s
_ = ret _ = ret
temp := &item{query, objectName, counter, instance, measurement, temp := &item{query, objectName, counter, instance, getmetricevery,
include_total, handle, counterHandle} metriccounter, measurement, include_total, handle, counterHandle}
index := len(gItemList) index := len(gItemList)
gItemList[index] = temp gItemList[index] = temp
@ -190,6 +197,13 @@ func (m *Win_PerfCounters) ParseConfig(metrics *itemList) error {
query = "\\" + objectname + "(" + instance + ")\\" + counter query = "\\" + objectname + "(" + instance + ")\\" + counter
} }
var getmetricevery int
if PerfObject.GetMetricEvery == 0 {
getmetricevery = 1
} else {
getmetricevery = PerfObject.GetMetricEvery
}
var exists uint32 = win.PdhValidatePath(query) var exists uint32 = win.PdhValidatePath(query)
if exists == win.ERROR_SUCCESS { if exists == win.ERROR_SUCCESS {
@ -197,7 +211,8 @@ func (m *Win_PerfCounters) ParseConfig(metrics *itemList) error {
fmt.Printf("Valid: %s\n", query) fmt.Printf("Valid: %s\n", query)
} }
m.AddItem(metrics, query, objectname, counter, instance, m.AddItem(metrics, query, objectname, counter, instance,
PerfObject.Measurement, PerfObject.IncludeTotal) getmetricevery, PerfObject.Measurement,
PerfObject.IncludeTotal)
} else { } else {
err := m.InvalidObject(exists, query, PerfObject, instance, counter) err := m.InvalidObject(exists, query, PerfObject, instance, counter)
return err return err
@ -271,59 +286,63 @@ func (m *Win_PerfCounters) Gather(acc telegraf.Accumulator) error {
// For iterate over the known metrics and get the samples. // For iterate over the known metrics and get the samples.
for _, metric := range gItemList { for _, metric := range gItemList {
// collect // collect
ret := win.PdhCollectQueryData(metric.handle) if metric.getmetricevery == metric.metriccounter {
if ret == win.ERROR_SUCCESS { metric.metriccounter = 1
ret = win.PdhGetFormattedCounterArrayDouble(metric.counterHandle, &bufSize, ret := win.PdhCollectQueryData(metric.handle)
&bufCount, &emptyBuf[0]) // uses null ptr here according to MSDN. if ret == win.ERROR_SUCCESS {
if ret == win.PDH_MORE_DATA { ret = win.PdhGetFormattedCounterArrayDouble(metric.counterHandle, &bufSize,
filledBuf := make([]win.PDH_FMT_COUNTERVALUE_ITEM_DOUBLE, bufCount*size) &bufCount, &emptyBuf[0]) // uses null ptr here according to MSDN.
ret = win.PdhGetFormattedCounterArrayDouble(metric.counterHandle, if ret == win.PDH_MORE_DATA {
&bufSize, &bufCount, &filledBuf[0]) filledBuf := make([]win.PDH_FMT_COUNTERVALUE_ITEM_DOUBLE, bufCount*size)
for i := 0; i < int(bufCount); i++ { ret = win.PdhGetFormattedCounterArrayDouble(metric.counterHandle,
c := filledBuf[i] &bufSize, &bufCount, &filledBuf[0])
var s string = win.UTF16PtrToString(c.SzName) for i := 0; i < int(bufCount); i++ {
c := filledBuf[i]
var s string = win.UTF16PtrToString(c.SzName)
var add bool var add bool
if metric.include_total { if metric.include_total {
// If IncludeTotal is set, include all. // If IncludeTotal is set, include all.
add = true add = true
} else if metric.instance == "*" && !strings.Contains(s, "_Total") { } else if metric.instance == "*" && !strings.Contains(s, "_Total") {
// Catch if set to * and that it is not a '*_Total*' instance. // Catch if set to * and that it is not a '*_Total*' instance.
add = true add = true
} else if metric.instance == s { } else if metric.instance == s {
// Catch if we set it to total or some form of it // Catch if we set it to total or some form of it
add = true add = true
} else if metric.instance == "------" { } else if metric.instance == "------" {
add = true add = true
}
if add {
fields := make(map[string]interface{})
tags := make(map[string]string)
if s != "" {
tags["instance"] = s
}
tags["objectname"] = metric.objectName
fields[string(metric.counter)] = float32(c.FmtValue.DoubleValue)
var measurement string
if metric.measurement == "" {
measurement = "win_perf_counters"
} else {
measurement = metric.measurement
}
acc.AddFields(measurement, fields, tags)
}
} }
if add { filledBuf = nil
fields := make(map[string]interface{}) // Need to at least set bufSize to zero, because if not, the function will not
tags := make(map[string]string) // return PDH_MORE_DATA and will not set the bufSize.
if s != "" { bufCount = 0
tags["instance"] = s bufSize = 0
}
tags["objectname"] = metric.objectName
fields[string(metric.counter)] = float32(c.FmtValue.DoubleValue)
var measurement string
if metric.measurement == "" {
measurement = "win_perf_counters"
} else {
measurement = metric.measurement
}
acc.AddFields(measurement, fields, tags)
}
} }
filledBuf = nil
// Need to at least set bufSize to zero, because if not, the function will not
// return PDH_MORE_DATA and will not set the bufSize.
bufCount = 0
bufSize = 0
} }
} else {
metric.metriccounter++
} }
} }