[ZBXNEXT-2247] Add discovery of Performance Counter instances on Windows Agent Created: 2014 Apr 10  Updated: 2016 Mar 07  Resolved: 2014 May 12

Status: Closed
Project: ZABBIX FEATURE REQUESTS
Component/s: Agent (G)
Affects Version/s: 2.2.1
Fix Version/s: None

Type: New Feature Request Priority: Minor
Reporter: Ryan Armstrong Assignee: Unassigned
Resolution: Duplicate Votes: 0
Labels: lld, perf_counter, windows
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified

Issue Links:
Duplicate
duplicates ZBXNEXT-1839 LLD for perf_counter Closed

 Description   

I'd like to be able to discover Performance Counter instance natively via the Windows Agent. This way Discovery Rules can be created for the automated monitoring of Multi-Instance Performance Counters such as Process, PhysicalDisk, LogicalDisk, Paging File, etc.

I initially used a PowerShell script to discover Perf Counter instances but realized most of the work is already done in the Agent source and is a much preferred method.

The following code has worked nicely for me (Agent sources v2.2.1)

<moved to comments below>



 Comments   
Comment by Ryan Armstrong [ 2014 Apr 10 ]

To use the discovery rule, use key 'perf_counter.discovery[<Category>]'. This will return '

{#INSTANCE}' names which you then use in Discovery Rule Item Prototypes like 'perf_counter[<Category>({#INSTANCE}

)\CounterName]'

Apologies for using the incorrect MarkDown in the initial request. I can't seem to edit it. Moderators, please feel free to edit at your leisure.

Comment by Ryan Armstrong [ 2014 Apr 10 ]

Here's the code in a readable fashion:

include/sysinfo.h[244]
int	PERF_COUNTER_DISCOVERY(AGENT_REQUEST *request, AGENT_RESULT *result); 
src/libs/zbxsysinfo/win32/win32.c[58]
	{"perf_counter.discovery",	CF_HAVEPARAMS,	PERF_COUNTER_DISCOVERY,	 "Processor"}, 
src/libs/zbxsysinfo/win32/pdhmon.c[25]
#include "zbxjson.h" 
src/libs/zbxsysinfo/win32/pdhmon.c[149]
int PERF_COUNTER_DISCOVERY(AGENT_REQUEST *request, AGENT_RESULT *result)
{
	const char			*__function_name = "PERF_COUNTER_DISCOVERY";
	char				counterPath[PDH_MAX_COUNTER_PATH], *tmp;
	LPWSTR				wcounterPath;

	int					ret = SYSINFO_RET_FAIL;
	struct zbx_json		j;
	
	PDH_STATUS			status;
	LPTSTR				mszCounterList = NULL;	
	DWORD				pcchCounterListLength = 0;
	LPTSTR				mszInstanceList = NULL;
	DWORD				pcchInstanceListLength = 0;
	LPWSTR				nameBuffer = NULL;
	char				*name = NULL;
	
	zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __function_name);
	
	// Get requested counter path
	if (1 != request->nparam)
		goto clean;

	tmp = get_rparam(request, 0);
	if (NULL == tmp || '\0' == *tmp)
		goto clean;
		
	// Validate counter path
	strscpy(counterPath, tmp);
	wcounterPath = zbx_utf8_to_unicode(counterPath);
	
	// Get required buffer sizes
	status = PdhEnumObjectItems(
		NULL,						// _In_     LPCTSTR szDataSource
		NULL,						// _In_     LPCTSTR szMachineName
		wcounterPath,				// _In_     LPCTSTR szObjectName
		NULL,						// _Out_    LPTSTR mszCounterList
		&pcchCounterListLength,		// _Inout_  LPDWORD pcchCounterListLength
		NULL,						// _Out_    LPTSTR mszInstanceList
		&pcchInstanceListLength,	// _Inout_  LPDWORD pcchInstanceListLength
		PERF_DETAIL_WIZARD,			// _In_     DWORD dwDetailLevel
		0							// DWORD dwFlags
	);
	
	if(status != PDH_MORE_DATA) {
		zabbix_log(LOG_LEVEL_ERR, "cannot get required buffer size for counter path '%s': %s",
		counterPath, strerror_from_module(status, L"PDH.DLL"));
		goto clean;
	}
	
	if(0 == pcchInstanceListLength) {
		zabbix_log(LOG_LEVEL_ERR, "counter object '%s' does not support multiple instances.", counterPath);
		goto clean;
	}
	
	// Initialize buffers
	mszCounterList = (LPTSTR) zbx_malloc(mszCounterList, sizeof(TCHAR) * pcchCounterListLength);
	mszInstanceList = (LPTSTR) zbx_malloc(mszInstanceList, sizeof(TCHAR) * pcchInstanceListLength);
	
	// Get counter and instance names
	status = PdhEnumObjectItems(
		NULL,						// _In_     LPCTSTR szDataSource
		NULL,						// _In_     LPCTSTR szMachineName
		wcounterPath,				// _In_     LPCTSTR szObjectName
		mszCounterList,				// _Out_    LPTSTR mszCounterList
		&pcchCounterListLength,		// _Inout_  LPDWORD pcchCounterListLength
		mszInstanceList,			// _Out_    LPTSTR mszInstanceList
		&pcchInstanceListLength,	// _Inout_  LPDWORD pcchInstanceListLength
		PERF_DETAIL_WIZARD,			// _In_     DWORD dwDetailLevel
		0							// DWORD dwFlags
	);
	
	if(status != ERROR_SUCCESS) {
		zabbix_log(LOG_LEVEL_ERR, "cannot get instance and counter names for '%s': %s",
		counterPath, strerror_from_module(status, L"PDH.DLL"));
		goto clean;
	}
	
	// Create JSON Output
	zbx_json_init(&j, ZBX_JSON_STAT_BUF_LEN);
	zbx_json_addarray(&j, ZBX_PROTO_TAG_DATA);
	
	for(nameBuffer = mszInstanceList; *nameBuffer != 0; nameBuffer += wcslen(nameBuffer) + 1) {
		name = zbx_unicode_to_utf8(nameBuffer);
	
		zbx_json_addobject(&j, NULL);
		zbx_json_addstring(&j, "{#INSTANCE}", name, ZBX_JSON_TYPE_STRING);
		zbx_json_close(&j);
		
		zbx_free(name);
	}
		
	zbx_json_close(&j);

	// Result
	SET_STR_RESULT(result, strdup(j.buffer));
	ret = SYSINFO_RET_OK;
	
	// Clean up
	zbx_json_free(&j);
	zbx_free(wcounterPath);
	zbx_free(mszCounterList);
	zbx_free(mszInstanceList);
	
clean:
	zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __function_name);
	
	return ret;	
}
Comment by Oleksii Zagorskyi [ 2014 Apr 10 ]

Description truncated as requested by reporter.

In any case it would be better to create a patch and attach it here.

Comment by Oleksii Zagorskyi [ 2014 May 12 ]

Closed as duplicate of ZBXNEXT-1839

Comment by jrouvier [ 2015 Sep 02 ]

Maybe some help for that, i didn't find anything online.
A UserParameter to retreive all instances of a perf counter (could be certainly optimized )

UserParameter=perf_counter.discovery[*],powershell -C "$coma='';write-output '{\"data\":[';typeperf -qx \"$1\" | where {$.StartsWith(\"$1\")} | select $ | %

{ $_ -replace '.*\(([^\)]+)\).*', '$$1' }

| sort | get-unique | % { ($coma + '{\"

{#INSTANCE}\":\"' + $_ + '\"}'); $coma=','; }; write-output \"]}\""

Usage in discovery : perf_counter.discovery[\Process]
And in item prototype : perf_counter[\Process({#INSTANCE}

)\ID Process]

Comment by Paolo Bozzini [ 2016 Mar 07 ]

Hi jrouvier,

if i set your script in unserparameter i get a lot of syntax error, i need to LLD of all site in my windows' hosting infrastrucuture.

Have you any updated powershell script?

Thank you

Comment by jrouvier [ 2016 Mar 07 ]

Looks like a formatting problem, here is what I use every where:

UserParameter=perf_counter.discovery[*],powershell -C "$coma='';write-output '{\"data\":['; (Get-Counter -Counter \"$1\").CounterSamples | ?{$_.InstanceName -match \"$2\"} | %{ try{ ($coma + '{\"{#$3INSTANCE}\":\"' + ($_.Path -replace '.*\(([^^\)]+)\).*','$$1') + '\",\"{#$3PID}\":' + $_.CookedValue + '}'); $coma=','; }catch{} } ; write-output \"]}\""

Example of use:

zabbix_get -s 10.0.0.1 -k 'perf_counter.discovery[\Process(*)\ID Process,myprocessname,VARPREFIX]'

which return

{"data":[
{"{#VARPREFIXINSTANCE}":"myprocessname","{#VARPREFIXPID}":4936}
,{"{#VARPREFIXINSTANCE}":"myprocessname","{#VARPREFIXPID}":10485}
]}

Just put ".*" in myprocessname if you want all instances

Comment by Paolo Bozzini [ 2016 Mar 07 ]

Hi,

if i use

zabbix_get -s 1.1.1.1 -k 'perf_counter.discovery["\Web Service (.*)\Total Bytes Transferred"]'

i get the following error:

Get-Counter : The specified object was not found on the computer.

but if i navigate to perfmon i can see the value.

What's wrong?

Thanks for the support

Comment by jrouvier [ 2016 Mar 07 ]

try:
perf_counter.discovery[\Web Service(*)\Total Bytes Transferred,.*,WS]

Comment by Paolo Bozzini [ 2016 Mar 07 ]

Yess!!

Now i must create all the item prototype and graphic.

May i ask other support in case?

Comment by Paolo Bozzini [ 2016 Mar 07 ]

Is it possible only have the list of site without any other parameter?

Your query give me only the information about that value for all web site but this operation can be done configuring the item prototype..

i would like a query as:

per_counter.discovery[\Web Service(*),.*,WS]

Thanks

Generated at Thu Mar 28 16:34:54 EET 2024 using Jira 9.12.4#9120004-sha1:625303b708afdb767e17cb2838290c41888e9ff0.