[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: |
|
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 |
Comment by jrouvier [ 2015 Sep 02 ] |
Maybe some help for that, i didn't find anything online. 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: |
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 |