Add option to enable wildcard expansion (#4265)
This is needed because wildcard expansion causes counters to be localized.
(cherry picked from commit 1690f36b09
)
This commit is contained in:
parent
b4b3beb765
commit
5fe1aa1a24
|
@ -8,9 +8,6 @@ whether the Object, Instance and Counter exist on Telegraf startup.
|
||||||
Counter paths are refreshed periodically, see [CountersRefreshInterval](#countersrefreshinterval)
|
Counter paths are refreshed periodically, see [CountersRefreshInterval](#countersrefreshinterval)
|
||||||
configuration parameter for more info.
|
configuration parameter for more info.
|
||||||
|
|
||||||
Wildcards can be used in instance and counter names. Partial wildcards are supported only
|
|
||||||
in instance names on Windows Vista and newer.
|
|
||||||
|
|
||||||
In case of query for all instances `["*"]`, the plugin does not return the instance `_Total`
|
In case of query for all instances `["*"]`, the plugin does not return the instance `_Total`
|
||||||
by default. See [IncludeTotal](#includetotal) for more info.
|
by default. See [IncludeTotal](#includetotal) for more info.
|
||||||
|
|
||||||
|
@ -34,18 +31,36 @@ Bool, if set to `true` will print out all matching performance objects.
|
||||||
Example:
|
Example:
|
||||||
`PrintValid=true`
|
`PrintValid=true`
|
||||||
|
|
||||||
|
#### UseWildcardsExpansion
|
||||||
|
|
||||||
|
If `UseWildcardsExpansion` is set to true, wildcards can be used in instance name and counter name
|
||||||
|
.
|
||||||
|
Partial wildcard (e.g. `chrome*`) is supported only in instance name on Windows Vista and newer.
|
||||||
|
|
||||||
|
On localized Windows, returned counters will be also localized.
|
||||||
|
|
||||||
|
It also returns instance indexes in instance names.
|
||||||
|
|
||||||
|
If set to `false`, wildcards (not partial) in instance names can still be used, but instance indexes will not be returned in instance names.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
`UseWildcardsExpansion=true`
|
||||||
|
|
||||||
#### CountersRefreshInterval
|
#### CountersRefreshInterval
|
||||||
|
|
||||||
Configured counters are matched against available counters at the interval
|
Configured counters are matched against available counters at the interval
|
||||||
specified by the `CountersRefreshInterval` parameter. Default value is `1m` (1 minute).
|
specified by the `CountersRefreshInterval` parameter. Default value is `1m` (1 minute).
|
||||||
|
|
||||||
If wildcards are used in instance or counter names, they are expanded at this point.
|
If wildcards are used in instance or counter names, they are expanded at this point, if the `UseWildcardsExpansion` param is set to `true`.
|
||||||
|
|
||||||
Setting `CountersRefreshInterval` too low (order of seconds) can cause Telegraf to create
|
Setting `CountersRefreshInterval` too low (order of seconds) can cause Telegraf to create
|
||||||
a high CPU load.
|
a high CPU load.
|
||||||
|
|
||||||
Set to `0s` to disable periodic refreshing.
|
Set to `0s` to disable periodic refreshing.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
`CountersRefreshInterval=1m`
|
||||||
|
|
||||||
#### PreVistaSupport
|
#### PreVistaSupport
|
||||||
|
|
||||||
_Deprecated. Necessary features on Windows Vista and newer are checked dynamically_
|
_Deprecated. Necessary features on Windows Vista and newer are checked dynamically_
|
||||||
|
@ -88,7 +103,7 @@ By default any results containing `_Total` are stripped,
|
||||||
unless this is specified as the wanted instance.
|
unless this is specified as the wanted instance.
|
||||||
Alternatively see the option `IncludeTotal` below.
|
Alternatively see the option `IncludeTotal` below.
|
||||||
|
|
||||||
It is also possible to set partial wildcards, eg. `["chrome*"]`
|
It is also possible to set partial wildcards, eg. `["chrome*"]`, if the `UseWildcardsExpansion` param is set to `true`
|
||||||
|
|
||||||
Some Objects do not have instances to select from at all.
|
Some Objects do not have instances to select from at all.
|
||||||
Here only one option is valid if you want data back,
|
Here only one option is valid if you want data back,
|
||||||
|
@ -101,8 +116,8 @@ Counters key (this is an array) is the counters of the ObjectName
|
||||||
you would like returned, it can also be one or more values.
|
you would like returned, it can also be one or more values.
|
||||||
|
|
||||||
Example: `Counters = ["% Idle Time", "% Disk Read Time", "% Disk Write Time"]`
|
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, or use `["*"]` for all the counters for object,
|
||||||
or use `["*"]` for all the counters for object.
|
if the `UseWildcardsExpansion` param is set to `true`
|
||||||
|
|
||||||
#### Measurement
|
#### Measurement
|
||||||
*Optional*
|
*Optional*
|
||||||
|
|
|
@ -352,7 +352,7 @@ func PdhGetFormattedCounterValueDouble(hCounter PDH_HCOUNTER, lpdwType *uint32,
|
||||||
// time.Sleep(2000 * time.Millisecond)
|
// time.Sleep(2000 * time.Millisecond)
|
||||||
// }
|
// }
|
||||||
// }
|
// }
|
||||||
func PdhGetFormattedCounterArrayDouble(hCounter PDH_HCOUNTER, lpdwBufferSize *uint32, lpdwBufferCount *uint32, itemBuffer *PDH_FMT_COUNTERVALUE_ITEM_DOUBLE) uint32 {
|
func PdhGetFormattedCounterArrayDouble(hCounter PDH_HCOUNTER, lpdwBufferSize *uint32, lpdwBufferCount *uint32, itemBuffer *byte) uint32 {
|
||||||
ret, _, _ := pdh_GetFormattedCounterArrayW.Call(
|
ret, _, _ := pdh_GetFormattedCounterArrayW.Call(
|
||||||
uintptr(hCounter),
|
uintptr(hCounter),
|
||||||
uintptr(PDH_FMT_DOUBLE|PDH_FMT_NOCAP100),
|
uintptr(PDH_FMT_DOUBLE|PDH_FMT_NOCAP100),
|
||||||
|
|
|
@ -9,6 +9,12 @@ import (
|
||||||
"unsafe"
|
"unsafe"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
//PerformanceQuery is abstraction for PDH_FMT_COUNTERVALUE_ITEM_DOUBLE
|
||||||
|
type CounterValue struct {
|
||||||
|
InstanceName string
|
||||||
|
Value float64
|
||||||
|
}
|
||||||
|
|
||||||
//PerformanceQuery provides wrappers around Windows performance counters API for easy usage in GO
|
//PerformanceQuery provides wrappers around Windows performance counters API for easy usage in GO
|
||||||
type PerformanceQuery interface {
|
type PerformanceQuery interface {
|
||||||
Open() error
|
Open() error
|
||||||
|
@ -18,6 +24,7 @@ type PerformanceQuery interface {
|
||||||
GetCounterPath(counterHandle PDH_HCOUNTER) (string, error)
|
GetCounterPath(counterHandle PDH_HCOUNTER) (string, error)
|
||||||
ExpandWildCardPath(counterPath string) ([]string, error)
|
ExpandWildCardPath(counterPath string) ([]string, error)
|
||||||
GetFormattedCounterValueDouble(hCounter PDH_HCOUNTER) (float64, error)
|
GetFormattedCounterValueDouble(hCounter PDH_HCOUNTER) (float64, error)
|
||||||
|
GetFormattedCounterArrayDouble(hCounter PDH_HCOUNTER) ([]CounterValue, error)
|
||||||
CollectData() error
|
CollectData() error
|
||||||
AddEnglishCounterSupported() bool
|
AddEnglishCounterSupported() bool
|
||||||
}
|
}
|
||||||
|
@ -151,6 +158,28 @@ func (m *PerformanceQueryImpl) GetFormattedCounterValueDouble(hCounter PDH_HCOUN
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (m *PerformanceQueryImpl) GetFormattedCounterArrayDouble(hCounter PDH_HCOUNTER) ([]CounterValue, error) {
|
||||||
|
var buffSize uint32
|
||||||
|
var itemCount uint32
|
||||||
|
ret := PdhGetFormattedCounterArrayDouble(hCounter, &buffSize, &itemCount, nil)
|
||||||
|
if ret == PDH_MORE_DATA {
|
||||||
|
buff := make([]byte, buffSize)
|
||||||
|
ret = PdhGetFormattedCounterArrayDouble(hCounter, &buffSize, &itemCount, &buff[0])
|
||||||
|
if ret == ERROR_SUCCESS {
|
||||||
|
items := (*[1 << 20]PDH_FMT_COUNTERVALUE_ITEM_DOUBLE)(unsafe.Pointer(&buff[0]))[:itemCount]
|
||||||
|
values := make([]CounterValue, 0, itemCount)
|
||||||
|
for _, item := range items {
|
||||||
|
if item.FmtValue.CStatus == PDH_CSTATUS_VALID_DATA || item.FmtValue.CStatus == PDH_CSTATUS_NEW_DATA {
|
||||||
|
val := CounterValue{UTF16PtrToString(item.SzName), item.FmtValue.DoubleValue}
|
||||||
|
values = append(values, val)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return values, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil, NewPdhError(ret)
|
||||||
|
}
|
||||||
|
|
||||||
func (m *PerformanceQueryImpl) CollectData() error {
|
func (m *PerformanceQueryImpl) CollectData() error {
|
||||||
if m.query == 0 {
|
if m.query == 0 {
|
||||||
return errors.New("uninitialised query")
|
return errors.New("uninitialised query")
|
||||||
|
|
|
@ -22,6 +22,10 @@ var sampleConfig = `
|
||||||
## agent, it will not be gathered.
|
## agent, it will not be gathered.
|
||||||
## Settings:
|
## Settings:
|
||||||
# PrintValid = false # Print All matching performance counters
|
# PrintValid = false # Print All matching performance counters
|
||||||
|
# If UseWildcardsExpansion params is set to true, wildcards (partial wildcards in instance names and wildcards in counters names) in configured counter paths will be expanded
|
||||||
|
# and in case of localized Windows, counter paths will be also localized. It also returns instance indexes in instance names.
|
||||||
|
# If false, wildcards (not partial) in instance names will be still expanded, but instance indexes will not be returned in instance names.
|
||||||
|
#UseWildcardsExpansion = false
|
||||||
# Period after which counters will be reread from configuration and wildcards in counter paths expanded
|
# Period after which counters will be reread from configuration and wildcards in counter paths expanded
|
||||||
CountersRefreshInterval="1m"
|
CountersRefreshInterval="1m"
|
||||||
|
|
||||||
|
@ -75,6 +79,7 @@ type Win_PerfCounters struct {
|
||||||
PreVistaSupport bool
|
PreVistaSupport bool
|
||||||
Object []perfobject
|
Object []perfobject
|
||||||
CountersRefreshInterval internal.Duration
|
CountersRefreshInterval internal.Duration
|
||||||
|
UseWildcardsExpansion bool
|
||||||
|
|
||||||
lastRefreshed time.Time
|
lastRefreshed time.Time
|
||||||
counters []*counter
|
counters []*counter
|
||||||
|
@ -137,45 +142,59 @@ func (m *Win_PerfCounters) SampleConfig() string {
|
||||||
return sampleConfig
|
return sampleConfig
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *Win_PerfCounters) AddItem(counterPath string, instance string, measurement string, includeTotal bool) error {
|
//objectName string, counter string, instance string, measurement string, include_total bool
|
||||||
|
func (m *Win_PerfCounters) AddItem(counterPath string, objectName string, instance string, counterName string, measurement string, includeTotal bool) error {
|
||||||
|
var err error
|
||||||
|
var counterHandle PDH_HCOUNTER
|
||||||
if !m.query.AddEnglishCounterSupported() {
|
if !m.query.AddEnglishCounterSupported() {
|
||||||
_, err := m.query.AddCounterToQuery(counterPath)
|
counterHandle, err = m.query.AddCounterToQuery(counterPath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
counterHandle, err := m.query.AddEnglishCounterToQuery(counterPath)
|
counterHandle, err = m.query.AddEnglishCounterToQuery(counterPath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
if m.UseWildcardsExpansion {
|
||||||
|
origInstance := instance
|
||||||
counterPath, err = m.query.GetCounterPath(counterHandle)
|
counterPath, err = m.query.GetCounterPath(counterHandle)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
counters, err := m.query.ExpandWildCardPath(counterPath)
|
||||||
|
|
||||||
counters, err := m.query.ExpandWildCardPath(counterPath)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, counterPath := range counters {
|
|
||||||
var err error
|
|
||||||
counterHandle, err := m.query.AddCounterToQuery(counterPath)
|
|
||||||
|
|
||||||
parsedObjectName, parsedInstance, parsedCounter, err := extractObjectInstanceCounterFromQuery(counterPath)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
if parsedInstance == "_Total" && instance == "*" && !includeTotal {
|
for _, counterPath := range counters {
|
||||||
continue
|
var err error
|
||||||
}
|
counterHandle, err := m.query.AddCounterToQuery(counterPath)
|
||||||
|
|
||||||
newItem := &counter{counterPath, parsedObjectName, parsedCounter, parsedInstance, measurement,
|
objectName, instance, counterName, err = extractObjectInstanceCounterFromQuery(counterPath)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if instance == "_Total" && origInstance == "*" && !includeTotal {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
newItem := &counter{counterPath, objectName, counterName, instance, measurement,
|
||||||
|
includeTotal, counterHandle}
|
||||||
|
m.counters = append(m.counters, newItem)
|
||||||
|
|
||||||
|
if m.PrintValid {
|
||||||
|
log.Printf("Valid: %s\n", counterPath)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
newItem := &counter{counterPath, objectName, counterName, instance, measurement,
|
||||||
includeTotal, counterHandle}
|
includeTotal, counterHandle}
|
||||||
m.counters = append(m.counters, newItem)
|
m.counters = append(m.counters, newItem)
|
||||||
|
|
||||||
if m.PrintValid {
|
if m.PrintValid {
|
||||||
log.Printf("Valid: %s\n", counterPath)
|
log.Printf("Valid: %s\n", counterPath)
|
||||||
}
|
}
|
||||||
|
@ -199,7 +218,7 @@ func (m *Win_PerfCounters) ParseConfig() error {
|
||||||
counterPath = "\\" + objectname + "(" + instance + ")\\" + counter
|
counterPath = "\\" + objectname + "(" + instance + ")\\" + counter
|
||||||
}
|
}
|
||||||
|
|
||||||
err := m.AddItem(counterPath, instance, PerfObject.Measurement, PerfObject.IncludeTotal)
|
err := m.AddItem(counterPath, objectname, instance, counter, PerfObject.Measurement, PerfObject.IncludeTotal)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if PerfObject.FailOnMissing || PerfObject.WarnOnMissing {
|
if PerfObject.FailOnMissing || PerfObject.WarnOnMissing {
|
||||||
|
@ -225,7 +244,9 @@ func (m *Win_PerfCounters) Gather(acc telegraf.Accumulator) error {
|
||||||
var err error
|
var err error
|
||||||
|
|
||||||
if m.lastRefreshed.IsZero() || (m.CountersRefreshInterval.Duration.Nanoseconds() > 0 && m.lastRefreshed.Add(m.CountersRefreshInterval.Duration).Before(time.Now())) {
|
if m.lastRefreshed.IsZero() || (m.CountersRefreshInterval.Duration.Nanoseconds() > 0 && m.lastRefreshed.Add(m.CountersRefreshInterval.Duration).Before(time.Now())) {
|
||||||
m.counters = m.counters[:0]
|
if m.counters != nil {
|
||||||
|
m.counters = m.counters[:0]
|
||||||
|
}
|
||||||
|
|
||||||
err = m.query.Open()
|
err = m.query.Open()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -261,22 +282,61 @@ 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 m.counters {
|
for _, metric := range m.counters {
|
||||||
// collect
|
// collect
|
||||||
value, err := m.query.GetFormattedCounterValueDouble(metric.counterHandle)
|
if m.UseWildcardsExpansion {
|
||||||
if err == nil {
|
value, err := m.query.GetFormattedCounterValueDouble(metric.counterHandle)
|
||||||
measurement := sanitizedChars.Replace(metric.measurement)
|
if err == nil {
|
||||||
if measurement == "" {
|
measurement := sanitizedChars.Replace(metric.measurement)
|
||||||
measurement = "win_perf_counters"
|
if measurement == "" {
|
||||||
}
|
measurement = "win_perf_counters"
|
||||||
|
}
|
||||||
|
|
||||||
var instance = InstanceGrouping{measurement, metric.instance, metric.objectName}
|
var instance = InstanceGrouping{measurement, metric.instance, metric.objectName}
|
||||||
if collectFields[instance] == nil {
|
if collectFields[instance] == nil {
|
||||||
collectFields[instance] = make(map[string]interface{})
|
collectFields[instance] = make(map[string]interface{})
|
||||||
|
}
|
||||||
|
collectFields[instance][sanitizedChars.Replace(metric.counter)] = float32(value)
|
||||||
|
} else {
|
||||||
|
//ignore invalid data from as some counters from process instances returns this sometimes
|
||||||
|
if phderr, ok := err.(*PdhError); ok && phderr.ErrorCode != PDH_INVALID_DATA && phderr.ErrorCode != PDH_CALC_NEGATIVE_VALUE {
|
||||||
|
return fmt.Errorf("error while getting value for counter %s: %v", metric.counterPath, err)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
collectFields[instance][sanitizedChars.Replace(metric.counter)] = float32(value)
|
|
||||||
} else {
|
} else {
|
||||||
//ignore invalid data from as some counters from process instances returns this sometimes
|
counterValues, err := m.query.GetFormattedCounterArrayDouble(metric.counterHandle)
|
||||||
if phderr, ok := err.(*PdhError); ok && phderr.ErrorCode != PDH_INVALID_DATA && phderr.ErrorCode != PDH_CALC_NEGATIVE_VALUE {
|
if err == nil {
|
||||||
return fmt.Errorf("error while getting value for counter %s: %v", metric.counterPath, err)
|
for _, cValue := range counterValues {
|
||||||
|
var add bool
|
||||||
|
if metric.includeTotal {
|
||||||
|
// If IncludeTotal is set, include all.
|
||||||
|
add = true
|
||||||
|
} else if metric.instance == "*" && !strings.Contains(cValue.InstanceName, "_Total") {
|
||||||
|
// Catch if set to * and that it is not a '*_Total*' instance.
|
||||||
|
add = true
|
||||||
|
} else if metric.instance == cValue.InstanceName {
|
||||||
|
// Catch if we set it to total or some form of it
|
||||||
|
add = true
|
||||||
|
} else if strings.Contains(metric.instance, "#") && strings.HasPrefix(metric.instance, cValue.InstanceName) {
|
||||||
|
// If you are using a multiple instance identifier such as "w3wp#1"
|
||||||
|
// phd.dll returns only the first 2 characters of the identifier.
|
||||||
|
add = true
|
||||||
|
cValue.InstanceName = metric.instance
|
||||||
|
} else if metric.instance == "------" {
|
||||||
|
add = true
|
||||||
|
}
|
||||||
|
|
||||||
|
if add {
|
||||||
|
measurement := sanitizedChars.Replace(metric.measurement)
|
||||||
|
if measurement == "" {
|
||||||
|
measurement = "win_perf_counters"
|
||||||
|
}
|
||||||
|
var instance = InstanceGrouping{measurement, cValue.InstanceName, metric.objectName}
|
||||||
|
|
||||||
|
if collectFields[instance] == nil {
|
||||||
|
collectFields[instance] = make(map[string]interface{})
|
||||||
|
}
|
||||||
|
collectFields[instance][sanitizedChars.Replace(metric.counter)] = float32(cValue.Value)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -81,6 +81,29 @@ func TestWinPerformanceQueryImpl(t *testing.T) {
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
require.NotNil(t, paths)
|
require.NotNil(t, paths)
|
||||||
assert.True(t, len(paths) > 1)
|
assert.True(t, len(paths) > 1)
|
||||||
|
|
||||||
|
err = query.Open()
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
counterPath = "\\Process(*)\\% Processor Time"
|
||||||
|
hCounter, err = query.AddEnglishCounterToQuery(counterPath)
|
||||||
|
require.NoError(t, err)
|
||||||
|
assert.NotEqual(t, 0, hCounter)
|
||||||
|
|
||||||
|
err = query.CollectData()
|
||||||
|
require.NoError(t, err)
|
||||||
|
time.Sleep(time.Second)
|
||||||
|
|
||||||
|
err = query.CollectData()
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
arr, err := query.GetFormattedCounterArrayDouble(hCounter)
|
||||||
|
require.NoError(t, err)
|
||||||
|
assert.True(t, len(arr) > 0, "Too")
|
||||||
|
|
||||||
|
err = query.Close()
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestWinPerfcountersConfigGet1(t *testing.T) {
|
func TestWinPerfcountersConfigGet1(t *testing.T) {
|
||||||
|
@ -573,7 +596,7 @@ func TestWinPerfcountersCollect2(t *testing.T) {
|
||||||
|
|
||||||
perfobjects[0] = PerfObject
|
perfobjects[0] = PerfObject
|
||||||
|
|
||||||
m := Win_PerfCounters{PrintValid: false, Object: perfobjects, query: &PerformanceQueryImpl{}}
|
m := Win_PerfCounters{PrintValid: false, Object: perfobjects, query: &PerformanceQueryImpl{}, UseWildcardsExpansion: true}
|
||||||
var acc testutil.Accumulator
|
var acc testutil.Accumulator
|
||||||
err := m.Gather(&acc)
|
err := m.Gather(&acc)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
|
@ -25,6 +25,14 @@ type FakePerformanceQuery struct {
|
||||||
openCalled bool
|
openCalled bool
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (m *testCounter) ToCounterValue() *CounterValue {
|
||||||
|
_, inst, _, _ := extractObjectInstanceCounterFromQuery(m.path)
|
||||||
|
if inst == "" {
|
||||||
|
inst = "--"
|
||||||
|
}
|
||||||
|
return &CounterValue{inst, m.value}
|
||||||
|
}
|
||||||
|
|
||||||
func (m *FakePerformanceQuery) Open() error {
|
func (m *FakePerformanceQuery) Open() error {
|
||||||
if m.openCalled {
|
if m.openCalled {
|
||||||
err := m.Close()
|
err := m.Close()
|
||||||
|
@ -102,6 +110,48 @@ func (m *FakePerformanceQuery) GetFormattedCounterValueDouble(counterHandle PDH_
|
||||||
}
|
}
|
||||||
return 0, fmt.Errorf("GetFormattedCounterValueDouble: invalid handle: %d", counterHandle)
|
return 0, fmt.Errorf("GetFormattedCounterValueDouble: invalid handle: %d", counterHandle)
|
||||||
}
|
}
|
||||||
|
func (m *FakePerformanceQuery) findCounterByPath(counterPath string) *testCounter {
|
||||||
|
for _, c := range m.counters {
|
||||||
|
if c.path == counterPath {
|
||||||
|
return &c
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *FakePerformanceQuery) findCounterByHandle(counterHandle PDH_HCOUNTER) *testCounter {
|
||||||
|
for _, c := range m.counters {
|
||||||
|
if c.handle == counterHandle {
|
||||||
|
return &c
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *FakePerformanceQuery) GetFormattedCounterArrayDouble(hCounter PDH_HCOUNTER) ([]CounterValue, error) {
|
||||||
|
if !m.openCalled {
|
||||||
|
return nil, errors.New("GetFormattedCounterArrayDouble: uninitialised query")
|
||||||
|
}
|
||||||
|
for _, c := range m.counters {
|
||||||
|
if c.handle == hCounter {
|
||||||
|
if e, ok := m.expandPaths[c.path]; ok {
|
||||||
|
counters := make([]CounterValue, 0, len(e))
|
||||||
|
for _, p := range e {
|
||||||
|
counter := m.findCounterByPath(p)
|
||||||
|
if counter != nil && counter.value > 0 {
|
||||||
|
counters = append(counters, *counter.ToCounterValue())
|
||||||
|
} else {
|
||||||
|
return nil, fmt.Errorf("GetFormattedCounterArrayDouble: invalid counter : %s", p)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return counters, nil
|
||||||
|
} else {
|
||||||
|
return nil, fmt.Errorf("GetFormattedCounterArrayDouble: invalid counter : %d", hCounter)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil, fmt.Errorf("GetFormattedCounterArrayDouble: invalid counter : %d, no paths found", hCounter)
|
||||||
|
}
|
||||||
|
|
||||||
func (m *FakePerformanceQuery) CollectData() error {
|
func (m *FakePerformanceQuery) CollectData() error {
|
||||||
if !m.openCalled {
|
if !m.openCalled {
|
||||||
|
@ -152,7 +202,7 @@ func TestAddItemSimple(t *testing.T) {
|
||||||
}}
|
}}
|
||||||
err = m.query.Open()
|
err = m.query.Open()
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
err = m.AddItem(cps1[0], "I", "test", false)
|
err = m.AddItem(cps1[0], "O", "I", "c", "test", false)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
err = m.query.Close()
|
err = m.query.Close()
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
@ -161,7 +211,7 @@ func TestAddItemSimple(t *testing.T) {
|
||||||
func TestAddItemInvalidCountPath(t *testing.T) {
|
func TestAddItemInvalidCountPath(t *testing.T) {
|
||||||
var err error
|
var err error
|
||||||
cps1 := []string{"\\O\\C"}
|
cps1 := []string{"\\O\\C"}
|
||||||
m := Win_PerfCounters{PrintValid: false, Object: nil, query: &FakePerformanceQuery{
|
m := Win_PerfCounters{PrintValid: false, Object: nil, UseWildcardsExpansion: true, query: &FakePerformanceQuery{
|
||||||
counters: createCounterMap(cps1, []float64{1.1}),
|
counters: createCounterMap(cps1, []float64{1.1}),
|
||||||
expandPaths: map[string][]string{
|
expandPaths: map[string][]string{
|
||||||
cps1[0]: {"\\O/C"},
|
cps1[0]: {"\\O/C"},
|
||||||
|
@ -170,7 +220,7 @@ func TestAddItemInvalidCountPath(t *testing.T) {
|
||||||
}}
|
}}
|
||||||
err = m.query.Open()
|
err = m.query.Open()
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
err = m.AddItem("\\O\\C", "*", "test", false)
|
err = m.AddItem("\\O\\C", "O", "------", "C", "test", false)
|
||||||
require.Error(t, err)
|
require.Error(t, err)
|
||||||
err = m.query.Close()
|
err = m.query.Close()
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
@ -197,13 +247,24 @@ func TestParseConfigBasic(t *testing.T) {
|
||||||
assert.Len(t, m.counters, 4)
|
assert.Len(t, m.counters, 4)
|
||||||
err = m.query.Close()
|
err = m.query.Close()
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
m.UseWildcardsExpansion = true
|
||||||
|
m.counters = nil
|
||||||
|
|
||||||
|
err = m.query.Open()
|
||||||
|
require.NoError(t, err)
|
||||||
|
err = m.ParseConfig()
|
||||||
|
require.NoError(t, err)
|
||||||
|
assert.Len(t, m.counters, 4)
|
||||||
|
err = m.query.Close()
|
||||||
|
require.NoError(t, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestParseConfigNoInstance(t *testing.T) {
|
func TestParseConfigNoInstance(t *testing.T) {
|
||||||
var err error
|
var err error
|
||||||
perfObjects := createPerfObject("m", "O", []string{"------"}, []string{"C1", "C2"}, false, false)
|
perfObjects := createPerfObject("m", "O", []string{"------"}, []string{"C1", "C2"}, false, false)
|
||||||
cps1 := []string{"\\O\\C1", "\\O\\C2"}
|
cps1 := []string{"\\O\\C1", "\\O\\C2"}
|
||||||
m := Win_PerfCounters{PrintValid: false, Object: perfObjects, query: &FakePerformanceQuery{
|
m := Win_PerfCounters{PrintValid: false, Object: perfObjects, UseWildcardsExpansion: false, query: &FakePerformanceQuery{
|
||||||
counters: createCounterMap(cps1, []float64{1.1, 1.2}),
|
counters: createCounterMap(cps1, []float64{1.1, 1.2}),
|
||||||
expandPaths: map[string][]string{
|
expandPaths: map[string][]string{
|
||||||
cps1[0]: {cps1[0]},
|
cps1[0]: {cps1[0]},
|
||||||
|
@ -218,6 +279,17 @@ func TestParseConfigNoInstance(t *testing.T) {
|
||||||
assert.Len(t, m.counters, 2)
|
assert.Len(t, m.counters, 2)
|
||||||
err = m.query.Close()
|
err = m.query.Close()
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
m.UseWildcardsExpansion = true
|
||||||
|
m.counters = nil
|
||||||
|
|
||||||
|
err = m.query.Open()
|
||||||
|
require.NoError(t, err)
|
||||||
|
err = m.ParseConfig()
|
||||||
|
require.NoError(t, err)
|
||||||
|
assert.Len(t, m.counters, 2)
|
||||||
|
err = m.query.Close()
|
||||||
|
require.NoError(t, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestParseConfigInvalidCounterError(t *testing.T) {
|
func TestParseConfigInvalidCounterError(t *testing.T) {
|
||||||
|
@ -239,6 +311,16 @@ func TestParseConfigInvalidCounterError(t *testing.T) {
|
||||||
require.Error(t, err)
|
require.Error(t, err)
|
||||||
err = m.query.Close()
|
err = m.query.Close()
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
m.UseWildcardsExpansion = true
|
||||||
|
m.counters = nil
|
||||||
|
|
||||||
|
err = m.query.Open()
|
||||||
|
require.NoError(t, err)
|
||||||
|
err = m.ParseConfig()
|
||||||
|
require.Error(t, err)
|
||||||
|
err = m.query.Close()
|
||||||
|
require.NoError(t, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestParseConfigInvalidCounterNoError(t *testing.T) {
|
func TestParseConfigInvalidCounterNoError(t *testing.T) {
|
||||||
|
@ -260,13 +342,24 @@ func TestParseConfigInvalidCounterNoError(t *testing.T) {
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
err = m.query.Close()
|
err = m.query.Close()
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
m.UseWildcardsExpansion = true
|
||||||
|
m.counters = nil
|
||||||
|
|
||||||
|
err = m.query.Open()
|
||||||
|
require.NoError(t, err)
|
||||||
|
err = m.ParseConfig()
|
||||||
|
require.NoError(t, err)
|
||||||
|
err = m.query.Close()
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestParseConfigTotal(t *testing.T) {
|
func TestParseConfigTotalExpansion(t *testing.T) {
|
||||||
var err error
|
var err error
|
||||||
perfObjects := createPerfObject("m", "O", []string{"*"}, []string{"*"}, true, true)
|
perfObjects := createPerfObject("m", "O", []string{"*"}, []string{"*"}, true, true)
|
||||||
cps1 := []string{"\\O(I1)\\C1", "\\O(I1)\\C2", "\\O(_Total)\\C1", "\\O(_Total)\\C2"}
|
cps1 := []string{"\\O(I1)\\C1", "\\O(I1)\\C2", "\\O(_Total)\\C1", "\\O(_Total)\\C2"}
|
||||||
m := Win_PerfCounters{PrintValid: false, Object: perfObjects, query: &FakePerformanceQuery{
|
m := Win_PerfCounters{PrintValid: false, UseWildcardsExpansion: true, Object: perfObjects, query: &FakePerformanceQuery{
|
||||||
counters: createCounterMap(append(cps1, "\\O(*)\\*"), []float64{1.1, 1.2, 1.3, 1.4, 0}),
|
counters: createCounterMap(append(cps1, "\\O(*)\\*"), []float64{1.1, 1.2, 1.3, 1.4, 0}),
|
||||||
expandPaths: map[string][]string{
|
expandPaths: map[string][]string{
|
||||||
"\\O(*)\\*": cps1,
|
"\\O(*)\\*": cps1,
|
||||||
|
@ -283,7 +376,7 @@ func TestParseConfigTotal(t *testing.T) {
|
||||||
|
|
||||||
perfObjects[0].IncludeTotal = false
|
perfObjects[0].IncludeTotal = false
|
||||||
|
|
||||||
m = Win_PerfCounters{PrintValid: false, Object: perfObjects, query: &FakePerformanceQuery{
|
m = Win_PerfCounters{PrintValid: false, UseWildcardsExpansion: true, Object: perfObjects, query: &FakePerformanceQuery{
|
||||||
counters: createCounterMap(append(cps1, "\\O(*)\\*"), []float64{1.1, 1.2, 1.3, 1.4, 0}),
|
counters: createCounterMap(append(cps1, "\\O(*)\\*"), []float64{1.1, 1.2, 1.3, 1.4, 0}),
|
||||||
expandPaths: map[string][]string{
|
expandPaths: map[string][]string{
|
||||||
"\\O(*)\\*": cps1,
|
"\\O(*)\\*": cps1,
|
||||||
|
@ -303,7 +396,7 @@ func TestParseConfigExpand(t *testing.T) {
|
||||||
var err error
|
var err error
|
||||||
perfObjects := createPerfObject("m", "O", []string{"*"}, []string{"*"}, false, false)
|
perfObjects := createPerfObject("m", "O", []string{"*"}, []string{"*"}, false, false)
|
||||||
cps1 := []string{"\\O(I1)\\C1", "\\O(I1)\\C2", "\\O(I2)\\C1", "\\O(I2)\\C2"}
|
cps1 := []string{"\\O(I1)\\C1", "\\O(I1)\\C2", "\\O(I2)\\C1", "\\O(I2)\\C2"}
|
||||||
m := Win_PerfCounters{PrintValid: false, Object: perfObjects, query: &FakePerformanceQuery{
|
m := Win_PerfCounters{PrintValid: false, UseWildcardsExpansion: true, Object: perfObjects, query: &FakePerformanceQuery{
|
||||||
counters: createCounterMap(append(cps1, "\\O(*)\\*"), []float64{1.1, 1.2, 1.3, 1.4, 0}),
|
counters: createCounterMap(append(cps1, "\\O(*)\\*"), []float64{1.1, 1.2, 1.3, 1.4, 0}),
|
||||||
expandPaths: map[string][]string{
|
expandPaths: map[string][]string{
|
||||||
"\\O(*)\\*": cps1,
|
"\\O(*)\\*": cps1,
|
||||||
|
@ -346,6 +439,17 @@ func TestSimpleGather(t *testing.T) {
|
||||||
"objectname": "O",
|
"objectname": "O",
|
||||||
}
|
}
|
||||||
acc1.AssertContainsTaggedFields(t, measurement, fields1, tags1)
|
acc1.AssertContainsTaggedFields(t, measurement, fields1, tags1)
|
||||||
|
|
||||||
|
m.UseWildcardsExpansion = true
|
||||||
|
m.counters = nil
|
||||||
|
m.lastRefreshed = time.Time{}
|
||||||
|
|
||||||
|
var acc2 testutil.Accumulator
|
||||||
|
|
||||||
|
err = m.Gather(&acc2)
|
||||||
|
require.NoError(t, err)
|
||||||
|
acc1.AssertContainsTaggedFields(t, measurement, fields1, tags1)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestGatherInvalidDataIgnore(t *testing.T) {
|
func TestGatherInvalidDataIgnore(t *testing.T) {
|
||||||
|
@ -377,15 +481,25 @@ func TestGatherInvalidDataIgnore(t *testing.T) {
|
||||||
"objectname": "O",
|
"objectname": "O",
|
||||||
}
|
}
|
||||||
acc1.AssertContainsTaggedFields(t, measurement, fields1, tags1)
|
acc1.AssertContainsTaggedFields(t, measurement, fields1, tags1)
|
||||||
|
|
||||||
|
m.UseWildcardsExpansion = true
|
||||||
|
m.counters = nil
|
||||||
|
m.lastRefreshed = time.Time{}
|
||||||
|
|
||||||
|
var acc2 testutil.Accumulator
|
||||||
|
err = m.Gather(&acc2)
|
||||||
|
require.NoError(t, err)
|
||||||
|
acc1.AssertContainsTaggedFields(t, measurement, fields1, tags1)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestGatherRefreshing(t *testing.T) {
|
//tests with expansion
|
||||||
|
func TestGatherRefreshingWithExpansion(t *testing.T) {
|
||||||
var err error
|
var err error
|
||||||
if testing.Short() {
|
if testing.Short() {
|
||||||
t.Skip("Skipping long taking test in short mode")
|
t.Skip("Skipping long taking test in short mode")
|
||||||
}
|
}
|
||||||
measurement := "test"
|
measurement := "test"
|
||||||
perfObjects := createPerfObject(measurement, "O", []string{"*"}, []string{"*"}, false, false)
|
perfObjects := createPerfObject(measurement, "O", []string{"*"}, []string{"*"}, true, false)
|
||||||
cps1 := []string{"\\O(I1)\\C1", "\\O(I1)\\C2", "\\O(I2)\\C1", "\\O(I2)\\C2"}
|
cps1 := []string{"\\O(I1)\\C1", "\\O(I1)\\C2", "\\O(I2)\\C1", "\\O(I2)\\C2"}
|
||||||
fpm := &FakePerformanceQuery{
|
fpm := &FakePerformanceQuery{
|
||||||
counters: createCounterMap(append(cps1, "\\O(*)\\*"), []float64{1.1, 1.2, 1.3, 1.4, 0}),
|
counters: createCounterMap(append(cps1, "\\O(*)\\*"), []float64{1.1, 1.2, 1.3, 1.4, 0}),
|
||||||
|
@ -394,7 +508,7 @@ func TestGatherRefreshing(t *testing.T) {
|
||||||
},
|
},
|
||||||
addEnglishSupported: true,
|
addEnglishSupported: true,
|
||||||
}
|
}
|
||||||
m := Win_PerfCounters{PrintValid: false, Object: perfObjects, query: fpm, CountersRefreshInterval: internal.Duration{Duration: time.Second * 10}}
|
m := Win_PerfCounters{PrintValid: false, Object: perfObjects, UseWildcardsExpansion: true, query: fpm, CountersRefreshInterval: internal.Duration{Duration: time.Second * 10}}
|
||||||
var acc1 testutil.Accumulator
|
var acc1 testutil.Accumulator
|
||||||
err = m.Gather(&acc1)
|
err = m.Gather(&acc1)
|
||||||
assert.Len(t, m.counters, 4)
|
assert.Len(t, m.counters, 4)
|
||||||
|
@ -464,6 +578,181 @@ func TestGatherRefreshing(t *testing.T) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestGatherRefreshingWithoutExpansion(t *testing.T) {
|
||||||
|
var err error
|
||||||
|
if testing.Short() {
|
||||||
|
t.Skip("Skipping long taking test in short mode")
|
||||||
|
}
|
||||||
|
measurement := "test"
|
||||||
|
perfObjects := createPerfObject(measurement, "O", []string{"*"}, []string{"C1", "C2"}, true, false)
|
||||||
|
cps1 := []string{"\\O(I1)\\C1", "\\O(I1)\\C2", "\\O(I2)\\C1", "\\O(I2)\\C2"}
|
||||||
|
fpm := &FakePerformanceQuery{
|
||||||
|
counters: createCounterMap(append([]string{"\\O(*)\\C1", "\\O(*)\\C2"}, cps1...), []float64{0, 0, 1.1, 1.2, 1.3, 1.4}),
|
||||||
|
expandPaths: map[string][]string{
|
||||||
|
"\\O(*)\\C1": {cps1[0], cps1[2]},
|
||||||
|
"\\O(*)\\C2": {cps1[1], cps1[3]},
|
||||||
|
},
|
||||||
|
addEnglishSupported: true,
|
||||||
|
}
|
||||||
|
m := Win_PerfCounters{PrintValid: false, Object: perfObjects, UseWildcardsExpansion: false, query: fpm, CountersRefreshInterval: internal.Duration{Duration: time.Second * 10}}
|
||||||
|
var acc1 testutil.Accumulator
|
||||||
|
err = m.Gather(&acc1)
|
||||||
|
assert.Len(t, m.counters, 2)
|
||||||
|
require.NoError(t, err)
|
||||||
|
assert.Len(t, acc1.Metrics, 2)
|
||||||
|
|
||||||
|
fields1 := map[string]interface{}{
|
||||||
|
"C1": float32(1.1),
|
||||||
|
"C2": float32(1.2),
|
||||||
|
}
|
||||||
|
tags1 := map[string]string{
|
||||||
|
"instance": "I1",
|
||||||
|
"objectname": "O",
|
||||||
|
}
|
||||||
|
acc1.AssertContainsTaggedFields(t, measurement, fields1, tags1)
|
||||||
|
|
||||||
|
fields2 := map[string]interface{}{
|
||||||
|
"C1": float32(1.3),
|
||||||
|
"C2": float32(1.4),
|
||||||
|
}
|
||||||
|
tags2 := map[string]string{
|
||||||
|
"instance": "I2",
|
||||||
|
"objectname": "O",
|
||||||
|
}
|
||||||
|
acc1.AssertContainsTaggedFields(t, measurement, fields2, tags2)
|
||||||
|
//test finding new instance
|
||||||
|
cps2 := []string{"\\O(I1)\\C1", "\\O(I1)\\C2", "\\O(I2)\\C1", "\\O(I2)\\C2", "\\O(I3)\\C1", "\\O(I3)\\C2"}
|
||||||
|
fpm = &FakePerformanceQuery{
|
||||||
|
counters: createCounterMap(append([]string{"\\O(*)\\C1", "\\O(*)\\C2"}, cps2...), []float64{0, 0, 1.1, 1.2, 1.3, 1.4, 1.5, 1.6}),
|
||||||
|
expandPaths: map[string][]string{
|
||||||
|
"\\O(*)\\C1": {cps2[0], cps2[2], cps2[4]},
|
||||||
|
"\\O(*)\\C2": {cps2[1], cps2[3], cps2[5]},
|
||||||
|
},
|
||||||
|
addEnglishSupported: true,
|
||||||
|
}
|
||||||
|
m.query = fpm
|
||||||
|
fpm.Open()
|
||||||
|
var acc2 testutil.Accumulator
|
||||||
|
|
||||||
|
fields3 := map[string]interface{}{
|
||||||
|
"C1": float32(1.5),
|
||||||
|
"C2": float32(1.6),
|
||||||
|
}
|
||||||
|
tags3 := map[string]string{
|
||||||
|
"instance": "I3",
|
||||||
|
"objectname": "O",
|
||||||
|
}
|
||||||
|
|
||||||
|
//test before elapsing CounterRefreshRate counters are not refreshed
|
||||||
|
err = m.Gather(&acc2)
|
||||||
|
require.NoError(t, err)
|
||||||
|
assert.Len(t, m.counters, 2)
|
||||||
|
assert.Len(t, acc2.Metrics, 3)
|
||||||
|
|
||||||
|
acc2.AssertContainsTaggedFields(t, measurement, fields1, tags1)
|
||||||
|
acc2.AssertContainsTaggedFields(t, measurement, fields2, tags2)
|
||||||
|
acc2.AssertContainsTaggedFields(t, measurement, fields3, tags3)
|
||||||
|
//test changed configuration
|
||||||
|
perfObjects = createPerfObject(measurement, "O", []string{"*"}, []string{"C1", "C2", "C3"}, true, false)
|
||||||
|
cps3 := []string{"\\O(I1)\\C1", "\\O(I1)\\C2", "\\O(I1)\\C3", "\\O(I2)\\C1", "\\O(I2)\\C2", "\\O(I2)\\C3"}
|
||||||
|
fpm = &FakePerformanceQuery{
|
||||||
|
counters: createCounterMap(append([]string{"\\O(*)\\C1", "\\O(*)\\C2", "\\O(*)\\C3"}, cps3...), []float64{0, 0, 0, 1.1, 1.2, 1.3, 1.4, 1.5, 1.6}),
|
||||||
|
expandPaths: map[string][]string{
|
||||||
|
"\\O(*)\\C1": {cps3[0], cps3[3]},
|
||||||
|
"\\O(*)\\C2": {cps3[1], cps3[4]},
|
||||||
|
"\\O(*)\\C3": {cps3[2], cps3[5]},
|
||||||
|
},
|
||||||
|
addEnglishSupported: true,
|
||||||
|
}
|
||||||
|
m.query = fpm
|
||||||
|
m.Object = perfObjects
|
||||||
|
|
||||||
|
fpm.Open()
|
||||||
|
|
||||||
|
time.Sleep(m.CountersRefreshInterval.Duration)
|
||||||
|
|
||||||
|
var acc3 testutil.Accumulator
|
||||||
|
err = m.Gather(&acc3)
|
||||||
|
require.NoError(t, err)
|
||||||
|
assert.Len(t, acc3.Metrics, 2)
|
||||||
|
fields4 := map[string]interface{}{
|
||||||
|
"C1": float32(1.1),
|
||||||
|
"C2": float32(1.2),
|
||||||
|
"C3": float32(1.3),
|
||||||
|
}
|
||||||
|
tags4 := map[string]string{
|
||||||
|
"instance": "I1",
|
||||||
|
"objectname": "O",
|
||||||
|
}
|
||||||
|
fields5 := map[string]interface{}{
|
||||||
|
"C1": float32(1.4),
|
||||||
|
"C2": float32(1.5),
|
||||||
|
"C3": float32(1.6),
|
||||||
|
}
|
||||||
|
tags5 := map[string]string{
|
||||||
|
"instance": "I2",
|
||||||
|
"objectname": "O",
|
||||||
|
}
|
||||||
|
|
||||||
|
acc3.AssertContainsTaggedFields(t, measurement, fields4, tags4)
|
||||||
|
acc3.AssertContainsTaggedFields(t, measurement, fields5, tags5)
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestGatherTotalNoExpansion(t *testing.T) {
|
||||||
|
var err error
|
||||||
|
measurement := "m"
|
||||||
|
perfObjects := createPerfObject(measurement, "O", []string{"*"}, []string{"C1", "C2"}, true, true)
|
||||||
|
cps1 := []string{"\\O(I1)\\C1", "\\O(I1)\\C2", "\\O(_Total)\\C1", "\\O(_Total)\\C2"}
|
||||||
|
m := Win_PerfCounters{PrintValid: false, UseWildcardsExpansion: false, Object: perfObjects, query: &FakePerformanceQuery{
|
||||||
|
counters: createCounterMap(append([]string{"\\O(*)\\C1", "\\O(*)\\C2"}, cps1...), []float64{0, 0, 1.1, 1.2, 1.3, 1.4}),
|
||||||
|
expandPaths: map[string][]string{
|
||||||
|
"\\O(*)\\C1": {cps1[0], cps1[2]},
|
||||||
|
"\\O(*)\\C2": {cps1[1], cps1[3]},
|
||||||
|
},
|
||||||
|
addEnglishSupported: true,
|
||||||
|
}}
|
||||||
|
var acc1 testutil.Accumulator
|
||||||
|
err = m.Gather(&acc1)
|
||||||
|
require.NoError(t, err)
|
||||||
|
assert.Len(t, m.counters, 2)
|
||||||
|
assert.Len(t, acc1.Metrics, 2)
|
||||||
|
fields1 := map[string]interface{}{
|
||||||
|
"C1": float32(1.1),
|
||||||
|
"C2": float32(1.2),
|
||||||
|
}
|
||||||
|
tags1 := map[string]string{
|
||||||
|
"instance": "I1",
|
||||||
|
"objectname": "O",
|
||||||
|
}
|
||||||
|
acc1.AssertContainsTaggedFields(t, measurement, fields1, tags1)
|
||||||
|
|
||||||
|
fields2 := map[string]interface{}{
|
||||||
|
"C1": float32(1.3),
|
||||||
|
"C2": float32(1.4),
|
||||||
|
}
|
||||||
|
tags2 := map[string]string{
|
||||||
|
"instance": "_Total",
|
||||||
|
"objectname": "O",
|
||||||
|
}
|
||||||
|
acc1.AssertContainsTaggedFields(t, measurement, fields2, tags2)
|
||||||
|
|
||||||
|
perfObjects[0].IncludeTotal = false
|
||||||
|
|
||||||
|
m.counters = nil
|
||||||
|
m.lastRefreshed = time.Time{}
|
||||||
|
|
||||||
|
var acc2 testutil.Accumulator
|
||||||
|
err = m.Gather(&acc2)
|
||||||
|
require.NoError(t, err)
|
||||||
|
assert.Len(t, m.counters, 2)
|
||||||
|
assert.Len(t, acc2.Metrics, 1)
|
||||||
|
|
||||||
|
acc2.AssertContainsTaggedFields(t, measurement, fields1, tags1)
|
||||||
|
|
||||||
|
acc2.AssertDoesNotContainsTaggedFields(t, measurement, fields2, tags2)
|
||||||
|
}
|
||||||
|
|
||||||
// list of nul terminated strings from WinAPI
|
// list of nul terminated strings from WinAPI
|
||||||
var unicodeStringListWithEnglishChars = []uint16{0x5c, 0x5c, 0x54, 0x34, 0x38, 0x30, 0x5c, 0x50, 0x68, 0x79, 0x73, 0x69, 0x63, 0x61, 0x6c, 0x44, 0x69, 0x73, 0x6b, 0x28, 0x30, 0x20, 0x43, 0x3a, 0x29, 0x5c, 0x43, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, 0x20, 0x44, 0x69, 0x73, 0x6b, 0x20, 0x51, 0x75, 0x65, 0x75, 0x65, 0x20, 0x4c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x0, 0x5c, 0x5c, 0x54, 0x34, 0x38, 0x30, 0x5c, 0x50, 0x68, 0x79, 0x73, 0x69, 0x63, 0x61, 0x6c, 0x44, 0x69, 0x73, 0x6b, 0x28, 0x5f, 0x54, 0x6f, 0x74, 0x61, 0x6c, 0x29, 0x5c, 0x43, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, 0x20, 0x44, 0x69, 0x73, 0x6b, 0x20, 0x51, 0x75, 0x65, 0x75, 0x65, 0x20, 0x4c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x0, 0x0}
|
var unicodeStringListWithEnglishChars = []uint16{0x5c, 0x5c, 0x54, 0x34, 0x38, 0x30, 0x5c, 0x50, 0x68, 0x79, 0x73, 0x69, 0x63, 0x61, 0x6c, 0x44, 0x69, 0x73, 0x6b, 0x28, 0x30, 0x20, 0x43, 0x3a, 0x29, 0x5c, 0x43, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, 0x20, 0x44, 0x69, 0x73, 0x6b, 0x20, 0x51, 0x75, 0x65, 0x75, 0x65, 0x20, 0x4c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x0, 0x5c, 0x5c, 0x54, 0x34, 0x38, 0x30, 0x5c, 0x50, 0x68, 0x79, 0x73, 0x69, 0x63, 0x61, 0x6c, 0x44, 0x69, 0x73, 0x6b, 0x28, 0x5f, 0x54, 0x6f, 0x74, 0x61, 0x6c, 0x29, 0x5c, 0x43, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, 0x20, 0x44, 0x69, 0x73, 0x6b, 0x20, 0x51, 0x75, 0x65, 0x75, 0x65, 0x20, 0x4c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x0, 0x0}
|
||||||
var unicodeStringListWithCzechChars = []uint16{0x5c, 0x5c, 0x54, 0x34, 0x38, 0x30, 0x5c, 0x46, 0x79, 0x7a, 0x69, 0x63, 0x6b, 0xfd, 0x20, 0x64, 0x69, 0x73, 0x6b, 0x28, 0x30, 0x20, 0x43, 0x3a, 0x29, 0x5c, 0x41, 0x6b, 0x74, 0x75, 0xe1, 0x6c, 0x6e, 0xed, 0x20, 0x64, 0xe9, 0x6c, 0x6b, 0x61, 0x20, 0x66, 0x72, 0x6f, 0x6e, 0x74, 0x79, 0x20, 0x64, 0x69, 0x73, 0x6b, 0x75, 0x0, 0x5c, 0x5c, 0x54, 0x34, 0x38, 0x30, 0x5c, 0x46, 0x79, 0x7a, 0x69, 0x63, 0x6b, 0xfd, 0x20, 0x64, 0x69, 0x73, 0x6b, 0x28, 0x5f, 0x54, 0x6f, 0x74, 0x61, 0x6c, 0x29, 0x5c, 0x41, 0x6b, 0x74, 0x75, 0xe1, 0x6c, 0x6e, 0xed, 0x20, 0x64, 0xe9, 0x6c, 0x6b, 0x61, 0x20, 0x66, 0x72, 0x6f, 0x6e, 0x74, 0x79, 0x20, 0x64, 0x69, 0x73, 0x6b, 0x75, 0x0, 0x0}
|
var unicodeStringListWithCzechChars = []uint16{0x5c, 0x5c, 0x54, 0x34, 0x38, 0x30, 0x5c, 0x46, 0x79, 0x7a, 0x69, 0x63, 0x6b, 0xfd, 0x20, 0x64, 0x69, 0x73, 0x6b, 0x28, 0x30, 0x20, 0x43, 0x3a, 0x29, 0x5c, 0x41, 0x6b, 0x74, 0x75, 0xe1, 0x6c, 0x6e, 0xed, 0x20, 0x64, 0xe9, 0x6c, 0x6b, 0x61, 0x20, 0x66, 0x72, 0x6f, 0x6e, 0x74, 0x79, 0x20, 0x64, 0x69, 0x73, 0x6b, 0x75, 0x0, 0x5c, 0x5c, 0x54, 0x34, 0x38, 0x30, 0x5c, 0x46, 0x79, 0x7a, 0x69, 0x63, 0x6b, 0xfd, 0x20, 0x64, 0x69, 0x73, 0x6b, 0x28, 0x5f, 0x54, 0x6f, 0x74, 0x61, 0x6c, 0x29, 0x5c, 0x41, 0x6b, 0x74, 0x75, 0xe1, 0x6c, 0x6e, 0xed, 0x20, 0x64, 0xe9, 0x6c, 0x6b, 0x61, 0x20, 0x66, 0x72, 0x6f, 0x6e, 0x74, 0x79, 0x20, 0x64, 0x69, 0x73, 0x6b, 0x75, 0x0, 0x0}
|
||||||
|
@ -495,5 +784,4 @@ func TestUTF16ToStringArray(t *testing.T) {
|
||||||
|
|
||||||
czechStrings := UTF16ToStringArray(unicodeStringListWithCzechChars)
|
czechStrings := UTF16ToStringArray(unicodeStringListWithCzechChars)
|
||||||
assert.True(t, assert.ObjectsAreEqual(czechStrings, stringArrayWithCzechChars), "Not equal czech arrays")
|
assert.True(t, assert.ObjectsAreEqual(czechStrings, stringArrayWithCzechChars), "Not equal czech arrays")
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue