adds an alternate windows performance counter input plugin

This commit is contained in:
David Zarlengo 2016-08-11 23:17:41 -07:00
parent 26315bfbea
commit 2934f860db
6 changed files with 850 additions and 0 deletions

View File

@ -82,6 +82,7 @@ consistent with the behavior of `collection_jitter`.
- [#1213](https://github.com/influxdata/telegraf/issues/1213): Add inactive & active memory to mem plugin. - [#1213](https://github.com/influxdata/telegraf/issues/1213): Add inactive & active memory to mem plugin.
- [#1543](https://github.com/influxdata/telegraf/pull/1543): Official Windows service. - [#1543](https://github.com/influxdata/telegraf/pull/1543): Official Windows service.
- [#1414](https://github.com/influxdata/telegraf/pull/1414): Forking sensors command to remove C package dependency. - [#1414](https://github.com/influxdata/telegraf/pull/1414): Forking sensors command to remove C package dependency.
- [FIXME](https://github.com/influxdata/telegraf/issues/FIXME): Adds `wpc` input plugin as an alternative to `win_perf_counters`.
### Bugfixes ### Bugfixes

View File

@ -74,6 +74,7 @@ import (
_ "github.com/influxdata/telegraf/plugins/inputs/varnish" _ "github.com/influxdata/telegraf/plugins/inputs/varnish"
_ "github.com/influxdata/telegraf/plugins/inputs/webhooks" _ "github.com/influxdata/telegraf/plugins/inputs/webhooks"
_ "github.com/influxdata/telegraf/plugins/inputs/win_perf_counters" _ "github.com/influxdata/telegraf/plugins/inputs/win_perf_counters"
_ "github.com/influxdata/telegraf/plugins/inputs/wpc"
_ "github.com/influxdata/telegraf/plugins/inputs/zfs" _ "github.com/influxdata/telegraf/plugins/inputs/zfs"
_ "github.com/influxdata/telegraf/plugins/inputs/zookeeper" _ "github.com/influxdata/telegraf/plugins/inputs/zookeeper"
) )

View File

@ -0,0 +1,133 @@
# wpc Input Plugin
This plugin gathers stats from [Windows Performance Counters](https://msdn.microsoft.com/en-us/library/windows/desktop/aa373083(v=vs.85).aspx)
### Configuration:
```toml
# A plugin to collect stats from Windows Performance Counters
[[inputs.wpc]]
## If the system being polled for data does not have a particular Counter at startup
## of the Telegraf agent, it will not be gathered.
# Prints all matching performance counters (useful for debugging)
# PrintValid = false
[[inputs.wpc.template]]
# Processor usage, alternative to native.
Counters = [
# Use double-backslashes to work around a TOML parsing issue.
[ "usage_idle", "\\Processor(*)\\%% Idle Time" ],
[ "usage_user", "\\Processor(*)\\%% User Time" ],
[ "usage_system", "\\Processor(*)\\%% Processor Time" ]
]
Measurement = "win_cpu"
# Print out when the performance counter is missing from object, counter or instance.
# WarnOnMissing = false
```
## `wpc` vs `win_perf_counters`
The `win_perf_counters` plugin generates tags and fields using native Windows names. This can make it difficult to compare common measurements across heterogenous environments because Windows names tend towards complexity. For example, on Windows the performance counter "\\Processor(*)\\%% User Time" is equivalent to the Linux metric "cpu.usage_user" - good luck displaying both series on the same plot in Grafana.
Additionally, `win_perf_counters` can generate an large number of series in an InfluxDB database due to the inclusion of the Windows Performance Counter Object Name (e.g. Processor, Processor Information, Memory, etc) in the tag list. According to the [Hardware Sizing Guidelines](https://docs.influxdata.com/influxdb/v0.13/guides/hardware_sizing/#when-do-i-need-more-ram), series cardinality strongly affects the amount of RAM required by the InfluxDB server. Therefore, there is a risk that heavily instrumented Windows machines can unduly impact the provisioning requirements of the InfluxDB server simply due to the use of `win_perf_counters`.
The `wpc` plugin mitigates these two potential issues by making Performance Counter queries field names explicit, and by transparently regrouping fully-qualified Performance Counter queries by instance to minimize the number of points generated.
## An IIS / ASP.NET example
The templates below could be one way of instrumenting an IIS/ASP.NET web server.
```
[[inputs.wpc.template]]
Counters = [
[ "get_rate", "\\Web Service(*)\\Get Requests/sec" ],
[ "post_rate", "\\Web Service(*)\\Post Requests/sec" ],
[ "conn_rate", "\\Web Service(*)\\Connection Attempts/sec" ],
[ "conn", "\\Web Service(*)\\Current Connections" ],
[ "isapi_rate", "\\Web Service(*)\\ISAPI Extension Requests/sec" ],
# These queries are remapped to equivalent HAProxy field names.
[ "qcur", "\\HTTP Service Request Queues(*)\\CurrentQueueSize" ],
[ "dreq", "\\HTTP Service Request Queues(*)\\RejectedRequests" ],
]
Measurement = "iis_websvc"
## Example output
# iis_websvc,instance=HelloWorld get_rate=4i,post_rate=10i,conn_rate=1i,conn=100i,isapi_rate=0i,qcur=0i,dreq=0i 1462765437090957980
[[inputs.wpc.template]]
Counters = [
[ "restart", "\\ASP.NET\\Application Restarts" ],
[ "wait_time", "\\ASP.NET\\Request Wait Time" ],
[ "requests", "\\ASP.NET\\Requests Current" ],
[ "waiting", "\\ASP.NET\\Requests Queued" ],
[ "rejected", "\\ASP.NET\\Requests Rejected" ],
[ "cache_tot", "\\ASP.NET Applications(__Total__)\\Cache Total Entries" ],
[ "cache_hit", "\\ASP.NET Applications(__Total__)\\Cache Total Hit Ratio" ],
[ "error_rate", "\\ASP.NET Applications(__Total__)\\Errors Total/Sec" ],
[ "req_rate", "\\ASP.NET Applications(__Total__)\\Requests/Sec" ],
[ "user_hit_rate", "\\Web Service Cache\\URI Cache Hits %" ],
[ "system_hit_rate", "\\Web Service Cache\\Kernel: URI Cache Hits %" ],
[ "file_hit_rate", "\\Web Service Cache\\File Cache Hits %" ],
]
Measurement = "iis"
## Example output
# iis,instance= restart=0i,wait_time=0i,requests=0i,waiting=0i,rejected=3i,user_hit_rate=4.99,system_hit_rate=3.34,file_hit_rate=9.3 1462765437090957980
# iis,instance=__Total__ cache_tot=100000i,cache_hit=55.555555,error_rate=3.324,req_rate=0
```
## Exploring Windows Performance Counters with `typeperf`
Windows ships with a command-line utility named `typeperf` that can be used to query, explore, and sample the same fully-qualified Performance Counter queries that the `wpc` plugin expects.
```Dos
C:\> typeperf /?
Microsoft r TypePerf.exe (6.3.9600.17415)
Typeperf writes performance data to the command window or to a log file. To
stop Typeperf, press CTRL+C.
Usage:
typeperf { <counter [counter ...]> | -cf <filename> | -q [object]
| -qx [object] } [options]
Parameters:
<counter [counter ...]> Performance counters to monitor.
Options:
-? Displays context sensitive help.
-f <CSV|TSV|BIN|SQL> Output file format. Default is CSV.
-cf <filename> File containing performance counters to
monitor, one per line.
-si <[[hh:]mm:]ss> Time between samples. Default is 1 second.
-o <filename> Path of output file or SQL database. Default
is STDOUT.
-q [object] List installed counters (no instances). To
list counters for one object, include the
object name, such as Processor.
-qx [object] List installed counters with instances. To
list counters for one object, include the
object name, such as Processor.
-sc <samples> Number of samples to collect. Default is to
sample until CTRL+C.
-config <filename> Settings file containing command options.
-s <computer_name> Server to monitor if no server is specified
in the counter path.
-y Answer yes to all questions without prompting.
Note:
Counter is the full name of a performance counter in
"\\<Computer>\<Object>(<Instance>)\<Counter>" format,
such as "\\Server1\Processor(0)\% User Time".
Examples:
typeperf "\Processor(_Total)\% Processor Time"
typeperf -cf counters.txt -si 5 -sc 50 -f TSV -o domain2.tsv
typeperf -qx PhysicalDisk -o counters.txt
```
## Future Features
- Add the ability to alias Instance values and/or the ability to specify sets of equivalent instances (e.g. [ "", "_Total", "__Total__" ]).

316
plugins/inputs/wpc/wpc.go Normal file
View File

@ -0,0 +1,316 @@
// +build windows
package wpc
import (
"errors"
"fmt"
"strings"
"unsafe"
"github.com/influxdata/telegraf"
"github.com/influxdata/telegraf/plugins/inputs"
lxn "github.com/lxn/win"
)
var sampleConfig string = `
## A plugin to collect stats from Windows Performance Counters.
## If the system being polled for data does not have a particular Counter at startup
## of the Telegraf agent, it will not be gathered.
# Prints all matching performance counters (useful for debugging)
# PrintValid = false
[[inputs.wpc.template]]
# Processor usage, alternative to native.
Counters = [
[ "usage_idle", "\\Processor(*)\\%% Idle Time" ],
[ "usage_user", "\\Processor(*)\\%% User Time" ],
[ "usage_system", "\\Processor(*)\\%% Processor Time" ]
]
Measurement = "win_cpu"
# Print out when the performance counter is missing from object, counter or instance.
# WarnOnMissing = false
[[inputs.wpc.template]]
# Disk times and queues
Counters = [
[ "usage_idle", "\\LogicalDisk(*)\\%% Idle Time" ],
[ "usage_used", "\\LogicalDisk(*)\\%% Disk Time" ],
[ "usage_read", "\\LogicalDisk(*)\\%% Disk Read Time" ],
[ "usage_write", "\\LogicalDisk(*)\\%% Disk Write Time" ],
[ "usage_user", "\\LogicalDisk(*)\\%% User Time" ],
[ "qcur", "\\LogicalDisk(*)\\Current Disk Queue Length" ]
]
Measurement = "win_diskio"
# Print out when the performance counter is missing from object, counter or instance.
# WarnOnMissing = false
[[inputs.wpc.template]]
# System and memory details
Counters = [
[ "cs_rate", "\\System\\Context Switches/sec" ],
[ "syscall_rate", "\\System\\System Calls/sec" ],
[ "mem_available", "\\Memory\\Available Bytes" ]
]
Measurement = "win_system"
# Print out when the performance counter is missing from object, counter or instance.
# WarnOnMissing = false
`
type WindowsPerformanceCounter struct {
PrintValid bool
TestName string
PreVistaSupport bool
Template []template
}
type template struct {
Counters [][]string
Measurement string
WarnOnMissing bool
FailOnMissing bool
}
type task struct {
measurement string
fields map[string]*counter
}
type counter struct {
query string
handle lxn.PDH_HQUERY
counterHandle lxn.PDH_HCOUNTER
current map[string]float32
}
// Globals
var (
gConfigParsed bool
// Parsed configuration ends up here after it has been validated
gTaskList []*task
// Counter cache to avoid gathering the same counter more than once per Gather
gCounterCache = make(map[string]*counter)
// Various error messages
errBadConfig error = errors.New("inputs.wpc.series contains invalid configuration")
errObjectNotExist error = errors.New("Performance object does not exist")
errCounterNotExist error = errors.New("Counter in Performance object does not exist")
errInstanceNotExist error = errors.New("Instance in Performance object does not exist")
errBadQuery error = errors.New("Invalid query for Performance Counters")
// Used to cleanup instance names
sanitizedChars = strings.NewReplacer("/sec", "_persec", "/Sec", "_persec", " ", "_", "%", "Percent", `\`, "", ",", "_")
)
func (m *WindowsPerformanceCounter) Description() string {
return "Input plugin to query Performance Counters on Windows operating systems"
}
func (m *WindowsPerformanceCounter) SampleConfig() string {
return sampleConfig
}
func (m *WindowsPerformanceCounter) Gather(acc telegraf.Accumulator) error {
// We only need to parse the config during the init, it uses the global variable after.
if gConfigParsed == false {
err := m.parseConfig()
gConfigParsed = true
if err != nil {
return err
}
}
// Sample counters
for _, c := range gCounterCache {
if ok := c.queryPerformanceCounter(); !ok {
continue
}
}
type grouping struct {
fields map[string]interface{}
tags map[string]string
}
for _, t := range gTaskList {
groups := make(map[string]*grouping)
// Regroup samples by (measurement, instance) to minimize points generated.
for field, c := range t.fields {
for instance, f32 := range c.current {
g, ok := groups[instance]
if !ok {
g = &grouping{
tags: make(map[string]string),
fields: make(map[string]interface{})}
g.tags["instance"] = sanitizedChars.Replace(instance)
groups[instance] = g
}
g.fields[field] = f32
}
}
for _, g := range groups {
acc.AddFields(t.measurement, g.fields, g.tags)
}
}
return nil
}
// Samples (instance, value) tuples from the performance counter
func (c *counter) queryPerformanceCounter() (ok bool) {
if ret := lxn.PdhCollectQueryData(c.handle); ret != lxn.ERROR_SUCCESS {
return false
}
var bufSize uint32
var bufCount uint32
var size uint32 = uint32(unsafe.Sizeof(lxn.PDH_FMT_COUNTERVALUE_ITEM_DOUBLE{}))
var emptyBuf [1]lxn.PDH_FMT_COUNTERVALUE_ITEM_DOUBLE // need at least 1 addressable null ptr.
// uses null ptr here according to MSDN.
if ret := lxn.PdhGetFormattedCounterArrayDouble(c.counterHandle, &bufSize, &bufCount, &emptyBuf[0]); ret != lxn.PDH_MORE_DATA || bufCount == 0 {
return false
}
coll := make(map[string]float32)
data := make([]lxn.PDH_FMT_COUNTERVALUE_ITEM_DOUBLE, bufCount*size)
_ = lxn.PdhGetFormattedCounterArrayDouble(c.counterHandle, &bufSize, &bufCount, &data[0])
for i := 0; i < int(bufCount); i++ {
res := data[i]
instance := lxn.UTF16PtrToString(res.SzName)
value := float32(res.FmtValue.DoubleValue)
coll[instance] = value
}
c.current = coll
return true
}
func (m *WindowsPerformanceCounter) validatePerformanceCounterPath(query string, onMissingWarn, onMissingFail bool) (ok bool, err error) {
const (
lxn_PDH_CSTATUS_NO_OBJECT uint32 = 3221228472
lxn_PDH_CSTATUS_NO_COUNTER uint32 = 3221228473
lxn_PDH_CSTATUS_NO_INSTANCE uint32 = 2147485649
)
exists := lxn.PdhValidatePath(query)
if exists == lxn.ERROR_SUCCESS {
if m.PrintValid {
fmt.Printf("Valid: %s\n", query)
}
return true, nil
} else if !onMissingWarn && !onMissingFail {
return false, nil
}
switch exists {
case lxn_PDH_CSTATUS_NO_OBJECT:
if onMissingFail {
return false, errObjectNotExist
}
fmt.Printf("Performance Object does not exist in query: %s\n", query)
break
case lxn_PDH_CSTATUS_NO_COUNTER:
if onMissingFail {
return false, errCounterNotExist
}
fmt.Printf("Counter does not exist in query: %s\n", query)
break
case lxn_PDH_CSTATUS_NO_INSTANCE:
if onMissingFail {
return false, errInstanceNotExist
}
fmt.Printf("Instance does not exist in query: %s\n", query)
break
default:
fmt.Printf("Invalid result: %v, query: %s\n", exists, query)
if onMissingFail {
return false, errBadQuery
}
break
}
return false, nil
}
func (m *WindowsPerformanceCounter) openPerformanceCounter(query string) *counter {
var handle lxn.PDH_HQUERY
var counterHandle lxn.PDH_HCOUNTER
ret := lxn.PdhOpenQuery(0, 0, &handle)
if m.PreVistaSupport {
ret = lxn.PdhAddCounter(handle, query, 0, &counterHandle)
} else {
ret = lxn.PdhAddEnglishCounter(handle, query, 0, &counterHandle)
}
_ = ret
return &counter{query, handle, counterHandle, nil}
}
// Populates the global counter cache and task list.
func (m *WindowsPerformanceCounter) parseConfig() error {
if len(m.Template) == 0 {
err := errors.New("Nothing to do!")
return err
}
for _, tmpl := range m.Template {
t := &task{
measurement: tmpl.Measurement,
fields: make(map[string]*counter),
}
for _, pair := range tmpl.Counters {
if len(pair) != 2 {
return errBadConfig
}
field := pair[0]
query := pair[1]
if _, ok := gCounterCache[query]; !ok {
if ok, err := m.validatePerformanceCounterPath(query, tmpl.WarnOnMissing, tmpl.FailOnMissing); !ok && err != nil {
return err
} else if !ok {
continue
}
gCounterCache[query] = m.openPerformanceCounter(query)
}
t.fields[field] = gCounterCache[query]
}
gTaskList = append(gTaskList, t)
}
return nil
}
// func (m *WindowsPerformanceCounter) cleanup(metrics *itemList) {
// // Cleanup
// for _, metric := range metrics.items {
// ret := lxn.PdhCloseQuery(metric.handle)
// _ = ret
// }
// }
func init() {
inputs.Add("wpc", func() telegraf.Input { return &WindowsPerformanceCounter{} })
}

View File

@ -0,0 +1,3 @@
// +build !windows
package wpc

View File

@ -0,0 +1,396 @@
// +build windows
package wpc
import (
"errors"
"testing"
"time"
"github.com/influxdata/telegraf/testutil"
"github.com/stretchr/testify/require"
)
func TestWPCConfigGet1(t *testing.T) {
var templates = make([]template, 1)
counters := [][]string{
[]string{"foo", "\\Processor Information(_Total)\\%% Processor Time"},
}
var measurement string = "test"
var warnonmissing bool = false
var failonmissing bool = true
tmpl := template{
Counters: counters,
Measurement: measurement,
WarnOnMissing: warnonmissing,
FailOnMissing: failonmissing,
}
templates[0] = tmpl
m := WindowsPerformanceCounter{PrintValid: false, TestName: "ConfigGet1", Template: templates}
err := m.parseConfig()
require.NoError(t, err)
}
func TestWPCConfigGet2(t *testing.T) {
var templates = make([]template, 1)
counters := [][]string{
[]string{"foo", "\\Processor Information(_Total)\\%% Processor Time"},
}
var measurement string = "test"
var warnonmissing bool = false
var failonmissing bool = true
tmpl := template{
Counters: counters,
Measurement: measurement,
WarnOnMissing: warnonmissing,
FailOnMissing: failonmissing,
}
templates[0] = tmpl
m := WindowsPerformanceCounter{PrintValid: false, TestName: "ConfigGet2", Template: templates}
err := m.parseConfig()
require.NoError(t, err)
require.Equal(t, 1, len(gTaskList), "Wrong number of tasks defined.")
require.Equal(t, 1, len(gCounterCache), "Wrong number of counters opened.")
require.Equal(t, 1, len(gTaskList[0].fields), "Wrong number of field mappings defined.")
require.Equal(t, "test", gTaskList[0].measurement, "Wrong measurement saved.")
}
func TestWPCConfigGet3(t *testing.T) {
var templates = make([]template, 1)
counters := [][]string{
[]string{"foo", "\\Processor Information(_Total)\\%% Processor Time"},
[]string{"bar", "\\Processor Information(_Total)\\%% Processor Time"},
}
var measurement string = "test"
var warnonmissing bool = false
var failonmissing bool = true
tmpl := template{
Counters: counters,
Measurement: measurement,
WarnOnMissing: warnonmissing,
FailOnMissing: failonmissing,
}
templates[0] = tmpl
m := WindowsPerformanceCounter{PrintValid: false, TestName: "ConfigGet3", Template: templates}
err := m.parseConfig()
require.NoError(t, err)
require.Equal(t, 1, len(gTaskList), "Wrong number of tasks defined.")
require.Equal(t, 1, len(gCounterCache), "Wrong number of counters opened.")
require.Equal(t, 2, len(gTaskList[0].fields), "Wrong number of field mappings defined.")
require.Equal(t, "test", gTaskList[0].measurement, "Wrong measurement saved.")
}
func TestWPCConfigGet4(t *testing.T) {
var templates = make([]template, 1)
counters := [][]string{
[]string{"foo", "\\Processor Information(_Total)\\%% Processor Time"},
[]string{"bar", "\\System\\Context Switches/sec"},
}
var measurement string = "test"
var warnonmissing bool = false
var failonmissing bool = true
tmpl := template{
Counters: counters,
Measurement: measurement,
WarnOnMissing: warnonmissing,
FailOnMissing: failonmissing,
}
templates[0] = tmpl
m := WindowsPerformanceCounter{PrintValid: false, TestName: "ConfigGet4", Template: templates}
err := m.parseConfig()
require.NoError(t, err)
require.Equal(t, 1, len(gTaskList), "Wrong number of tasks defined.")
require.Equal(t, 2, len(gCounterCache), "Wrong number of counters opened.")
require.Equal(t, 2, len(gTaskList[0].fields), "Wrong number of field mappings defined.")
require.Equal(t, "test", gTaskList[0].measurement, "Wrong measurement saved.")
}
func TestWPCConfigGet5(t *testing.T) {
var templates = make([]template, 1)
counters := [][]string{
[]string{"foo", "\\Processor Information(*)\\%% Processor Time"},
}
var measurement string = "test"
var warnonmissing bool = false
var failonmissing bool = true
tmpl := template{
Counters: counters,
Measurement: measurement,
WarnOnMissing: warnonmissing,
FailOnMissing: failonmissing,
}
templates[0] = tmpl
m := WindowsPerformanceCounter{PrintValid: false, TestName: "ConfigGet5", Template: templates}
err := m.parseConfig()
require.NoError(t, err)
require.Equal(t, 1, len(gTaskList), "Wrong number of tasks defined.")
require.Equal(t, 1, len(gCounterCache), "Wrong number of counters opened.")
require.Equal(t, 1, len(gTaskList[0].fields), "Wrong number of field mappings defined.")
require.Equal(t, "test", gTaskList[0].measurement, "Wrong measurement saved.")
}
func TestWPCConfigGet6(t *testing.T) {
var templates = make([]template, 1)
counters := [][]string{
[]string{"foo", "\\Processor Information(*)\\%% Processor TimeERROR"},
[]string{"bar", "\\Processor Information(*)\\%% Idle Time"},
}
var measurement string = "test"
var warnonmissing bool = false
var failonmissing bool = false
tmpl := template{
Counters: counters,
Measurement: measurement,
WarnOnMissing: warnonmissing,
FailOnMissing: failonmissing,
}
templates[0] = tmpl
m := WindowsPerformanceCounter{PrintValid: false, TestName: "ConfigGet6", Template: templates}
err := m.parseConfig()
require.NoError(t, err)
require.Equal(t, 1, len(gTaskList), "Wrong number of tasks defined.")
require.Equal(t, 1, len(gCounterCache), "Wrong number of counters opened.")
require.Equal(t, 1, len(gTaskList[0].fields), "Wrong number of field mappings defined.")
require.Equal(t, "test", gTaskList[0].measurement, "Wrong measurement saved.")
}
func TestWPCConfigError1(t *testing.T) {
var templates = make([]template, 1)
counters := [][]string{
[]string{"foo", "\\Processor InformationERROR(*)\\%% Processor Time"},
}
var measurement string = "test"
var warnonmissing bool = false
var failonmissing bool = false
tmpl := template{
Counters: counters,
Measurement: measurement,
WarnOnMissing: warnonmissing,
FailOnMissing: failonmissing,
}
templates[0] = tmpl
m := WindowsPerformanceCounter{PrintValid: false, TestName: "ConfigError1", Template: templates}
err := m.parseConfig()
require.Error(t, err)
}
func TestWPCConfigError2(t *testing.T) {
var templates = make([]template, 1)
counters := [][]string{
[]string{"foo", "\\Processor(SuperERROR)\\%% C1 Time"},
}
var measurement string = "test"
var warnonmissing bool = false
var failonmissing bool = false
tmpl := template{
Counters: counters,
Measurement: measurement,
WarnOnMissing: warnonmissing,
FailOnMissing: failonmissing,
}
templates[0] = tmpl
m := WindowsPerformanceCounter{PrintValid: false, TestName: "ConfigError2", Template: templates}
err := m.parseConfig()
require.Error(t, err)
}
func TestWPCConfigError3(t *testing.T) {
var templates = make([]template, 1)
counters := [][]string{
[]string{"foo", "\\Processor Information(*)\\%% Processor TimeERROR"},
}
var measurement string = "test"
var warnonmissing bool = false
var failonmissing bool = true
tmpl := template{
Counters: counters,
Measurement: measurement,
WarnOnMissing: warnonmissing,
FailOnMissing: failonmissing,
}
templates[0] = tmpl
m := WindowsPerformanceCounter{PrintValid: false, TestName: "ConfigError3", Template: templates}
err := m.parseConfig()
require.Error(t, err)
}
func TestWPCCollect1(t *testing.T) {
var templates = make([]template, 1)
counters := [][]string{
[]string{"park", "\\Processor Information(_Total)\\Parking Status"},
}
var measurement string = "test"
var warnonmissing bool = false
var failonmissing bool = true
tmpl := template{
Counters: counters,
Measurement: measurement,
WarnOnMissing: warnonmissing,
FailOnMissing: failonmissing,
}
templates[0] = tmpl
m := WindowsPerformanceCounter{PrintValid: false, TestName: "Collect1", Template: templates}
var acc testutil.Accumulator
err := m.Gather(&acc)
require.NoError(t, err)
time.Sleep(2000 * time.Millisecond)
err = m.Gather(&acc)
tags := map[string]string{
"instance": "_Total",
}
fields := map[string]interface{}{
"park": float32(0),
}
acc.AssertContainsTaggedFields(t, measurement, fields, tags)
}
func TestWPCCollect2(t *testing.T) {
var templates = make([]template, 1)
counters := [][]string{
[]string{"park", "\\Processor Information(_Total)\\Parking Status"},
[]string{"plim", "\\Processor Information(_Total)\\Performance Limit Flags"},
}
var measurement string = "test"
var warnonmissing bool = false
var failonmissing bool = true
tmpl := template{
Counters: counters,
Measurement: measurement,
WarnOnMissing: warnonmissing,
FailOnMissing: failonmissing,
}
templates[0] = tmpl
m := WindowsPerformanceCounter{PrintValid: false, TestName: "Collect2", Template: templates}
var acc testutil.Accumulator
err := m.Gather(&acc)
require.NoError(t, err)
time.Sleep(2000 * time.Millisecond)
err = m.Gather(&acc)
tags := map[string]string{
"instance": "_Total",
}
fields := map[string]interface{}{
"park": float32(0),
"plim": float32(0),
}
acc.AssertContainsTaggedFields(t, measurement, fields, tags)
}
func TestWPCCollect3(t *testing.T) {
var templates = make([]template, 1)
counters := [][]string{
[]string{"park", "\\Processor Information(_Total)\\Parking Status"},
[]string{"sys_cs_rate", "\\System\\Context Switches/sec"},
}
var measurement string = "test"
var warnonmissing bool = false
var failonmissing bool = true
tmpl := template{
Counters: counters,
Measurement: measurement,
WarnOnMissing: warnonmissing,
FailOnMissing: failonmissing,
}
templates[0] = tmpl
m := WindowsPerformanceCounter{PrintValid: false, TestName: "Collect3", Template: templates}
var acc testutil.Accumulator
err := m.Gather(&acc)
require.NoError(t, err)
time.Sleep(2000 * time.Millisecond)
err = m.Gather(&acc)
tags := map[string]string{
"instance": "_Total",
}
fields := map[string]interface{}{
"park": float32(0),
}
acc.AssertContainsTaggedFields(t, measurement, fields, tags)
tags = map[string]string{
"instance": "",
}
fields = map[string]interface{}{
"sys_cs_rate": float32(0),
}
acc.AssertContainsTaggedFields(t, measurement, fields, tags)
}