parent
eb96443a34
commit
4e808c5c20
|
@ -29,6 +29,7 @@ in their config file.
|
||||||
- [#2078](https://github.com/influxdata/telegraf/pull/2078): Ping input: add standard deviation field.
|
- [#2078](https://github.com/influxdata/telegraf/pull/2078): Ping input: add standard deviation field.
|
||||||
- [#2121](https://github.com/influxdata/telegraf/pull/2121): Add GC pause metric to InfluxDB input plugin.
|
- [#2121](https://github.com/influxdata/telegraf/pull/2121): Add GC pause metric to InfluxDB input plugin.
|
||||||
- [#2006](https://github.com/influxdata/telegraf/pull/2006): Added response_timeout property to prometheus input plugin.
|
- [#2006](https://github.com/influxdata/telegraf/pull/2006): Added response_timeout property to prometheus input plugin.
|
||||||
|
- [#1763](https://github.com/influxdata/telegraf/issues/1763): Pulling github.com/lxn/win's pdh wrapper into telegraf
|
||||||
|
|
||||||
### Bugfixes
|
### Bugfixes
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
github.com/Microsoft/go-winio ce2922f643c8fd76b46cadc7f404a06282678b34
|
github.com/Microsoft/go-winio ce2922f643c8fd76b46cadc7f404a06282678b34
|
||||||
github.com/StackExchange/wmi f3e2bae1e0cb5aef83e319133eabfee30013a4a5
|
github.com/StackExchange/wmi f3e2bae1e0cb5aef83e319133eabfee30013a4a5
|
||||||
github.com/go-ole/go-ole be49f7c07711fcb603cff39e1de7c67926dc0ba7
|
github.com/go-ole/go-ole be49f7c07711fcb603cff39e1de7c67926dc0ba7
|
||||||
github.com/lxn/win 950a0e81e7678e63d8e6cd32412bdecb325ccd88
|
|
||||||
github.com/shirou/w32 3c9377fc6748f222729a8270fe2775d149a249ad
|
github.com/shirou/w32 3c9377fc6748f222729a8270fe2775d149a249ad
|
||||||
golang.org/x/sys a646d33e2ee3172a661fc09bca23bb4889a41bc8
|
golang.org/x/sys a646d33e2ee3172a661fc09bca23bb4889a41bc8
|
||||||
github.com/go-ini/ini 9144852efba7c4daf409943ee90767da62d55438
|
github.com/go-ini/ini 9144852efba7c4daf409943ee90767da62d55438
|
||||||
|
|
|
@ -0,0 +1,419 @@
|
||||||
|
// Copyright (c) 2010 The win Authors. All rights reserved.
|
||||||
|
//
|
||||||
|
// Redistribution and use in source and binary forms, with or without
|
||||||
|
// modification, are permitted provided that the following conditions
|
||||||
|
// are met:
|
||||||
|
// 1. Redistributions of source code must retain the above copyright
|
||||||
|
// notice, this list of conditions and the following disclaimer.
|
||||||
|
// 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
// notice, this list of conditions and the following disclaimer in the
|
||||||
|
// documentation and/or other materials provided with the distribution.
|
||||||
|
// 3. The names of the authors may not be used to endorse or promote products
|
||||||
|
// derived from this software without specific prior written permission.
|
||||||
|
//
|
||||||
|
// THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR
|
||||||
|
// IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||||
|
// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||||
|
// IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||||
|
// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||||
|
// NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||||
|
// THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
//
|
||||||
|
// This is the official list of 'win' authors for copyright purposes.
|
||||||
|
//
|
||||||
|
// Alexander Neumann <an2048@googlemail.com>
|
||||||
|
// Joseph Watson <jtwatson@linux-consulting.us>
|
||||||
|
// Kevin Pors <krpors@gmail.com>
|
||||||
|
|
||||||
|
// +build windows
|
||||||
|
|
||||||
|
package win_perf_counters
|
||||||
|
|
||||||
|
import (
|
||||||
|
"syscall"
|
||||||
|
"unsafe"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Error codes
|
||||||
|
const (
|
||||||
|
ERROR_SUCCESS = 0
|
||||||
|
ERROR_INVALID_FUNCTION = 1
|
||||||
|
)
|
||||||
|
|
||||||
|
type (
|
||||||
|
HANDLE uintptr
|
||||||
|
)
|
||||||
|
|
||||||
|
// PDH error codes, which can be returned by all Pdh* functions. Taken from mingw-w64 pdhmsg.h
|
||||||
|
const (
|
||||||
|
PDH_CSTATUS_VALID_DATA = 0x00000000 // The returned data is valid.
|
||||||
|
PDH_CSTATUS_NEW_DATA = 0x00000001 // The return data value is valid and different from the last sample.
|
||||||
|
PDH_CSTATUS_NO_MACHINE = 0x800007D0 // Unable to connect to the specified computer, or the computer is offline.
|
||||||
|
PDH_CSTATUS_NO_INSTANCE = 0x800007D1
|
||||||
|
PDH_MORE_DATA = 0x800007D2 // The PdhGetFormattedCounterArray* function can return this if there's 'more data to be displayed'.
|
||||||
|
PDH_CSTATUS_ITEM_NOT_VALIDATED = 0x800007D3
|
||||||
|
PDH_RETRY = 0x800007D4
|
||||||
|
PDH_NO_DATA = 0x800007D5 // The query does not currently contain any counters (for example, limited access)
|
||||||
|
PDH_CALC_NEGATIVE_DENOMINATOR = 0x800007D6
|
||||||
|
PDH_CALC_NEGATIVE_TIMEBASE = 0x800007D7
|
||||||
|
PDH_CALC_NEGATIVE_VALUE = 0x800007D8
|
||||||
|
PDH_DIALOG_CANCELLED = 0x800007D9
|
||||||
|
PDH_END_OF_LOG_FILE = 0x800007DA
|
||||||
|
PDH_ASYNC_QUERY_TIMEOUT = 0x800007DB
|
||||||
|
PDH_CANNOT_SET_DEFAULT_REALTIME_DATASOURCE = 0x800007DC
|
||||||
|
PDH_CSTATUS_NO_OBJECT = 0xC0000BB8
|
||||||
|
PDH_CSTATUS_NO_COUNTER = 0xC0000BB9 // The specified counter could not be found.
|
||||||
|
PDH_CSTATUS_INVALID_DATA = 0xC0000BBA // The counter was successfully found, but the data returned is not valid.
|
||||||
|
PDH_MEMORY_ALLOCATION_FAILURE = 0xC0000BBB
|
||||||
|
PDH_INVALID_HANDLE = 0xC0000BBC
|
||||||
|
PDH_INVALID_ARGUMENT = 0xC0000BBD // Required argument is missing or incorrect.
|
||||||
|
PDH_FUNCTION_NOT_FOUND = 0xC0000BBE
|
||||||
|
PDH_CSTATUS_NO_COUNTERNAME = 0xC0000BBF
|
||||||
|
PDH_CSTATUS_BAD_COUNTERNAME = 0xC0000BC0 // Unable to parse the counter path. Check the format and syntax of the specified path.
|
||||||
|
PDH_INVALID_BUFFER = 0xC0000BC1
|
||||||
|
PDH_INSUFFICIENT_BUFFER = 0xC0000BC2
|
||||||
|
PDH_CANNOT_CONNECT_MACHINE = 0xC0000BC3
|
||||||
|
PDH_INVALID_PATH = 0xC0000BC4
|
||||||
|
PDH_INVALID_INSTANCE = 0xC0000BC5
|
||||||
|
PDH_INVALID_DATA = 0xC0000BC6 // specified counter does not contain valid data or a successful status code.
|
||||||
|
PDH_NO_DIALOG_DATA = 0xC0000BC7
|
||||||
|
PDH_CANNOT_READ_NAME_STRINGS = 0xC0000BC8
|
||||||
|
PDH_LOG_FILE_CREATE_ERROR = 0xC0000BC9
|
||||||
|
PDH_LOG_FILE_OPEN_ERROR = 0xC0000BCA
|
||||||
|
PDH_LOG_TYPE_NOT_FOUND = 0xC0000BCB
|
||||||
|
PDH_NO_MORE_DATA = 0xC0000BCC
|
||||||
|
PDH_ENTRY_NOT_IN_LOG_FILE = 0xC0000BCD
|
||||||
|
PDH_DATA_SOURCE_IS_LOG_FILE = 0xC0000BCE
|
||||||
|
PDH_DATA_SOURCE_IS_REAL_TIME = 0xC0000BCF
|
||||||
|
PDH_UNABLE_READ_LOG_HEADER = 0xC0000BD0
|
||||||
|
PDH_FILE_NOT_FOUND = 0xC0000BD1
|
||||||
|
PDH_FILE_ALREADY_EXISTS = 0xC0000BD2
|
||||||
|
PDH_NOT_IMPLEMENTED = 0xC0000BD3
|
||||||
|
PDH_STRING_NOT_FOUND = 0xC0000BD4
|
||||||
|
PDH_UNABLE_MAP_NAME_FILES = 0x80000BD5
|
||||||
|
PDH_UNKNOWN_LOG_FORMAT = 0xC0000BD6
|
||||||
|
PDH_UNKNOWN_LOGSVC_COMMAND = 0xC0000BD7
|
||||||
|
PDH_LOGSVC_QUERY_NOT_FOUND = 0xC0000BD8
|
||||||
|
PDH_LOGSVC_NOT_OPENED = 0xC0000BD9
|
||||||
|
PDH_WBEM_ERROR = 0xC0000BDA
|
||||||
|
PDH_ACCESS_DENIED = 0xC0000BDB
|
||||||
|
PDH_LOG_FILE_TOO_SMALL = 0xC0000BDC
|
||||||
|
PDH_INVALID_DATASOURCE = 0xC0000BDD
|
||||||
|
PDH_INVALID_SQLDB = 0xC0000BDE
|
||||||
|
PDH_NO_COUNTERS = 0xC0000BDF
|
||||||
|
PDH_SQL_ALLOC_FAILED = 0xC0000BE0
|
||||||
|
PDH_SQL_ALLOCCON_FAILED = 0xC0000BE1
|
||||||
|
PDH_SQL_EXEC_DIRECT_FAILED = 0xC0000BE2
|
||||||
|
PDH_SQL_FETCH_FAILED = 0xC0000BE3
|
||||||
|
PDH_SQL_ROWCOUNT_FAILED = 0xC0000BE4
|
||||||
|
PDH_SQL_MORE_RESULTS_FAILED = 0xC0000BE5
|
||||||
|
PDH_SQL_CONNECT_FAILED = 0xC0000BE6
|
||||||
|
PDH_SQL_BIND_FAILED = 0xC0000BE7
|
||||||
|
PDH_CANNOT_CONNECT_WMI_SERVER = 0xC0000BE8
|
||||||
|
PDH_PLA_COLLECTION_ALREADY_RUNNING = 0xC0000BE9
|
||||||
|
PDH_PLA_ERROR_SCHEDULE_OVERLAP = 0xC0000BEA
|
||||||
|
PDH_PLA_COLLECTION_NOT_FOUND = 0xC0000BEB
|
||||||
|
PDH_PLA_ERROR_SCHEDULE_ELAPSED = 0xC0000BEC
|
||||||
|
PDH_PLA_ERROR_NOSTART = 0xC0000BED
|
||||||
|
PDH_PLA_ERROR_ALREADY_EXISTS = 0xC0000BEE
|
||||||
|
PDH_PLA_ERROR_TYPE_MISMATCH = 0xC0000BEF
|
||||||
|
PDH_PLA_ERROR_FILEPATH = 0xC0000BF0
|
||||||
|
PDH_PLA_SERVICE_ERROR = 0xC0000BF1
|
||||||
|
PDH_PLA_VALIDATION_ERROR = 0xC0000BF2
|
||||||
|
PDH_PLA_VALIDATION_WARNING = 0x80000BF3
|
||||||
|
PDH_PLA_ERROR_NAME_TOO_LONG = 0xC0000BF4
|
||||||
|
PDH_INVALID_SQL_LOG_FORMAT = 0xC0000BF5
|
||||||
|
PDH_COUNTER_ALREADY_IN_QUERY = 0xC0000BF6
|
||||||
|
PDH_BINARY_LOG_CORRUPT = 0xC0000BF7
|
||||||
|
PDH_LOG_SAMPLE_TOO_SMALL = 0xC0000BF8
|
||||||
|
PDH_OS_LATER_VERSION = 0xC0000BF9
|
||||||
|
PDH_OS_EARLIER_VERSION = 0xC0000BFA
|
||||||
|
PDH_INCORRECT_APPEND_TIME = 0xC0000BFB
|
||||||
|
PDH_UNMATCHED_APPEND_COUNTER = 0xC0000BFC
|
||||||
|
PDH_SQL_ALTER_DETAIL_FAILED = 0xC0000BFD
|
||||||
|
PDH_QUERY_PERF_DATA_TIMEOUT = 0xC0000BFE
|
||||||
|
)
|
||||||
|
|
||||||
|
// Formatting options for GetFormattedCounterValue().
|
||||||
|
const (
|
||||||
|
PDH_FMT_RAW = 0x00000010
|
||||||
|
PDH_FMT_ANSI = 0x00000020
|
||||||
|
PDH_FMT_UNICODE = 0x00000040
|
||||||
|
PDH_FMT_LONG = 0x00000100 // Return data as a long int.
|
||||||
|
PDH_FMT_DOUBLE = 0x00000200 // Return data as a double precision floating point real.
|
||||||
|
PDH_FMT_LARGE = 0x00000400 // Return data as a 64 bit integer.
|
||||||
|
PDH_FMT_NOSCALE = 0x00001000 // can be OR-ed: Do not apply the counter's default scaling factor.
|
||||||
|
PDH_FMT_1000 = 0x00002000 // can be OR-ed: multiply the actual value by 1,000.
|
||||||
|
PDH_FMT_NODATA = 0x00004000 // can be OR-ed: unknown what this is for, MSDN says nothing.
|
||||||
|
PDH_FMT_NOCAP100 = 0x00008000 // can be OR-ed: do not cap values > 100.
|
||||||
|
PERF_DETAIL_COSTLY = 0x00010000
|
||||||
|
PERF_DETAIL_STANDARD = 0x0000FFFF
|
||||||
|
)
|
||||||
|
|
||||||
|
type (
|
||||||
|
PDH_HQUERY HANDLE // query handle
|
||||||
|
PDH_HCOUNTER HANDLE // counter handle
|
||||||
|
)
|
||||||
|
|
||||||
|
// Union specialization for double values
|
||||||
|
type PDH_FMT_COUNTERVALUE_DOUBLE struct {
|
||||||
|
CStatus uint32
|
||||||
|
DoubleValue float64
|
||||||
|
}
|
||||||
|
|
||||||
|
// Union specialization for 64 bit integer values
|
||||||
|
type PDH_FMT_COUNTERVALUE_LARGE struct {
|
||||||
|
CStatus uint32
|
||||||
|
LargeValue int64
|
||||||
|
}
|
||||||
|
|
||||||
|
// Union specialization for long values
|
||||||
|
type PDH_FMT_COUNTERVALUE_LONG struct {
|
||||||
|
CStatus uint32
|
||||||
|
LongValue int32
|
||||||
|
padding [4]byte
|
||||||
|
}
|
||||||
|
|
||||||
|
// Union specialization for double values, used by PdhGetFormattedCounterArrayDouble()
|
||||||
|
type PDH_FMT_COUNTERVALUE_ITEM_DOUBLE struct {
|
||||||
|
SzName *uint16 // pointer to a string
|
||||||
|
FmtValue PDH_FMT_COUNTERVALUE_DOUBLE
|
||||||
|
}
|
||||||
|
|
||||||
|
// Union specialization for 'large' values, used by PdhGetFormattedCounterArrayLarge()
|
||||||
|
type PDH_FMT_COUNTERVALUE_ITEM_LARGE struct {
|
||||||
|
SzName *uint16 // pointer to a string
|
||||||
|
FmtValue PDH_FMT_COUNTERVALUE_LARGE
|
||||||
|
}
|
||||||
|
|
||||||
|
// Union specialization for long values, used by PdhGetFormattedCounterArrayLong()
|
||||||
|
type PDH_FMT_COUNTERVALUE_ITEM_LONG struct {
|
||||||
|
SzName *uint16 // pointer to a string
|
||||||
|
FmtValue PDH_FMT_COUNTERVALUE_LONG
|
||||||
|
}
|
||||||
|
|
||||||
|
var (
|
||||||
|
// Library
|
||||||
|
libpdhDll *syscall.DLL
|
||||||
|
|
||||||
|
// Functions
|
||||||
|
pdh_AddCounterW *syscall.Proc
|
||||||
|
pdh_AddEnglishCounterW *syscall.Proc
|
||||||
|
pdh_CloseQuery *syscall.Proc
|
||||||
|
pdh_CollectQueryData *syscall.Proc
|
||||||
|
pdh_GetFormattedCounterValue *syscall.Proc
|
||||||
|
pdh_GetFormattedCounterArrayW *syscall.Proc
|
||||||
|
pdh_OpenQuery *syscall.Proc
|
||||||
|
pdh_ValidatePathW *syscall.Proc
|
||||||
|
)
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
// Library
|
||||||
|
libpdhDll = syscall.MustLoadDLL("pdh.dll")
|
||||||
|
|
||||||
|
// Functions
|
||||||
|
pdh_AddCounterW = libpdhDll.MustFindProc("PdhAddCounterW")
|
||||||
|
pdh_AddEnglishCounterW, _ = libpdhDll.FindProc("PdhAddEnglishCounterW") // XXX: only supported on versions > Vista.
|
||||||
|
pdh_CloseQuery = libpdhDll.MustFindProc("PdhCloseQuery")
|
||||||
|
pdh_CollectQueryData = libpdhDll.MustFindProc("PdhCollectQueryData")
|
||||||
|
pdh_GetFormattedCounterValue = libpdhDll.MustFindProc("PdhGetFormattedCounterValue")
|
||||||
|
pdh_GetFormattedCounterArrayW = libpdhDll.MustFindProc("PdhGetFormattedCounterArrayW")
|
||||||
|
pdh_OpenQuery = libpdhDll.MustFindProc("PdhOpenQuery")
|
||||||
|
pdh_ValidatePathW = libpdhDll.MustFindProc("PdhValidatePathW")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Adds the specified counter to the query. This is the internationalized version. Preferably, use the
|
||||||
|
// function PdhAddEnglishCounter instead. hQuery is the query handle, which has been fetched by PdhOpenQuery.
|
||||||
|
// szFullCounterPath is a full, internationalized counter path (this will differ per Windows language version).
|
||||||
|
// dwUserData is a 'user-defined value', which becomes part of the counter information. To retrieve this value
|
||||||
|
// later, call PdhGetCounterInfo() and access dwQueryUserData of the PDH_COUNTER_INFO structure.
|
||||||
|
//
|
||||||
|
// Examples of szFullCounterPath (in an English version of Windows):
|
||||||
|
//
|
||||||
|
// \\Processor(_Total)\\% Idle Time
|
||||||
|
// \\Processor(_Total)\\% Processor Time
|
||||||
|
// \\LogicalDisk(C:)\% Free Space
|
||||||
|
//
|
||||||
|
// To view all (internationalized...) counters on a system, there are three non-programmatic ways: perfmon utility,
|
||||||
|
// the typeperf command, and the the registry editor. perfmon.exe is perhaps the easiest way, because it's basically a
|
||||||
|
// full implemention of the pdh.dll API, except with a GUI and all that. The registry setting also provides an
|
||||||
|
// interface to the available counters, and can be found at the following key:
|
||||||
|
//
|
||||||
|
// HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Perflib\CurrentLanguage
|
||||||
|
//
|
||||||
|
// This registry key contains several values as follows:
|
||||||
|
//
|
||||||
|
// 1
|
||||||
|
// 1847
|
||||||
|
// 2
|
||||||
|
// System
|
||||||
|
// 4
|
||||||
|
// Memory
|
||||||
|
// 6
|
||||||
|
// % Processor Time
|
||||||
|
// ... many, many more
|
||||||
|
//
|
||||||
|
// Somehow, these numeric values can be used as szFullCounterPath too:
|
||||||
|
//
|
||||||
|
// \2\6 will correspond to \\System\% Processor Time
|
||||||
|
//
|
||||||
|
// The typeperf command may also be pretty easy. To find all performance counters, simply execute:
|
||||||
|
//
|
||||||
|
// typeperf -qx
|
||||||
|
func PdhAddCounter(hQuery PDH_HQUERY, szFullCounterPath string, dwUserData uintptr, phCounter *PDH_HCOUNTER) uint32 {
|
||||||
|
ptxt, _ := syscall.UTF16PtrFromString(szFullCounterPath)
|
||||||
|
ret, _, _ := pdh_AddCounterW.Call(
|
||||||
|
uintptr(hQuery),
|
||||||
|
uintptr(unsafe.Pointer(ptxt)),
|
||||||
|
dwUserData,
|
||||||
|
uintptr(unsafe.Pointer(phCounter)))
|
||||||
|
|
||||||
|
return uint32(ret)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Adds the specified language-neutral counter to the query. See the PdhAddCounter function. This function only exists on
|
||||||
|
// Windows versions higher than Vista.
|
||||||
|
func PdhAddEnglishCounter(hQuery PDH_HQUERY, szFullCounterPath string, dwUserData uintptr, phCounter *PDH_HCOUNTER) uint32 {
|
||||||
|
if pdh_AddEnglishCounterW == nil {
|
||||||
|
return ERROR_INVALID_FUNCTION
|
||||||
|
}
|
||||||
|
|
||||||
|
ptxt, _ := syscall.UTF16PtrFromString(szFullCounterPath)
|
||||||
|
ret, _, _ := pdh_AddEnglishCounterW.Call(
|
||||||
|
uintptr(hQuery),
|
||||||
|
uintptr(unsafe.Pointer(ptxt)),
|
||||||
|
dwUserData,
|
||||||
|
uintptr(unsafe.Pointer(phCounter)))
|
||||||
|
|
||||||
|
return uint32(ret)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Closes all counters contained in the specified query, closes all handles related to the query,
|
||||||
|
// and frees all memory associated with the query.
|
||||||
|
func PdhCloseQuery(hQuery PDH_HQUERY) uint32 {
|
||||||
|
ret, _, _ := pdh_CloseQuery.Call(uintptr(hQuery))
|
||||||
|
|
||||||
|
return uint32(ret)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Collects the current raw data value for all counters in the specified query and updates the status
|
||||||
|
// code of each counter. With some counters, this function needs to be repeatedly called before the value
|
||||||
|
// of the counter can be extracted with PdhGetFormattedCounterValue(). For example, the following code
|
||||||
|
// requires at least two calls:
|
||||||
|
//
|
||||||
|
// var handle win.PDH_HQUERY
|
||||||
|
// var counterHandle win.PDH_HCOUNTER
|
||||||
|
// ret := win.PdhOpenQuery(0, 0, &handle)
|
||||||
|
// ret = win.PdhAddEnglishCounter(handle, "\\Processor(_Total)\\% Idle Time", 0, &counterHandle)
|
||||||
|
// var derp win.PDH_FMT_COUNTERVALUE_DOUBLE
|
||||||
|
//
|
||||||
|
// ret = win.PdhCollectQueryData(handle)
|
||||||
|
// fmt.Printf("Collect return code is %x\n", ret) // return code will be PDH_CSTATUS_INVALID_DATA
|
||||||
|
// ret = win.PdhGetFormattedCounterValueDouble(counterHandle, 0, &derp)
|
||||||
|
//
|
||||||
|
// ret = win.PdhCollectQueryData(handle)
|
||||||
|
// fmt.Printf("Collect return code is %x\n", ret) // return code will be ERROR_SUCCESS
|
||||||
|
// ret = win.PdhGetFormattedCounterValueDouble(counterHandle, 0, &derp)
|
||||||
|
//
|
||||||
|
// The PdhCollectQueryData will return an error in the first call because it needs two values for
|
||||||
|
// displaying the correct data for the processor idle time. The second call will have a 0 return code.
|
||||||
|
func PdhCollectQueryData(hQuery PDH_HQUERY) uint32 {
|
||||||
|
ret, _, _ := pdh_CollectQueryData.Call(uintptr(hQuery))
|
||||||
|
|
||||||
|
return uint32(ret)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Formats the given hCounter using a 'double'. The result is set into the specialized union struct pValue.
|
||||||
|
// This function does not directly translate to a Windows counterpart due to union specialization tricks.
|
||||||
|
func PdhGetFormattedCounterValueDouble(hCounter PDH_HCOUNTER, lpdwType *uint32, pValue *PDH_FMT_COUNTERVALUE_DOUBLE) uint32 {
|
||||||
|
ret, _, _ := pdh_GetFormattedCounterValue.Call(
|
||||||
|
uintptr(hCounter),
|
||||||
|
uintptr(PDH_FMT_DOUBLE),
|
||||||
|
uintptr(unsafe.Pointer(lpdwType)),
|
||||||
|
uintptr(unsafe.Pointer(pValue)))
|
||||||
|
|
||||||
|
return uint32(ret)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Returns an array of formatted counter values. Use this function when you want to format the counter values of a
|
||||||
|
// counter that contains a wildcard character for the instance name. The itemBuffer must a slice of type PDH_FMT_COUNTERVALUE_ITEM_DOUBLE.
|
||||||
|
// An example of how this function can be used:
|
||||||
|
//
|
||||||
|
// okPath := "\\Process(*)\\% Processor Time" // notice the wildcard * character
|
||||||
|
//
|
||||||
|
// // ommitted all necessary stuff ...
|
||||||
|
//
|
||||||
|
// var bufSize uint32
|
||||||
|
// var bufCount uint32
|
||||||
|
// var size uint32 = uint32(unsafe.Sizeof(win.PDH_FMT_COUNTERVALUE_ITEM_DOUBLE{}))
|
||||||
|
// var emptyBuf [1]win.PDH_FMT_COUNTERVALUE_ITEM_DOUBLE // need at least 1 addressable null ptr.
|
||||||
|
//
|
||||||
|
// for {
|
||||||
|
// // collect
|
||||||
|
// ret := win.PdhCollectQueryData(queryHandle)
|
||||||
|
// if ret == win.ERROR_SUCCESS {
|
||||||
|
// ret = win.PdhGetFormattedCounterArrayDouble(counterHandle, &bufSize, &bufCount, &emptyBuf[0]) // uses null ptr here according to MSDN.
|
||||||
|
// if ret == win.PDH_MORE_DATA {
|
||||||
|
// filledBuf := make([]win.PDH_FMT_COUNTERVALUE_ITEM_DOUBLE, bufCount*size)
|
||||||
|
// ret = win.PdhGetFormattedCounterArrayDouble(counterHandle, &bufSize, &bufCount, &filledBuf[0])
|
||||||
|
// for i := 0; i < int(bufCount); i++ {
|
||||||
|
// c := filledBuf[i]
|
||||||
|
// var s string = win.UTF16PtrToString(c.SzName)
|
||||||
|
// fmt.Printf("Index %d -> %s, value %v\n", i, s, c.FmtValue.DoubleValue)
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// filledBuf = nil
|
||||||
|
// // Need to at least set bufSize to zero, because if not, the function will not
|
||||||
|
// // return PDH_MORE_DATA and will not set the bufSize.
|
||||||
|
// bufCount = 0
|
||||||
|
// bufSize = 0
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// time.Sleep(2000 * time.Millisecond)
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
func PdhGetFormattedCounterArrayDouble(hCounter PDH_HCOUNTER, lpdwBufferSize *uint32, lpdwBufferCount *uint32, itemBuffer *PDH_FMT_COUNTERVALUE_ITEM_DOUBLE) uint32 {
|
||||||
|
ret, _, _ := pdh_GetFormattedCounterArrayW.Call(
|
||||||
|
uintptr(hCounter),
|
||||||
|
uintptr(PDH_FMT_DOUBLE),
|
||||||
|
uintptr(unsafe.Pointer(lpdwBufferSize)),
|
||||||
|
uintptr(unsafe.Pointer(lpdwBufferCount)),
|
||||||
|
uintptr(unsafe.Pointer(itemBuffer)))
|
||||||
|
|
||||||
|
return uint32(ret)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Creates a new query that is used to manage the collection of performance data.
|
||||||
|
// szDataSource is a null terminated string that specifies the name of the log file from which to
|
||||||
|
// retrieve the performance data. If 0, performance data is collected from a real-time data source.
|
||||||
|
// dwUserData is a user-defined value to associate with this query. To retrieve the user data later,
|
||||||
|
// call PdhGetCounterInfo and access dwQueryUserData of the PDH_COUNTER_INFO structure. phQuery is
|
||||||
|
// the handle to the query, and must be used in subsequent calls. This function returns a PDH_
|
||||||
|
// constant error code, or ERROR_SUCCESS if the call succeeded.
|
||||||
|
func PdhOpenQuery(szDataSource uintptr, dwUserData uintptr, phQuery *PDH_HQUERY) uint32 {
|
||||||
|
ret, _, _ := pdh_OpenQuery.Call(
|
||||||
|
szDataSource,
|
||||||
|
dwUserData,
|
||||||
|
uintptr(unsafe.Pointer(phQuery)))
|
||||||
|
|
||||||
|
return uint32(ret)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Validates a path. Will return ERROR_SUCCESS when ok, or PDH_CSTATUS_BAD_COUNTERNAME when the path is
|
||||||
|
// erroneous.
|
||||||
|
func PdhValidatePath(path string) uint32 {
|
||||||
|
ptxt, _ := syscall.UTF16PtrFromString(path)
|
||||||
|
ret, _, _ := pdh_ValidatePathW.Call(uintptr(unsafe.Pointer(ptxt)))
|
||||||
|
|
||||||
|
return uint32(ret)
|
||||||
|
}
|
||||||
|
|
||||||
|
func UTF16PtrToString(s *uint16) string {
|
||||||
|
if s == nil {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
return syscall.UTF16ToString((*[1 << 29]uint16)(unsafe.Pointer(s))[0:])
|
||||||
|
}
|
|
@ -10,7 +10,6 @@ import (
|
||||||
|
|
||||||
"github.com/influxdata/telegraf"
|
"github.com/influxdata/telegraf"
|
||||||
"github.com/influxdata/telegraf/plugins/inputs"
|
"github.com/influxdata/telegraf/plugins/inputs"
|
||||||
"github.com/lxn/win"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
var sampleConfig string = `
|
var sampleConfig string = `
|
||||||
|
@ -103,8 +102,8 @@ type item struct {
|
||||||
instance string
|
instance string
|
||||||
measurement string
|
measurement string
|
||||||
include_total bool
|
include_total bool
|
||||||
handle win.PDH_HQUERY
|
handle PDH_HQUERY
|
||||||
counterHandle win.PDH_HCOUNTER
|
counterHandle PDH_HCOUNTER
|
||||||
}
|
}
|
||||||
|
|
||||||
var sanitizedChars = strings.NewReplacer("/sec", "_persec", "/Sec", "_persec",
|
var sanitizedChars = strings.NewReplacer("/sec", "_persec", "/Sec", "_persec",
|
||||||
|
@ -113,10 +112,10 @@ var sanitizedChars = strings.NewReplacer("/sec", "_persec", "/Sec", "_persec",
|
||||||
func (m *Win_PerfCounters) AddItem(metrics *itemList, query string, objectName string, counter string, instance string,
|
func (m *Win_PerfCounters) AddItem(metrics *itemList, query string, objectName string, counter string, instance string,
|
||||||
measurement string, include_total bool) {
|
measurement string, include_total bool) {
|
||||||
|
|
||||||
var handle win.PDH_HQUERY
|
var handle PDH_HQUERY
|
||||||
var counterHandle win.PDH_HCOUNTER
|
var counterHandle PDH_HCOUNTER
|
||||||
ret := win.PdhOpenQuery(0, 0, &handle)
|
ret := PdhOpenQuery(0, 0, &handle)
|
||||||
ret = win.PdhAddCounter(handle, query, 0, &counterHandle)
|
ret = PdhAddCounter(handle, query, 0, &counterHandle)
|
||||||
_ = ret
|
_ = ret
|
||||||
|
|
||||||
temp := &item{query, objectName, counter, instance, measurement,
|
temp := &item{query, objectName, counter, instance, measurement,
|
||||||
|
@ -131,14 +130,14 @@ func (m *Win_PerfCounters) AddItem(metrics *itemList, query string, objectName s
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *Win_PerfCounters) InvalidObject(exists uint32, query string, PerfObject perfobject, instance string, counter string) error {
|
func (m *Win_PerfCounters) InvalidObject(exists uint32, query string, PerfObject perfobject, instance string, counter string) error {
|
||||||
if exists == 3221228472 { // win.PDH_CSTATUS_NO_OBJECT
|
if exists == 3221228472 { // PDH_CSTATUS_NO_OBJECT
|
||||||
if PerfObject.FailOnMissing {
|
if PerfObject.FailOnMissing {
|
||||||
err := errors.New("Performance object does not exist")
|
err := errors.New("Performance object does not exist")
|
||||||
return err
|
return err
|
||||||
} else {
|
} else {
|
||||||
fmt.Printf("Performance Object '%s' does not exist in query: %s\n", PerfObject.ObjectName, query)
|
fmt.Printf("Performance Object '%s' does not exist in query: %s\n", PerfObject.ObjectName, query)
|
||||||
}
|
}
|
||||||
} else if exists == 3221228473 { //win.PDH_CSTATUS_NO_COUNTER
|
} else if exists == 3221228473 { // PDH_CSTATUS_NO_COUNTER
|
||||||
|
|
||||||
if PerfObject.FailOnMissing {
|
if PerfObject.FailOnMissing {
|
||||||
err := errors.New("Counter in Performance object does not exist")
|
err := errors.New("Counter in Performance object does not exist")
|
||||||
|
@ -146,7 +145,7 @@ func (m *Win_PerfCounters) InvalidObject(exists uint32, query string, PerfObject
|
||||||
} else {
|
} else {
|
||||||
fmt.Printf("Counter '%s' does not exist in query: %s\n", counter, query)
|
fmt.Printf("Counter '%s' does not exist in query: %s\n", counter, query)
|
||||||
}
|
}
|
||||||
} else if exists == 2147485649 { //win.PDH_CSTATUS_NO_INSTANCE
|
} else if exists == 2147485649 { // PDH_CSTATUS_NO_INSTANCE
|
||||||
if PerfObject.FailOnMissing {
|
if PerfObject.FailOnMissing {
|
||||||
err := errors.New("Instance in Performance object does not exist")
|
err := errors.New("Instance in Performance object does not exist")
|
||||||
return err
|
return err
|
||||||
|
@ -189,9 +188,9 @@ func (m *Win_PerfCounters) ParseConfig(metrics *itemList) error {
|
||||||
query = "\\" + objectname + "(" + instance + ")\\" + counter
|
query = "\\" + objectname + "(" + instance + ")\\" + counter
|
||||||
}
|
}
|
||||||
|
|
||||||
var exists uint32 = win.PdhValidatePath(query)
|
var exists uint32 = PdhValidatePath(query)
|
||||||
|
|
||||||
if exists == win.ERROR_SUCCESS {
|
if exists == ERROR_SUCCESS {
|
||||||
if m.PrintValid {
|
if m.PrintValid {
|
||||||
fmt.Printf("Valid: %s\n", query)
|
fmt.Printf("Valid: %s\n", query)
|
||||||
}
|
}
|
||||||
|
@ -218,7 +217,7 @@ func (m *Win_PerfCounters) Cleanup(metrics *itemList) {
|
||||||
// Cleanup
|
// Cleanup
|
||||||
|
|
||||||
for _, metric := range metrics.items {
|
for _, metric := range metrics.items {
|
||||||
ret := win.PdhCloseQuery(metric.handle)
|
ret := PdhCloseQuery(metric.handle)
|
||||||
_ = ret
|
_ = ret
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -227,7 +226,7 @@ func (m *Win_PerfCounters) CleanupTestMode() {
|
||||||
// Cleanup for the testmode.
|
// Cleanup for the testmode.
|
||||||
|
|
||||||
for _, metric := range gItemList {
|
for _, metric := range gItemList {
|
||||||
ret := win.PdhCloseQuery(metric.handle)
|
ret := PdhCloseQuery(metric.handle)
|
||||||
_ = ret
|
_ = ret
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -256,26 +255,26 @@ func (m *Win_PerfCounters) Gather(acc telegraf.Accumulator) error {
|
||||||
|
|
||||||
var bufSize uint32
|
var bufSize uint32
|
||||||
var bufCount uint32
|
var bufCount uint32
|
||||||
var size uint32 = uint32(unsafe.Sizeof(win.PDH_FMT_COUNTERVALUE_ITEM_DOUBLE{}))
|
var size uint32 = uint32(unsafe.Sizeof(PDH_FMT_COUNTERVALUE_ITEM_DOUBLE{}))
|
||||||
var emptyBuf [1]win.PDH_FMT_COUNTERVALUE_ITEM_DOUBLE // need at least 1 addressable null ptr.
|
var emptyBuf [1]PDH_FMT_COUNTERVALUE_ITEM_DOUBLE // need at least 1 addressable null ptr.
|
||||||
|
|
||||||
// For iterate over the known metrics and get the samples.
|
// For iterate over the known metrics and get the samples.
|
||||||
for _, metric := range gItemList {
|
for _, metric := range gItemList {
|
||||||
// collect
|
// collect
|
||||||
ret := win.PdhCollectQueryData(metric.handle)
|
ret := PdhCollectQueryData(metric.handle)
|
||||||
if ret == win.ERROR_SUCCESS {
|
if ret == ERROR_SUCCESS {
|
||||||
ret = win.PdhGetFormattedCounterArrayDouble(metric.counterHandle, &bufSize,
|
ret = PdhGetFormattedCounterArrayDouble(metric.counterHandle, &bufSize,
|
||||||
&bufCount, &emptyBuf[0]) // uses null ptr here according to MSDN.
|
&bufCount, &emptyBuf[0]) // uses null ptr here according to MSDN.
|
||||||
if ret == win.PDH_MORE_DATA {
|
if ret == PDH_MORE_DATA {
|
||||||
filledBuf := make([]win.PDH_FMT_COUNTERVALUE_ITEM_DOUBLE, bufCount*size)
|
filledBuf := make([]PDH_FMT_COUNTERVALUE_ITEM_DOUBLE, bufCount*size)
|
||||||
if len(filledBuf) == 0 {
|
if len(filledBuf) == 0 {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
ret = win.PdhGetFormattedCounterArrayDouble(metric.counterHandle,
|
ret = PdhGetFormattedCounterArrayDouble(metric.counterHandle,
|
||||||
&bufSize, &bufCount, &filledBuf[0])
|
&bufSize, &bufCount, &filledBuf[0])
|
||||||
for i := 0; i < int(bufCount); i++ {
|
for i := 0; i < int(bufCount); i++ {
|
||||||
c := filledBuf[i]
|
c := filledBuf[i]
|
||||||
var s string = win.UTF16PtrToString(c.SzName)
|
var s string = UTF16PtrToString(c.SzName)
|
||||||
|
|
||||||
var add bool
|
var add bool
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue