feat: Implemented support for reading raw values, added tests and doc (#6501)
This commit is contained in:
parent
437d3b0773
commit
3ef1c73582
|
|
@ -179,7 +179,19 @@ So for ordering your data in a good manner,
|
|||
this is a good key to set with a value when you want your IIS and Disk results stored
|
||||
separately from Processor results.
|
||||
|
||||
Example: `Measurement = "win_disk"``
|
||||
Example: `Measurement = "win_disk"`
|
||||
|
||||
#### UseRawValues
|
||||
|
||||
(Optional)
|
||||
|
||||
This key is optional. It is a simple bool.
|
||||
If set to `true`, counter values will be provided in the raw, integer, form. This is in contrast with the default behavior, where values are returned in a formatted, displayable, form
|
||||
as seen in the Windows Performance Monitor.
|
||||
A field representing raw counter value has the `_Raw` suffix. Raw values should be further used in a calculation, e.g. `100-(non_negative_derivative("Percent_Processor_Time_Raw",1s)/100000`
|
||||
Note: Time based counters (i.e. _% Processor Time_) are reported in hundredths of nanoseconds.
|
||||
|
||||
Example: `UseRawValues = true`
|
||||
|
||||
#### IncludeTotal
|
||||
|
||||
|
|
|
|||
|
|
@ -272,6 +272,8 @@ var (
|
|||
pdh_ValidatePathW *syscall.Proc
|
||||
pdh_ExpandWildCardPathW *syscall.Proc
|
||||
pdh_GetCounterInfoW *syscall.Proc
|
||||
pdh_GetRawCounterValue *syscall.Proc
|
||||
pdh_GetRawCounterArrayW *syscall.Proc
|
||||
)
|
||||
|
||||
func init() {
|
||||
|
|
@ -290,6 +292,8 @@ func init() {
|
|||
pdh_ValidatePathW = libpdhDll.MustFindProc("PdhValidatePathW")
|
||||
pdh_ExpandWildCardPathW = libpdhDll.MustFindProc("PdhExpandWildCardPathW")
|
||||
pdh_GetCounterInfoW = libpdhDll.MustFindProc("PdhGetCounterInfoW")
|
||||
pdh_GetRawCounterValue = libpdhDll.MustFindProc("PdhGetRawCounterValue")
|
||||
pdh_GetRawCounterArrayW = libpdhDll.MustFindProc("PdhGetRawCounterArrayW")
|
||||
}
|
||||
|
||||
// PdhAddCounter adds the specified counter to the query. This is the internationalized version. Preferably, use the
|
||||
|
|
@ -591,3 +595,50 @@ func PdhGetCounterInfo(hCounter PDH_HCOUNTER, bRetrieveExplainText int, pdwBuffe
|
|||
|
||||
return uint32(ret)
|
||||
}
|
||||
|
||||
// Returns the current raw value of the counter.
|
||||
// If the specified counter instance does not exist, this function will return ERROR_SUCCESS
|
||||
// and the CStatus member of the PDH_RAW_COUNTER structure will contain PDH_CSTATUS_NO_INSTANCE.
|
||||
//
|
||||
// hCounter [in]
|
||||
// Handle of the counter from which to retrieve the current raw value. The PdhAddCounter function returns this handle.
|
||||
//
|
||||
// lpdwType [out]
|
||||
// Receives the counter type. For a list of counter types, see the Counter Types section of the Windows Server 2003 Deployment Kit.
|
||||
// This parameter is optional.
|
||||
//
|
||||
// pValue [out]
|
||||
// A PDH_RAW_COUNTER structure that receives the counter value.
|
||||
func PdhGetRawCounterValue(hCounter PDH_HCOUNTER, lpdwType *uint32, pValue *PDH_RAW_COUNTER) uint32 {
|
||||
ret, _, _ := pdh_GetRawCounterValue.Call(
|
||||
uintptr(hCounter),
|
||||
uintptr(unsafe.Pointer(lpdwType)),
|
||||
uintptr(unsafe.Pointer(pValue)))
|
||||
|
||||
return uint32(ret)
|
||||
}
|
||||
|
||||
// Returns an array of raw values from the specified counter. Use this function when you want to retrieve the raw counter values
|
||||
// of a counter that contains a wildcard character for the instance name.
|
||||
// hCounter
|
||||
// Handle of the counter for whose current raw instance values you want to retrieve. The PdhAddCounter function returns this handle.
|
||||
//
|
||||
// lpdwBufferSize
|
||||
// Size of the ItemBuffer buffer, in bytes. If zero on input, the function returns PDH_MORE_DATA and sets this parameter to the required buffer size.
|
||||
// If the buffer is larger than the required size, the function sets this parameter to the actual size of the buffer that was used.
|
||||
// If the specified size on input is greater than zero but less than the required size, you should not rely on the returned size to reallocate the buffer.
|
||||
//
|
||||
// lpdwItemCount
|
||||
// Number of raw counter values in the ItemBuffer buffer.
|
||||
//
|
||||
// ItemBuffer
|
||||
// Caller-allocated buffer that receives the array of PDH_RAW_COUNTER_ITEM structures; the structures contain the raw instance counter values.
|
||||
// Set to NULL if lpdwBufferSize is zero.
|
||||
func PdhGetRawCounterArray(hCounter PDH_HCOUNTER, lpdwBufferSize *uint32, lpdwBufferCount *uint32, itemBuffer *byte) uint32 {
|
||||
ret, _, _ := pdh_GetRawCounterArrayW.Call(
|
||||
uintptr(hCounter),
|
||||
uintptr(unsafe.Pointer(lpdwBufferSize)),
|
||||
uintptr(unsafe.Pointer(lpdwBufferCount)),
|
||||
uintptr(unsafe.Pointer(itemBuffer)))
|
||||
return uint32(ret)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -120,3 +120,26 @@ type PDH_COUNTER_INFO struct {
|
|||
//Start of the string data that is appended to the structure.
|
||||
DataBuffer [1]uint32 // pointer to an extra space
|
||||
}
|
||||
|
||||
// The PDH_RAW_COUNTER structure returns the data as it was collected from the counter provider. No translation, formatting, or other interpretation is performed on the data
|
||||
type PDH_RAW_COUNTER struct {
|
||||
// Counter status that indicates if the counter value is valid. Check this member before using the data in a calculation or displaying its value. For a list of possible values,
|
||||
// see https://docs.microsoft.com/windows/desktop/PerfCtrs/checking-pdh-interface-return-values
|
||||
CStatus uint32
|
||||
// Local time for when the data was collected
|
||||
TimeStamp FILETIME
|
||||
// First raw counter value.
|
||||
FirstValue int64
|
||||
// Second raw counter value. Rate counters require two values in order to compute a displayable value.
|
||||
SecondValue int64
|
||||
// If the counter type contains the PERF_MULTI_COUNTER flag, this member contains the additional counter data used in the calculation.
|
||||
// For example, the PERF_100NSEC_MULTI_TIMER counter type contains the PERF_MULTI_COUNTER flag.
|
||||
MultiCount uint32
|
||||
}
|
||||
|
||||
type PDH_RAW_COUNTER_ITEM struct {
|
||||
// Pointer to a null-terminated string that specifies the instance name of the counter. The string is appended to the end of this structure.
|
||||
SzName *uint16
|
||||
//A PDH_RAW_COUNTER structure that contains the raw counter value of the instance
|
||||
RawValue PDH_RAW_COUNTER
|
||||
}
|
||||
|
|
|
|||
|
|
@ -113,3 +113,26 @@ type PDH_COUNTER_INFO struct {
|
|||
//Start of the string data that is appended to the structure.
|
||||
DataBuffer [1]uint32 // pointer to an extra space
|
||||
}
|
||||
|
||||
// The PDH_RAW_COUNTER structure returns the data as it was collected from the counter provider. No translation, formatting, or other interpretation is performed on the data
|
||||
type PDH_RAW_COUNTER struct {
|
||||
// Counter status that indicates if the counter value is valid. Check this member before using the data in a calculation or displaying its value. For a list of possible values,
|
||||
// see https://docs.microsoft.com/windows/desktop/PerfCtrs/checking-pdh-interface-return-values
|
||||
CStatus uint32
|
||||
// Local time for when the data was collected
|
||||
TimeStamp FILETIME
|
||||
// First raw counter value.
|
||||
FirstValue int64
|
||||
// Second raw counter value. Rate counters require two values in order to compute a displayable value.
|
||||
SecondValue int64
|
||||
// If the counter type contains the PERF_MULTI_COUNTER flag, this member contains the additional counter data used in the calculation.
|
||||
// For example, the PERF_100NSEC_MULTI_TIMER counter type contains the PERF_MULTI_COUNTER flag.
|
||||
MultiCount uint32
|
||||
}
|
||||
|
||||
type PDH_RAW_COUNTER_ITEM struct {
|
||||
// Pointer to a null-terminated string that specifies the instance name of the counter. The string is appended to the end of this structure.
|
||||
SzName *uint16
|
||||
//A PDH_RAW_COUNTER structure that contains the raw counter value of the instance
|
||||
RawValue PDH_RAW_COUNTER
|
||||
}
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@ import (
|
|||
//PerformanceQuery is abstraction for PDH_FMT_COUNTERVALUE_ITEM_DOUBLE
|
||||
type CounterValue struct {
|
||||
InstanceName string
|
||||
Value float64
|
||||
Value interface{}
|
||||
}
|
||||
|
||||
//PerformanceQuery provides wrappers around Windows performance counters API for easy usage in GO
|
||||
|
|
@ -26,7 +26,9 @@ type PerformanceQuery interface {
|
|||
GetCounterPath(counterHandle PDH_HCOUNTER) (string, error)
|
||||
ExpandWildCardPath(counterPath string) ([]string, error)
|
||||
GetFormattedCounterValueDouble(hCounter PDH_HCOUNTER) (float64, error)
|
||||
GetRawCounterValue(hCounter PDH_HCOUNTER) (int64, error)
|
||||
GetFormattedCounterArrayDouble(hCounter PDH_HCOUNTER) ([]CounterValue, error)
|
||||
GetRawCounterArray(hCounter PDH_HCOUNTER) ([]CounterValue, error)
|
||||
CollectData() error
|
||||
CollectDataWithTime() (time.Time, error)
|
||||
IsVistaOrNewer() bool
|
||||
|
|
@ -182,6 +184,29 @@ func (m *PerformanceQueryImpl) GetFormattedCounterArrayDouble(hCounter PDH_HCOUN
|
|||
return nil, NewPdhError(ret)
|
||||
}
|
||||
|
||||
func (m *PerformanceQueryImpl) GetRawCounterArray(hCounter PDH_HCOUNTER) ([]CounterValue, error) {
|
||||
var buffSize uint32
|
||||
var itemCount uint32
|
||||
var ret uint32
|
||||
|
||||
if ret = PdhGetRawCounterArray(hCounter, &buffSize, &itemCount, nil); ret == PDH_MORE_DATA {
|
||||
buff := make([]byte, buffSize)
|
||||
|
||||
if ret = PdhGetRawCounterArray(hCounter, &buffSize, &itemCount, &buff[0]); ret == ERROR_SUCCESS {
|
||||
items := (*[1 << 20]PDH_RAW_COUNTER_ITEM)(unsafe.Pointer(&buff[0]))[:itemCount]
|
||||
values := make([]CounterValue, 0, itemCount)
|
||||
for _, item := range items {
|
||||
if item.RawValue.CStatus == PDH_CSTATUS_VALID_DATA || item.RawValue.CStatus == PDH_CSTATUS_NEW_DATA {
|
||||
val := CounterValue{UTF16PtrToString(item.SzName), item.RawValue.FirstValue}
|
||||
values = append(values, val)
|
||||
}
|
||||
}
|
||||
return values, nil
|
||||
}
|
||||
}
|
||||
return nil, NewPdhError(ret)
|
||||
}
|
||||
|
||||
func (m *PerformanceQueryImpl) CollectData() error {
|
||||
var ret uint32
|
||||
if m.query == 0 {
|
||||
|
|
@ -209,6 +234,27 @@ func (m *PerformanceQueryImpl) IsVistaOrNewer() bool {
|
|||
return PdhAddEnglishCounterSupported()
|
||||
}
|
||||
|
||||
func (m *PerformanceQueryImpl) GetRawCounterValue(hCounter PDH_HCOUNTER) (int64, error) {
|
||||
if m.query == 0 {
|
||||
return 0, errors.New("uninitialised query")
|
||||
}
|
||||
|
||||
var counterType uint32
|
||||
var value PDH_RAW_COUNTER
|
||||
var ret uint32
|
||||
|
||||
if ret = PdhGetRawCounterValue(hCounter, &counterType, &value); ret == ERROR_SUCCESS {
|
||||
if value.CStatus == PDH_CSTATUS_VALID_DATA || value.CStatus == PDH_CSTATUS_NEW_DATA {
|
||||
return value.FirstValue, nil
|
||||
} else {
|
||||
return 0, NewPdhError(value.CStatus)
|
||||
}
|
||||
} else {
|
||||
return 0, NewPdhError(ret)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// UTF16PtrToString converts Windows API LPTSTR (pointer to string) to go string
|
||||
func UTF16PtrToString(s *uint16) string {
|
||||
if s == nil {
|
||||
|
|
|
|||
|
|
@ -59,6 +59,8 @@ var sampleConfig = `
|
|||
# IncludeTotal=false
|
||||
# Print out when the performance counter is missing from object, counter or instance.
|
||||
# WarnOnMissing = false
|
||||
# Gather raw values instead of formatted. Raw value is stored in the field name with the "_Raw" suffix, e.g. "Disk_Read_Bytes_sec_Raw".
|
||||
# UseRawValues = true
|
||||
|
||||
[[inputs.win_perf_counters.object]]
|
||||
# Disk times and queues
|
||||
|
|
@ -174,6 +176,7 @@ type perfobject struct {
|
|||
WarnOnMissing bool
|
||||
FailOnMissing bool
|
||||
IncludeTotal bool
|
||||
UseRawValues bool
|
||||
}
|
||||
|
||||
type counter struct {
|
||||
|
|
@ -183,6 +186,7 @@ type counter struct {
|
|||
instance string
|
||||
measurement string
|
||||
includeTotal bool
|
||||
useRawValue bool
|
||||
counterHandle PDH_HCOUNTER
|
||||
}
|
||||
|
||||
|
|
@ -257,8 +261,20 @@ func (m *Win_PerfCounters) SampleConfig() string {
|
|||
return sampleConfig
|
||||
}
|
||||
|
||||
//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 {
|
||||
func newCounter(counterHandle PDH_HCOUNTER, counterPath string, objectName string, instance string, counterName string, measurement string, includeTotal bool, useRawValue bool) *counter {
|
||||
measurementName := sanitizedChars.Replace(measurement)
|
||||
if measurementName == "" {
|
||||
measurementName = "win_perf_counters"
|
||||
}
|
||||
newCounterName := sanitizedChars.Replace(counterName)
|
||||
if useRawValue {
|
||||
newCounterName += "_Raw"
|
||||
}
|
||||
return &counter{counterPath, objectName, newCounterName, instance, measurementName,
|
||||
includeTotal, useRawValue, counterHandle}
|
||||
}
|
||||
|
||||
func (m *Win_PerfCounters) AddItem(counterPath string, objectName string, instance string, counterName string, measurement string, includeTotal bool, useRawValue bool) error {
|
||||
origCounterPath := counterPath
|
||||
var err error
|
||||
var counterHandle PDH_HCOUNTER
|
||||
|
|
@ -315,20 +331,27 @@ func (m *Win_PerfCounters) AddItem(counterPath string, objectName string, instan
|
|||
}
|
||||
counterPath = formatPath(origObjectName, newInstance, origCounterName)
|
||||
counterHandle, err = m.query.AddEnglishCounterToQuery(counterPath)
|
||||
newItem = &counter{
|
||||
newItem = newCounter(
|
||||
counterHandle,
|
||||
counterPath,
|
||||
origObjectName, origCounterName,
|
||||
instance, measurement,
|
||||
includeTotal, counterHandle,
|
||||
}
|
||||
origObjectName, instance,
|
||||
origCounterName,
|
||||
measurement,
|
||||
includeTotal,
|
||||
useRawValue,
|
||||
)
|
||||
} else {
|
||||
counterHandle, err = m.query.AddCounterToQuery(counterPath)
|
||||
newItem = &counter{
|
||||
newItem = newCounter(
|
||||
counterHandle,
|
||||
counterPath,
|
||||
objectName, counterName,
|
||||
instance, measurement,
|
||||
includeTotal, counterHandle,
|
||||
}
|
||||
objectName,
|
||||
instance,
|
||||
counterName,
|
||||
measurement,
|
||||
includeTotal,
|
||||
useRawValue,
|
||||
)
|
||||
}
|
||||
|
||||
if instance == "_Total" && origInstance == "*" && !includeTotal {
|
||||
|
|
@ -342,8 +365,16 @@ func (m *Win_PerfCounters) AddItem(counterPath string, objectName string, instan
|
|||
}
|
||||
}
|
||||
} else {
|
||||
newItem := &counter{counterPath, objectName, counterName, instance, measurement,
|
||||
includeTotal, counterHandle}
|
||||
newItem := newCounter(
|
||||
counterHandle,
|
||||
counterPath,
|
||||
objectName,
|
||||
instance,
|
||||
counterName,
|
||||
measurement,
|
||||
includeTotal,
|
||||
useRawValue,
|
||||
)
|
||||
m.counters = append(m.counters, newItem)
|
||||
if m.PrintValid {
|
||||
m.Log.Infof("Valid: %s", counterPath)
|
||||
|
|
@ -369,12 +400,15 @@ func (m *Win_PerfCounters) ParseConfig() error {
|
|||
if len(m.Object) > 0 {
|
||||
for _, PerfObject := range m.Object {
|
||||
for _, counter := range PerfObject.Counters {
|
||||
if len(PerfObject.Instances) == 0 {
|
||||
m.Log.Warnf("Missing 'Instances' param for object '%s'\n", PerfObject.ObjectName)
|
||||
}
|
||||
for _, instance := range PerfObject.Instances {
|
||||
objectname := PerfObject.ObjectName
|
||||
|
||||
counterPath = formatPath(objectname, instance, counter)
|
||||
|
||||
err := m.AddItem(counterPath, objectname, instance, counter, PerfObject.Measurement, PerfObject.IncludeTotal)
|
||||
err := m.AddItem(counterPath, objectname, instance, counter, PerfObject.Measurement, PerfObject.IncludeTotal, PerfObject.UseRawValues)
|
||||
|
||||
if err != nil {
|
||||
if PerfObject.FailOnMissing || PerfObject.WarnOnMissing {
|
||||
|
|
@ -447,12 +481,16 @@ func (m *Win_PerfCounters) Gather(acc telegraf.Accumulator) error {
|
|||
return err
|
||||
}
|
||||
}
|
||||
|
||||
var value interface{}
|
||||
// For iterate over the known metrics and get the samples.
|
||||
for _, metric := range m.counters {
|
||||
// collect
|
||||
if m.UseWildcardsExpansion {
|
||||
value, err := m.query.GetFormattedCounterValueDouble(metric.counterHandle)
|
||||
if metric.useRawValue {
|
||||
value, err = m.query.GetRawCounterValue(metric.counterHandle)
|
||||
} else {
|
||||
value, err = m.query.GetFormattedCounterValueDouble(metric.counterHandle)
|
||||
}
|
||||
if err != nil {
|
||||
//ignore invalid data as some counters from process instances returns this sometimes
|
||||
if !isKnownCounterDataError(err) {
|
||||
|
|
@ -463,7 +501,12 @@ func (m *Win_PerfCounters) Gather(acc telegraf.Accumulator) error {
|
|||
}
|
||||
addCounterMeasurement(metric, metric.instance, value, collectFields)
|
||||
} else {
|
||||
counterValues, err := m.query.GetFormattedCounterArrayDouble(metric.counterHandle)
|
||||
var counterValues []CounterValue
|
||||
if metric.useRawValue {
|
||||
counterValues, err = m.query.GetRawCounterArray(metric.counterHandle)
|
||||
} else {
|
||||
counterValues, err = m.query.GetFormattedCounterArrayDouble(metric.counterHandle)
|
||||
}
|
||||
if err != nil {
|
||||
//ignore invalid data as some counters from process instances returns this sometimes
|
||||
if !isKnownCounterDataError(err) {
|
||||
|
|
@ -519,16 +562,12 @@ func shouldIncludeMetric(metric *counter, cValue CounterValue) bool {
|
|||
return false
|
||||
}
|
||||
|
||||
func addCounterMeasurement(metric *counter, instanceName string, value float64, collectFields map[instanceGrouping]map[string]interface{}) {
|
||||
measurement := sanitizedChars.Replace(metric.measurement)
|
||||
if measurement == "" {
|
||||
measurement = "win_perf_counters"
|
||||
}
|
||||
var instance = instanceGrouping{measurement, instanceName, metric.objectName}
|
||||
func addCounterMeasurement(metric *counter, instanceName string, value interface{}, collectFields map[instanceGrouping]map[string]interface{}) {
|
||||
var instance = instanceGrouping{metric.measurement, instanceName, metric.objectName}
|
||||
if collectFields[instance] == nil {
|
||||
collectFields[instance] = make(map[string]interface{})
|
||||
}
|
||||
collectFields[instance][sanitizedChars.Replace(metric.counter)] = float32(value)
|
||||
collectFields[instance][sanitizedChars.Replace(metric.counter)] = value
|
||||
}
|
||||
|
||||
func isKnownCounterDataError(err error) bool {
|
||||
|
|
|
|||
|
|
@ -69,8 +69,13 @@ func TestWinPerformanceQueryImplIntegration(t *testing.T) {
|
|||
err = query.CollectData()
|
||||
require.NoError(t, err)
|
||||
|
||||
_, err = query.GetFormattedCounterValueDouble(hCounter)
|
||||
fcounter, err := query.GetFormattedCounterValueDouble(hCounter)
|
||||
require.NoError(t, err)
|
||||
require.True(t, fcounter > 0)
|
||||
|
||||
rcounter, err := query.GetRawCounterValue(hCounter)
|
||||
require.NoError(t, err)
|
||||
require.True(t, rcounter > 10000000)
|
||||
|
||||
now := time.Now()
|
||||
mtime, err := query.CollectDataWithTime()
|
||||
|
|
@ -104,13 +109,17 @@ func TestWinPerformanceQueryImplIntegration(t *testing.T) {
|
|||
err = query.CollectData()
|
||||
require.NoError(t, err)
|
||||
|
||||
arr, err := query.GetFormattedCounterArrayDouble(hCounter)
|
||||
farr, err := query.GetFormattedCounterArrayDouble(hCounter)
|
||||
if phderr, ok := err.(*PdhError); ok && phderr.ErrorCode != PDH_INVALID_DATA && phderr.ErrorCode != PDH_CALC_NEGATIVE_VALUE {
|
||||
time.Sleep(time.Second)
|
||||
arr, err = query.GetFormattedCounterArrayDouble(hCounter)
|
||||
farr, err = query.GetFormattedCounterArrayDouble(hCounter)
|
||||
}
|
||||
require.NoError(t, err)
|
||||
require.True(t, len(arr) > 0, "Too")
|
||||
require.True(t, len(farr) > 0)
|
||||
|
||||
rarr, err := query.GetRawCounterArray(hCounter)
|
||||
require.NoError(t, err)
|
||||
require.True(t, len(rarr) > 0, "Too")
|
||||
|
||||
err = query.Close()
|
||||
require.NoError(t, err)
|
||||
|
|
@ -144,8 +153,13 @@ func TestWinPerfcountersConfigGet1Integration(t *testing.T) {
|
|||
|
||||
perfobjects[0] = PerfObject
|
||||
|
||||
m := Win_PerfCounters{PrintValid: false, Object: perfobjects, query: &PerformanceQueryImpl{}}
|
||||
m.query.Open()
|
||||
m := Win_PerfCounters{
|
||||
PrintValid: false,
|
||||
Object: perfobjects,
|
||||
query: &PerformanceQueryImpl{},
|
||||
Log: testutil.Logger{},
|
||||
}
|
||||
_ = m.query.Open()
|
||||
|
||||
err := m.ParseConfig()
|
||||
require.NoError(t, err)
|
||||
|
|
@ -178,8 +192,13 @@ func TestWinPerfcountersConfigGet2Integration(t *testing.T) {
|
|||
|
||||
perfobjects[0] = PerfObject
|
||||
|
||||
m := Win_PerfCounters{PrintValid: false, Object: perfobjects, query: &PerformanceQueryImpl{}}
|
||||
m.query.Open()
|
||||
m := Win_PerfCounters{
|
||||
PrintValid: false,
|
||||
Object: perfobjects,
|
||||
query: &PerformanceQueryImpl{},
|
||||
Log: testutil.Logger{},
|
||||
}
|
||||
_ = m.query.Open()
|
||||
|
||||
err := m.ParseConfig()
|
||||
require.NoError(t, err)
|
||||
|
|
@ -225,8 +244,13 @@ func TestWinPerfcountersConfigGet3Integration(t *testing.T) {
|
|||
|
||||
perfobjects[0] = PerfObject
|
||||
|
||||
m := Win_PerfCounters{PrintValid: false, Object: perfobjects, query: &PerformanceQueryImpl{}}
|
||||
m.query.Open()
|
||||
m := Win_PerfCounters{
|
||||
PrintValid: false,
|
||||
Object: perfobjects,
|
||||
query: &PerformanceQueryImpl{},
|
||||
Log: testutil.Logger{},
|
||||
}
|
||||
_ = m.query.Open()
|
||||
|
||||
err := m.ParseConfig()
|
||||
require.NoError(t, err)
|
||||
|
|
@ -274,8 +298,13 @@ func TestWinPerfcountersConfigGet4Integration(t *testing.T) {
|
|||
|
||||
perfobjects[0] = PerfObject
|
||||
|
||||
m := Win_PerfCounters{PrintValid: false, Object: perfobjects, query: &PerformanceQueryImpl{}}
|
||||
m.query.Open()
|
||||
m := Win_PerfCounters{
|
||||
PrintValid: false,
|
||||
Object: perfobjects,
|
||||
query: &PerformanceQueryImpl{},
|
||||
Log: testutil.Logger{},
|
||||
}
|
||||
_ = m.query.Open()
|
||||
|
||||
err := m.ParseConfig()
|
||||
require.NoError(t, err)
|
||||
|
|
@ -324,8 +353,13 @@ func TestWinPerfcountersConfigGet5Integration(t *testing.T) {
|
|||
|
||||
perfobjects[0] = PerfObject
|
||||
|
||||
m := Win_PerfCounters{PrintValid: false, Object: perfobjects, query: &PerformanceQueryImpl{}}
|
||||
m.query.Open()
|
||||
m := Win_PerfCounters{
|
||||
PrintValid: false,
|
||||
Object: perfobjects,
|
||||
query: &PerformanceQueryImpl{},
|
||||
Log: testutil.Logger{},
|
||||
}
|
||||
_ = m.query.Open()
|
||||
|
||||
err := m.ParseConfig()
|
||||
require.NoError(t, err)
|
||||
|
|
@ -370,8 +404,13 @@ func TestWinPerfcountersConfigGet6Integration(t *testing.T) {
|
|||
|
||||
perfobjects[0] = PerfObject
|
||||
|
||||
m := Win_PerfCounters{PrintValid: false, Object: perfobjects, query: &PerformanceQueryImpl{}}
|
||||
m.query.Open()
|
||||
m := Win_PerfCounters{
|
||||
PrintValid: false,
|
||||
Object: perfobjects,
|
||||
query: &PerformanceQueryImpl{},
|
||||
Log: testutil.Logger{},
|
||||
}
|
||||
_ = m.query.Open()
|
||||
|
||||
err := m.ParseConfig()
|
||||
require.NoError(t, err)
|
||||
|
|
@ -402,12 +441,18 @@ func TestWinPerfcountersConfigGet7Integration(t *testing.T) {
|
|||
false,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
}
|
||||
|
||||
perfobjects[0] = PerfObject
|
||||
|
||||
m := Win_PerfCounters{PrintValid: false, Object: perfobjects, query: &PerformanceQueryImpl{}}
|
||||
m.query.Open()
|
||||
m := Win_PerfCounters{
|
||||
PrintValid: false,
|
||||
Object: perfobjects,
|
||||
query: &PerformanceQueryImpl{},
|
||||
Log: testutil.Logger{},
|
||||
}
|
||||
_ = m.query.Open()
|
||||
|
||||
err := m.ParseConfig()
|
||||
require.NoError(t, err)
|
||||
|
|
@ -458,7 +503,7 @@ func TestWinPerfcountersConfigError1Integration(t *testing.T) {
|
|||
query: &PerformanceQueryImpl{},
|
||||
Log: testutil.Logger{},
|
||||
}
|
||||
m.query.Open()
|
||||
_ = m.query.Open()
|
||||
|
||||
err := m.ParseConfig()
|
||||
require.Error(t, err)
|
||||
|
|
@ -497,7 +542,7 @@ func TestWinPerfcountersConfigError2Integration(t *testing.T) {
|
|||
query: &PerformanceQueryImpl{},
|
||||
Log: testutil.Logger{},
|
||||
}
|
||||
m.query.Open()
|
||||
_ = m.query.Open()
|
||||
|
||||
err := m.ParseConfig()
|
||||
var acc testutil.Accumulator
|
||||
|
|
@ -538,7 +583,7 @@ func TestWinPerfcountersConfigError3Integration(t *testing.T) {
|
|||
query: &PerformanceQueryImpl{},
|
||||
Log: testutil.Logger{},
|
||||
}
|
||||
m.query.Open()
|
||||
_ = m.query.Open()
|
||||
|
||||
err := m.ParseConfig()
|
||||
require.Error(t, err)
|
||||
|
|
@ -647,3 +692,77 @@ func TestWinPerfcountersCollect2Integration(t *testing.T) {
|
|||
}
|
||||
|
||||
}
|
||||
|
||||
func TestWinPerfcountersCollectRawIntegration(t *testing.T) {
|
||||
if testing.Short() {
|
||||
t.Skip("Skipping integration test in short mode")
|
||||
}
|
||||
var instances = make([]string, 1)
|
||||
var counters = make([]string, 1)
|
||||
var perfobjects = make([]perfobject, 1)
|
||||
|
||||
objectname := "Processor"
|
||||
instances[0] = "*"
|
||||
counters[0] = "% Idle Time"
|
||||
|
||||
var expectedCounter = "Percent_Idle_Time_Raw"
|
||||
|
||||
var measurement = "test"
|
||||
|
||||
PerfObject := perfobject{
|
||||
ObjectName: objectname,
|
||||
Instances: instances,
|
||||
Counters: counters,
|
||||
Measurement: measurement,
|
||||
WarnOnMissing: false,
|
||||
FailOnMissing: true,
|
||||
IncludeTotal: false,
|
||||
UseRawValues: true,
|
||||
}
|
||||
|
||||
perfobjects[0] = PerfObject
|
||||
|
||||
m := Win_PerfCounters{
|
||||
PrintValid: false,
|
||||
Object: perfobjects,
|
||||
UseWildcardsExpansion: true,
|
||||
query: &PerformanceQueryImpl{},
|
||||
Log: testutil.Logger{},
|
||||
}
|
||||
var acc testutil.Accumulator
|
||||
err := m.Gather(&acc)
|
||||
require.NoError(t, err)
|
||||
|
||||
time.Sleep(2000 * time.Millisecond)
|
||||
err = m.Gather(&acc)
|
||||
require.NoError(t, err)
|
||||
require.True(t, len(acc.Metrics) > 1)
|
||||
|
||||
for _, metric := range acc.Metrics {
|
||||
val, ok := metric.Fields[expectedCounter]
|
||||
require.True(t, ok, "Expected presence of %s field", expectedCounter)
|
||||
valInt64, ok := val.(int64)
|
||||
require.True(t, ok, fmt.Sprintf("Expected int64, got %T", val))
|
||||
require.True(t, valInt64 > 0, fmt.Sprintf("Expected > 0, got %d, for %#v", valInt64, metric))
|
||||
}
|
||||
|
||||
// Test *Array way
|
||||
m = Win_PerfCounters{PrintValid: false, Object: perfobjects, UseWildcardsExpansion: false, query: &PerformanceQueryImpl{}, Log: testutil.Logger{}}
|
||||
var acc2 testutil.Accumulator
|
||||
err = m.Gather(&acc)
|
||||
require.NoError(t, err)
|
||||
|
||||
time.Sleep(2000 * time.Millisecond)
|
||||
err = m.Gather(&acc2)
|
||||
require.NoError(t, err)
|
||||
require.True(t, len(acc2.Metrics) > 1)
|
||||
|
||||
for _, metric := range acc2.Metrics {
|
||||
val, ok := metric.Fields[expectedCounter]
|
||||
require.True(t, ok, "Expected presence of %s field", expectedCounter)
|
||||
valInt64, ok := val.(int64)
|
||||
require.True(t, ok, fmt.Sprintf("Expected int64, got %T", val))
|
||||
require.True(t, valInt64 > 0, fmt.Sprintf("Expected > 0, got %d, for %#v", valInt64, metric))
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ package win_perf_counters
|
|||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
|
|
@ -30,12 +31,19 @@ type FakePerformanceQuery struct {
|
|||
|
||||
var MetricTime = time.Date(2018, 5, 28, 12, 0, 0, 0, time.UTC)
|
||||
|
||||
func (m *testCounter) ToCounterValue() *CounterValue {
|
||||
func (m *testCounter) ToCounterValue(raw bool) *CounterValue {
|
||||
_, inst, _, _ := extractCounterInfoFromCounterPath(m.path)
|
||||
if inst == "" {
|
||||
inst = "--"
|
||||
}
|
||||
return &CounterValue{inst, m.value}
|
||||
var val interface{}
|
||||
if raw {
|
||||
val = int64(m.value)
|
||||
} else {
|
||||
val = m.value
|
||||
}
|
||||
|
||||
return &CounterValue{inst, val}
|
||||
}
|
||||
|
||||
func (m *FakePerformanceQuery) Open() error {
|
||||
|
|
@ -110,6 +118,22 @@ func (m *FakePerformanceQuery) GetFormattedCounterValueDouble(counterHandle PDH_
|
|||
}
|
||||
return 0, fmt.Errorf("GetFormattedCounterValueDouble: invalid handle: %d", counterHandle)
|
||||
}
|
||||
|
||||
func (m *FakePerformanceQuery) GetRawCounterValue(counterHandle PDH_HCOUNTER) (int64, error) {
|
||||
if !m.openCalled {
|
||||
return 0, errors.New("GetRawCounterValue: uninitialised query")
|
||||
}
|
||||
for _, counter := range m.counters {
|
||||
if counter.handle == counterHandle {
|
||||
if counter.status > 0 {
|
||||
return 0, NewPdhError(counter.status)
|
||||
}
|
||||
return int64(counter.value), nil
|
||||
}
|
||||
}
|
||||
return 0, fmt.Errorf("GetRawCounterValue: invalid handle: %d", counterHandle)
|
||||
}
|
||||
|
||||
func (m *FakePerformanceQuery) findCounterByPath(counterPath string) *testCounter {
|
||||
for _, c := range m.counters {
|
||||
if c.path == counterPath {
|
||||
|
|
@ -142,7 +166,7 @@ func (m *FakePerformanceQuery) GetFormattedCounterArrayDouble(hCounter PDH_HCOUN
|
|||
if counter.status > 0 {
|
||||
return nil, NewPdhError(counter.status)
|
||||
}
|
||||
counters = append(counters, *counter.ToCounterValue())
|
||||
counters = append(counters, *counter.ToCounterValue(false))
|
||||
} else {
|
||||
return nil, fmt.Errorf("GetFormattedCounterArrayDouble: invalid counter : %s", p)
|
||||
}
|
||||
|
|
@ -156,6 +180,34 @@ func (m *FakePerformanceQuery) GetFormattedCounterArrayDouble(hCounter PDH_HCOUN
|
|||
return nil, fmt.Errorf("GetFormattedCounterArrayDouble: invalid counter : %d, no paths found", hCounter)
|
||||
}
|
||||
|
||||
func (m *FakePerformanceQuery) GetRawCounterArray(hCounter PDH_HCOUNTER) ([]CounterValue, error) {
|
||||
if !m.openCalled {
|
||||
return nil, errors.New("GetRawCounterArray: 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 {
|
||||
if counter.status > 0 {
|
||||
return nil, NewPdhError(counter.status)
|
||||
}
|
||||
counters = append(counters, *counter.ToCounterValue(true))
|
||||
} else {
|
||||
return nil, fmt.Errorf("GetRawCounterArray: invalid counter : %s", p)
|
||||
}
|
||||
}
|
||||
return counters, nil
|
||||
} else {
|
||||
return nil, fmt.Errorf("GetRawCounterArray: invalid counter : %d", hCounter)
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil, fmt.Errorf("GetRawCounterArray: invalid counter : %d, no paths found", hCounter)
|
||||
}
|
||||
|
||||
func (m *FakePerformanceQuery) CollectData() error {
|
||||
if !m.openCalled {
|
||||
return errors.New("CollectData: uninitialized query")
|
||||
|
|
@ -174,7 +226,7 @@ func (m *FakePerformanceQuery) IsVistaOrNewer() bool {
|
|||
return m.vistaAndNewer
|
||||
}
|
||||
|
||||
func createPerfObject(measurement string, object string, instances []string, counters []string, failOnMissing bool, includeTotal bool) []perfobject {
|
||||
func createPerfObject(measurement string, object string, instances []string, counters []string, failOnMissing, includeTotal, useRawValues bool) []perfobject {
|
||||
PerfObject := perfobject{
|
||||
ObjectName: object,
|
||||
Instances: instances,
|
||||
|
|
@ -183,6 +235,7 @@ func createPerfObject(measurement string, object string, instances []string, cou
|
|||
WarnOnMissing: false,
|
||||
FailOnMissing: failOnMissing,
|
||||
IncludeTotal: includeTotal,
|
||||
UseRawValues: useRawValues,
|
||||
}
|
||||
perfobjects := []perfobject{PerfObject}
|
||||
return perfobjects
|
||||
|
|
@ -261,7 +314,7 @@ func TestAddItemSimple(t *testing.T) {
|
|||
}}
|
||||
err = m.query.Open()
|
||||
require.NoError(t, err)
|
||||
err = m.AddItem(cps1[0], "O", "I", "c", "test", false)
|
||||
err = m.AddItem(cps1[0], "O", "I", "c", "test", false, true)
|
||||
require.NoError(t, err)
|
||||
err = m.query.Close()
|
||||
require.NoError(t, err)
|
||||
|
|
@ -284,7 +337,7 @@ func TestAddItemInvalidCountPath(t *testing.T) {
|
|||
}}
|
||||
err = m.query.Open()
|
||||
require.NoError(t, err)
|
||||
err = m.AddItem("\\O\\C", "O", "------", "C", "test", false)
|
||||
err = m.AddItem("\\O\\C", "O", "------", "C", "test", false, false)
|
||||
require.Error(t, err)
|
||||
err = m.query.Close()
|
||||
require.NoError(t, err)
|
||||
|
|
@ -292,7 +345,7 @@ func TestAddItemInvalidCountPath(t *testing.T) {
|
|||
|
||||
func TestParseConfigBasic(t *testing.T) {
|
||||
var err error
|
||||
perfObjects := createPerfObject("m", "O", []string{"I1", "I2"}, []string{"C1", "C2"}, false, false)
|
||||
perfObjects := createPerfObject("m", "O", []string{"I1", "I2"}, []string{"C1", "C2"}, false, false, false)
|
||||
cps1 := []string{"\\O(I1)\\C1", "\\O(I1)\\C2", "\\O(I2)\\C1", "\\O(I2)\\C2"}
|
||||
m := Win_PerfCounters{
|
||||
Log: testutil.Logger{},
|
||||
|
|
@ -330,7 +383,7 @@ func TestParseConfigBasic(t *testing.T) {
|
|||
|
||||
func TestParseConfigNoInstance(t *testing.T) {
|
||||
var err error
|
||||
perfObjects := createPerfObject("m", "O", []string{"------"}, []string{"C1", "C2"}, false, false)
|
||||
perfObjects := createPerfObject("m", "O", []string{"------"}, []string{"C1", "C2"}, false, false, false)
|
||||
cps1 := []string{"\\O\\C1", "\\O\\C2"}
|
||||
m := Win_PerfCounters{
|
||||
Log: testutil.Logger{},
|
||||
|
|
@ -367,7 +420,7 @@ func TestParseConfigNoInstance(t *testing.T) {
|
|||
|
||||
func TestParseConfigInvalidCounterError(t *testing.T) {
|
||||
var err error
|
||||
perfObjects := createPerfObject("m", "O", []string{"I1", "I2"}, []string{"C1", "C2"}, true, false)
|
||||
perfObjects := createPerfObject("m", "O", []string{"I1", "I2"}, []string{"C1", "C2"}, true, false, false)
|
||||
cps1 := []string{"\\O(I1)\\C2", "\\O(I2)\\C1", "\\O(I2)\\C2"}
|
||||
m := Win_PerfCounters{
|
||||
Log: testutil.Logger{},
|
||||
|
|
@ -402,7 +455,7 @@ func TestParseConfigInvalidCounterError(t *testing.T) {
|
|||
|
||||
func TestParseConfigInvalidCounterNoError(t *testing.T) {
|
||||
var err error
|
||||
perfObjects := createPerfObject("m", "O", []string{"I1", "I2"}, []string{"C1", "C2"}, false, false)
|
||||
perfObjects := createPerfObject("m", "O", []string{"I1", "I2"}, []string{"C1", "C2"}, false, false, false)
|
||||
cps1 := []string{"\\O(I1)\\C2", "\\O(I2)\\C1", "\\O(I2)\\C2"}
|
||||
m := Win_PerfCounters{
|
||||
Log: testutil.Logger{},
|
||||
|
|
@ -438,7 +491,7 @@ func TestParseConfigInvalidCounterNoError(t *testing.T) {
|
|||
|
||||
func TestParseConfigTotalExpansion(t *testing.T) {
|
||||
var err error
|
||||
perfObjects := createPerfObject("m", "O", []string{"*"}, []string{"*"}, true, true)
|
||||
perfObjects := createPerfObject("m", "O", []string{"*"}, []string{"*"}, true, true, false)
|
||||
cps1 := []string{"\\O(I1)\\C1", "\\O(I1)\\C2", "\\O(_Total)\\C1", "\\O(_Total)\\C2"}
|
||||
m := Win_PerfCounters{
|
||||
Log: testutil.Logger{},
|
||||
|
|
@ -485,7 +538,7 @@ func TestParseConfigTotalExpansion(t *testing.T) {
|
|||
|
||||
func TestParseConfigExpand(t *testing.T) {
|
||||
var err error
|
||||
perfObjects := createPerfObject("m", "O", []string{"*"}, []string{"*"}, false, false)
|
||||
perfObjects := createPerfObject("m", "O", []string{"*"}, []string{"*"}, false, false, false)
|
||||
cps1 := []string{"\\O(I1)\\C1", "\\O(I1)\\C2", "\\O(I2)\\C1", "\\O(I2)\\C2"}
|
||||
m := Win_PerfCounters{
|
||||
Log: testutil.Logger{},
|
||||
|
|
@ -514,7 +567,7 @@ func TestSimpleGather(t *testing.T) {
|
|||
t.Skip("Skipping long taking test in short mode")
|
||||
}
|
||||
measurement := "test"
|
||||
perfObjects := createPerfObject(measurement, "O", []string{"I"}, []string{"C"}, false, false)
|
||||
perfObjects := createPerfObject(measurement, "O", []string{"I"}, []string{"C"}, false, false, false)
|
||||
cp1 := "\\O(I)\\C"
|
||||
m := Win_PerfCounters{
|
||||
Log: testutil.Logger{},
|
||||
|
|
@ -532,7 +585,7 @@ func TestSimpleGather(t *testing.T) {
|
|||
require.NoError(t, err)
|
||||
|
||||
fields1 := map[string]interface{}{
|
||||
"C": float32(1.2),
|
||||
"C": 1.2,
|
||||
}
|
||||
tags1 := map[string]string{
|
||||
"instance": "I",
|
||||
|
|
@ -557,7 +610,7 @@ func TestSimpleGatherNoData(t *testing.T) {
|
|||
t.Skip("Skipping long taking test in short mode")
|
||||
}
|
||||
measurement := "test"
|
||||
perfObjects := createPerfObject(measurement, "O", []string{"I"}, []string{"C"}, false, false)
|
||||
perfObjects := createPerfObject(measurement, "O", []string{"I"}, []string{"C"}, false, false, false)
|
||||
cp1 := "\\O(I)\\C"
|
||||
m := Win_PerfCounters{
|
||||
Log: testutil.Logger{},
|
||||
|
|
@ -577,7 +630,7 @@ func TestSimpleGatherNoData(t *testing.T) {
|
|||
|
||||
// fields would contain if the error was ignored, and we simply added garbage
|
||||
fields1 := map[string]interface{}{
|
||||
"C": float32(1.2),
|
||||
"C": 1.2,
|
||||
}
|
||||
// tags would contain if the error was ignored, and we simply added garbage
|
||||
tags1 := map[string]string{
|
||||
|
|
@ -603,7 +656,7 @@ func TestSimpleGatherWithTimestamp(t *testing.T) {
|
|||
t.Skip("Skipping long taking test in short mode")
|
||||
}
|
||||
measurement := "test"
|
||||
perfObjects := createPerfObject(measurement, "O", []string{"I"}, []string{"C"}, false, false)
|
||||
perfObjects := createPerfObject(measurement, "O", []string{"I"}, []string{"C"}, false, false, false)
|
||||
cp1 := "\\O(I)\\C"
|
||||
m := Win_PerfCounters{
|
||||
Log: testutil.Logger{},
|
||||
|
|
@ -622,7 +675,7 @@ func TestSimpleGatherWithTimestamp(t *testing.T) {
|
|||
require.NoError(t, err)
|
||||
|
||||
fields1 := map[string]interface{}{
|
||||
"C": float32(1.2),
|
||||
"C": 1.2,
|
||||
}
|
||||
tags1 := map[string]string{
|
||||
"instance": "I",
|
||||
|
|
@ -634,12 +687,12 @@ func TestSimpleGatherWithTimestamp(t *testing.T) {
|
|||
|
||||
func TestGatherError(t *testing.T) {
|
||||
var err error
|
||||
expected_error := "error while getting value for counter \\O(I)\\C: The information passed is not valid.\r\n"
|
||||
expectedError := "error while getting value for counter \\O(I)\\C: The information passed is not valid.\r\n"
|
||||
if testing.Short() {
|
||||
t.Skip("Skipping long taking test in short mode")
|
||||
}
|
||||
measurement := "test"
|
||||
perfObjects := createPerfObject(measurement, "O", []string{"I"}, []string{"C"}, false, false)
|
||||
perfObjects := createPerfObject(measurement, "O", []string{"I"}, []string{"C"}, false, false, false)
|
||||
cp1 := "\\O(I)\\C"
|
||||
m := Win_PerfCounters{
|
||||
Log: testutil.Logger{},
|
||||
|
|
@ -655,7 +708,7 @@ func TestGatherError(t *testing.T) {
|
|||
var acc1 testutil.Accumulator
|
||||
err = m.Gather(&acc1)
|
||||
require.Error(t, err)
|
||||
require.Equal(t, expected_error, err.Error())
|
||||
require.Equal(t, expectedError, err.Error())
|
||||
|
||||
m.UseWildcardsExpansion = true
|
||||
m.counters = nil
|
||||
|
|
@ -665,7 +718,7 @@ func TestGatherError(t *testing.T) {
|
|||
|
||||
err = m.Gather(&acc2)
|
||||
require.Error(t, err)
|
||||
require.Equal(t, expected_error, err.Error())
|
||||
require.Equal(t, expectedError, err.Error())
|
||||
}
|
||||
|
||||
func TestGatherInvalidDataIgnore(t *testing.T) {
|
||||
|
|
@ -674,7 +727,7 @@ func TestGatherInvalidDataIgnore(t *testing.T) {
|
|||
t.Skip("Skipping long taking test in short mode")
|
||||
}
|
||||
measurement := "test"
|
||||
perfObjects := createPerfObject(measurement, "O", []string{"I"}, []string{"C1", "C2", "C3"}, false, false)
|
||||
perfObjects := createPerfObject(measurement, "O", []string{"I"}, []string{"C1", "C2", "C3"}, false, false, false)
|
||||
cps1 := []string{"\\O(I)\\C1", "\\O(I)\\C2", "\\O(I)\\C3"}
|
||||
m := Win_PerfCounters{
|
||||
Log: testutil.Logger{},
|
||||
|
|
@ -694,8 +747,8 @@ func TestGatherInvalidDataIgnore(t *testing.T) {
|
|||
require.NoError(t, err)
|
||||
|
||||
fields1 := map[string]interface{}{
|
||||
"C1": float32(1.2),
|
||||
"C3": float32(0),
|
||||
"C1": 1.2,
|
||||
"C3": float64(0),
|
||||
}
|
||||
tags1 := map[string]string{
|
||||
"instance": "I",
|
||||
|
|
@ -720,7 +773,7 @@ func TestGatherRefreshingWithExpansion(t *testing.T) {
|
|||
t.Skip("Skipping long taking test in short mode")
|
||||
}
|
||||
measurement := "test"
|
||||
perfObjects := createPerfObject(measurement, "O", []string{"*"}, []string{"*"}, true, false)
|
||||
perfObjects := createPerfObject(measurement, "O", []string{"*"}, []string{"*"}, true, false, false)
|
||||
cps1 := []string{"\\O(I1)\\C1", "\\O(I1)\\C2", "\\O(I2)\\C1", "\\O(I2)\\C2"}
|
||||
fpm := &FakePerformanceQuery{
|
||||
counters: createCounterMap(append(cps1, "\\O(*)\\*"), []float64{1.1, 1.2, 1.3, 1.4, 0}, []uint32{0, 0, 0, 0, 0}),
|
||||
|
|
@ -730,12 +783,13 @@ func TestGatherRefreshingWithExpansion(t *testing.T) {
|
|||
vistaAndNewer: true,
|
||||
}
|
||||
m := Win_PerfCounters{
|
||||
Log: testutil.Logger{},
|
||||
PrintValid: false,
|
||||
Object: perfObjects,
|
||||
UseWildcardsExpansion: true,
|
||||
query: fpm,
|
||||
CountersRefreshInterval: config.Duration(time.Second * 10),
|
||||
Log: testutil.Logger{},
|
||||
PrintValid: false,
|
||||
Object: perfObjects,
|
||||
UseWildcardsExpansion: true,
|
||||
query: fpm,
|
||||
CountersRefreshInterval: config.Duration(time.Second * 10),
|
||||
LocalizeWildcardsExpansion: true,
|
||||
}
|
||||
var acc1 testutil.Accumulator
|
||||
err = m.Gather(&acc1)
|
||||
|
|
@ -744,8 +798,8 @@ func TestGatherRefreshingWithExpansion(t *testing.T) {
|
|||
require.Len(t, acc1.Metrics, 2)
|
||||
|
||||
fields1 := map[string]interface{}{
|
||||
"C1": float32(1.1),
|
||||
"C2": float32(1.2),
|
||||
"C1": 1.1,
|
||||
"C2": 1.2,
|
||||
}
|
||||
tags1 := map[string]string{
|
||||
"instance": "I1",
|
||||
|
|
@ -754,8 +808,8 @@ func TestGatherRefreshingWithExpansion(t *testing.T) {
|
|||
acc1.AssertContainsTaggedFields(t, measurement, fields1, tags1)
|
||||
|
||||
fields2 := map[string]interface{}{
|
||||
"C1": float32(1.3),
|
||||
"C2": float32(1.4),
|
||||
"C1": 1.3,
|
||||
"C2": 1.4,
|
||||
}
|
||||
tags2 := map[string]string{
|
||||
"instance": "I2",
|
||||
|
|
@ -771,12 +825,12 @@ func TestGatherRefreshingWithExpansion(t *testing.T) {
|
|||
vistaAndNewer: true,
|
||||
}
|
||||
m.query = fpm
|
||||
fpm.Open()
|
||||
_ = fpm.Open()
|
||||
var acc2 testutil.Accumulator
|
||||
|
||||
fields3 := map[string]interface{}{
|
||||
"C1": float32(1.5),
|
||||
"C2": float32(1.6),
|
||||
"C1": 1.5,
|
||||
"C2": 1.6,
|
||||
}
|
||||
tags3 := map[string]string{
|
||||
"instance": "I3",
|
||||
|
|
@ -812,7 +866,7 @@ func TestGatherRefreshingWithoutExpansion(t *testing.T) {
|
|||
t.Skip("Skipping long taking test in short mode")
|
||||
}
|
||||
measurement := "test"
|
||||
perfObjects := createPerfObject(measurement, "O", []string{"*"}, []string{"C1", "C2"}, true, false)
|
||||
perfObjects := createPerfObject(measurement, "O", []string{"*"}, []string{"C1", "C2"}, true, false, 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}, []uint32{0, 0, 0, 0, 0, 0}),
|
||||
|
|
@ -836,8 +890,8 @@ func TestGatherRefreshingWithoutExpansion(t *testing.T) {
|
|||
require.Len(t, acc1.Metrics, 2)
|
||||
|
||||
fields1 := map[string]interface{}{
|
||||
"C1": float32(1.1),
|
||||
"C2": float32(1.2),
|
||||
"C1": 1.1,
|
||||
"C2": 1.2,
|
||||
}
|
||||
tags1 := map[string]string{
|
||||
"instance": "I1",
|
||||
|
|
@ -846,8 +900,8 @@ func TestGatherRefreshingWithoutExpansion(t *testing.T) {
|
|||
acc1.AssertContainsTaggedFields(t, measurement, fields1, tags1)
|
||||
|
||||
fields2 := map[string]interface{}{
|
||||
"C1": float32(1.3),
|
||||
"C2": float32(1.4),
|
||||
"C1": 1.3,
|
||||
"C2": 1.4,
|
||||
}
|
||||
tags2 := map[string]string{
|
||||
"instance": "I2",
|
||||
|
|
@ -865,12 +919,12 @@ func TestGatherRefreshingWithoutExpansion(t *testing.T) {
|
|||
vistaAndNewer: true,
|
||||
}
|
||||
m.query = fpm
|
||||
fpm.Open()
|
||||
_ = fpm.Open()
|
||||
var acc2 testutil.Accumulator
|
||||
|
||||
fields3 := map[string]interface{}{
|
||||
"C1": float32(1.5),
|
||||
"C2": float32(1.6),
|
||||
"C1": 1.5,
|
||||
"C2": 1.6,
|
||||
}
|
||||
tags3 := map[string]string{
|
||||
"instance": "I3",
|
||||
|
|
@ -887,7 +941,7 @@ func TestGatherRefreshingWithoutExpansion(t *testing.T) {
|
|||
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)
|
||||
perfObjects = createPerfObject(measurement, "O", []string{"*"}, []string{"C1", "C2", "C3"}, true, false, 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}, []uint32{0, 0, 0, 0, 0, 0, 0, 0, 0}),
|
||||
|
|
@ -901,7 +955,7 @@ func TestGatherRefreshingWithoutExpansion(t *testing.T) {
|
|||
m.query = fpm
|
||||
m.Object = perfObjects
|
||||
|
||||
fpm.Open()
|
||||
_ = fpm.Open()
|
||||
|
||||
time.Sleep(time.Duration(m.CountersRefreshInterval))
|
||||
|
||||
|
|
@ -910,18 +964,18 @@ func TestGatherRefreshingWithoutExpansion(t *testing.T) {
|
|||
require.NoError(t, err)
|
||||
require.Len(t, acc3.Metrics, 2)
|
||||
fields4 := map[string]interface{}{
|
||||
"C1": float32(1.1),
|
||||
"C2": float32(1.2),
|
||||
"C3": float32(1.3),
|
||||
"C1": 1.1,
|
||||
"C2": 1.2,
|
||||
"C3": 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),
|
||||
"C1": 1.4,
|
||||
"C2": 1.5,
|
||||
"C3": 1.6,
|
||||
}
|
||||
tags5 := map[string]string{
|
||||
"instance": "I2",
|
||||
|
|
@ -934,9 +988,12 @@ func TestGatherRefreshingWithoutExpansion(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestGatherTotalNoExpansion(t *testing.T) {
|
||||
if testing.Short() {
|
||||
t.Skip("Skipping long taking test in short mode")
|
||||
}
|
||||
var err error
|
||||
measurement := "m"
|
||||
perfObjects := createPerfObject(measurement, "O", []string{"*"}, []string{"C1", "C2"}, true, true)
|
||||
perfObjects := createPerfObject(measurement, "O", []string{"*"}, []string{"C1", "C2"}, true, true, false)
|
||||
cps1 := []string{"\\O(I1)\\C1", "\\O(I1)\\C2", "\\O(_Total)\\C1", "\\O(_Total)\\C2"}
|
||||
m := Win_PerfCounters{
|
||||
Log: testutil.Logger{},
|
||||
|
|
@ -957,8 +1014,8 @@ func TestGatherTotalNoExpansion(t *testing.T) {
|
|||
require.Len(t, m.counters, 2)
|
||||
require.Len(t, acc1.Metrics, 2)
|
||||
fields1 := map[string]interface{}{
|
||||
"C1": float32(1.1),
|
||||
"C2": float32(1.2),
|
||||
"C1": 1.1,
|
||||
"C2": 1.2,
|
||||
}
|
||||
tags1 := map[string]string{
|
||||
"instance": "I1",
|
||||
|
|
@ -967,8 +1024,8 @@ func TestGatherTotalNoExpansion(t *testing.T) {
|
|||
acc1.AssertContainsTaggedFields(t, measurement, fields1, tags1)
|
||||
|
||||
fields2 := map[string]interface{}{
|
||||
"C1": float32(1.3),
|
||||
"C2": float32(1.4),
|
||||
"C1": 1.3,
|
||||
"C2": 1.4,
|
||||
}
|
||||
tags2 := map[string]string{
|
||||
"instance": "_Total",
|
||||
|
|
@ -992,6 +1049,67 @@ func TestGatherTotalNoExpansion(t *testing.T) {
|
|||
acc2.AssertDoesNotContainsTaggedFields(t, measurement, fields2, tags2)
|
||||
}
|
||||
|
||||
func TestGatherRaw(t *testing.T) {
|
||||
if testing.Short() {
|
||||
t.Skip("Skipping long taking test in short mode")
|
||||
}
|
||||
var err error
|
||||
measurement := "m"
|
||||
perfObjects := createPerfObject(measurement, "O", []string{"*"}, []string{"C1", "C2"}, true, true, true)
|
||||
cps1 := []string{"\\O(I1)\\C1", "\\O(I1)\\C2", "\\O(_Total)\\C1", "\\O(_Total)\\C2"}
|
||||
m := Win_PerfCounters{
|
||||
Log: testutil.Logger{},
|
||||
PrintValid: false,
|
||||
UseWildcardsExpansion: false,
|
||||
Object: perfObjects,
|
||||
query: &FakePerformanceQuery{
|
||||
counters: createCounterMap(append([]string{"\\O(*)\\C1", "\\O(*)\\C2"}, cps1...), []float64{0, 0, 1.1, 2.2, 3.3, 4.4}, []uint32{0, 0, 0, 0, 0, 0}),
|
||||
expandPaths: map[string][]string{
|
||||
"\\O(*)\\C1": {cps1[0], cps1[2]},
|
||||
"\\O(*)\\C2": {cps1[1], cps1[3]},
|
||||
},
|
||||
vistaAndNewer: 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_Raw": int64(1),
|
||||
"C2_Raw": int64(2),
|
||||
}
|
||||
tags1 := map[string]string{
|
||||
"instance": "I1",
|
||||
"objectname": "O",
|
||||
}
|
||||
acc1.AssertContainsTaggedFields(t, measurement, fields1, tags1)
|
||||
|
||||
fields2 := map[string]interface{}{
|
||||
"C1_Raw": int64(3),
|
||||
"C2_Raw": int64(4),
|
||||
}
|
||||
tags2 := map[string]string{
|
||||
"instance": "_Total",
|
||||
"objectname": "O",
|
||||
}
|
||||
acc1.AssertContainsTaggedFields(t, measurement, fields2, tags2)
|
||||
|
||||
m.UseWildcardsExpansion = true
|
||||
m.counters = nil
|
||||
m.lastRefreshed = time.Time{}
|
||||
|
||||
var acc2 testutil.Accumulator
|
||||
err = m.Gather(&acc2)
|
||||
require.NoError(t, err)
|
||||
assert.Len(t, m.counters, 4) //expanded counters
|
||||
assert.Len(t, acc2.Metrics, 2)
|
||||
|
||||
acc2.AssertContainsTaggedFields(t, measurement, fields1, tags1)
|
||||
|
||||
acc2.AssertContainsTaggedFields(t, measurement, fields2, tags2)
|
||||
}
|
||||
|
||||
// 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 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}
|
||||
|
|
@ -1027,14 +1145,14 @@ func TestUTF16ToStringArray(t *testing.T) {
|
|||
|
||||
func TestNoWildcards(t *testing.T) {
|
||||
m := Win_PerfCounters{
|
||||
Object: createPerfObject("measurement", "object", []string{"instance"}, []string{"counter*"}, false, false),
|
||||
Object: createPerfObject("measurement", "object", []string{"instance"}, []string{"counter*"}, false, false, false),
|
||||
UseWildcardsExpansion: true,
|
||||
LocalizeWildcardsExpansion: false,
|
||||
Log: testutil.Logger{},
|
||||
}
|
||||
require.Error(t, m.Init())
|
||||
m = Win_PerfCounters{
|
||||
Object: createPerfObject("measurement", "object?", []string{"instance"}, []string{"counter"}, false, false),
|
||||
Object: createPerfObject("measurement", "object?", []string{"instance"}, []string{"counter"}, false, false, false),
|
||||
UseWildcardsExpansion: true,
|
||||
LocalizeWildcardsExpansion: false,
|
||||
Log: testutil.Logger{},
|
||||
|
|
@ -1053,7 +1171,7 @@ func TestLocalizeWildcardsExpansion(t *testing.T) {
|
|||
query: &PerformanceQueryImpl{},
|
||||
CountersRefreshInterval: config.Duration(time.Second * 60),
|
||||
Object: createPerfObject("measurement", "Processor Information",
|
||||
[]string{"_Total"}, []string{counter}, false, false),
|
||||
[]string{"_Total"}, []string{counter}, false, false, false),
|
||||
LocalizeWildcardsExpansion: false,
|
||||
UseWildcardsExpansion: true,
|
||||
Log: testutil.Logger{},
|
||||
|
|
|
|||
Loading…
Reference in New Issue