JNIEXPORT jint JNICALL Java_org_krakenapps_winapi_PerformanceCounter_addCounter(JNIEnv *env, jobject obj, jint queryHandle, jstring category, jstring counter, jstring instance, jstring machine) { PDH_HCOUNTER phCounter = NULL; PDH_HQUERY phQuery = (PDH_HQUERY)queryHandle; LPTSTR counterPath = NULL; PDH_COUNTER_PATH_ELEMENTS pathElement; DWORD dwSize = 0; PDH_STATUS stat = 0; jboolean isCopy = JNI_FALSE; memset(&pathElement, 0, sizeof(pathElement)); pathElement.szObjectName = category ? (LPTSTR)(*env)->GetStringChars(env, category, &isCopy) : NULL; pathElement.szCounterName = counter ? (LPTSTR)(*env)->GetStringChars(env, counter, &isCopy) : NULL; pathElement.szInstanceName = instance ? (LPTSTR)(*env)->GetStringChars(env, instance, &isCopy) : NULL; pathElement.szMachineName = machine ? (LPTSTR)(*env)->GetStringChars(env, machine, &isCopy) : NULL; if(pathElement.szMachineName) { stat = PdhConnectMachine(pathElement.szMachineName); if(stat != ERROR_SUCCESS) { fprintf(stderr, "Error in PdhConnectMachine:, 0x%x\n", stat); if(pathElement.szMachineName) (*env)->ReleaseStringChars(env, category, pathElement.szObjectName); (*env)->ReleaseStringChars(env, counter, pathElement.szCounterName); (*env)->ReleaseStringChars(env, instance, pathElement.szInstanceName); (*env)->ReleaseStringChars(env, machine, pathElement.szMachineName); return 0; } } PdhMakeCounterPath(&pathElement, NULL, &dwSize, 0); if(dwSize == 0) { fprintf(stderr, "Error in PdhMakeCounterPath\n"); (*env)->ReleaseStringChars(env, category, pathElement.szObjectName); (*env)->ReleaseStringChars(env, counter, pathElement.szCounterName); (*env)->ReleaseStringChars(env, instance, pathElement.szInstanceName); (*env)->ReleaseStringChars(env, machine, pathElement.szMachineName); return 0; } counterPath = (LPTSTR)malloc(sizeof(TCHAR)*dwSize); stat = PdhMakeCounterPath(&pathElement, counterPath, &dwSize, 0); (*env)->ReleaseStringChars(env, category, pathElement.szObjectName); (*env)->ReleaseStringChars(env, counter, pathElement.szCounterName); (*env)->ReleaseStringChars(env, instance, pathElement.szInstanceName); (*env)->ReleaseStringChars(env, machine, pathElement.szMachineName); if(stat != ERROR_SUCCESS) { fprintf(stderr, "Error in PdhMakeCounterPath: 0x%x\n", stat); return 0; } stat = PdhAddCounter(phQuery, counterPath, 0, &phCounter); if(stat != ERROR_SUCCESS) { fprintf(stderr, "Error in PdhAddCounter: 0x%x\n", stat); return 0; } free(counterPath); PdhCollectQueryData(phQuery); return (jint)phCounter; }
PerformanceCounter::PerformanceCounter(const wchar_t* object_name, const wchar_t* counter_name, const wchar_t* instance_name) : valid_(false), query_(NULL), counter_(NULL) { PDH_COUNTER_PATH_ELEMENTS elements{}; elements.szObjectName = const_cast<LPWSTR>(object_name); elements.szCounterName = const_cast<LPWSTR>(counter_name); elements.szInstanceName = const_cast<LPWSTR>(instance_name); DWORD length = 0; auto status = PdhMakeCounterPath(&elements, nullptr, &length, 0); if (status != PDH_MORE_DATA) return; std::wstring counter_path; counter_path.resize(length - 1); status = PdhMakeCounterPath(&elements, &counter_path[0], &length, 0); if (status != ERROR_SUCCESS) return; status = PdhOpenQuery(nullptr, 0, &query_); if (status != ERROR_SUCCESS) return; status = PdhAddCounter(query_, counter_path.c_str(), 0, &counter_); if (status != ERROR_SUCCESS) return; valid_ = PdhCollectQueryData(query_) == ERROR_SUCCESS; }
int MakeCounterPath(LPTSTR pszInstanceName, // インスタンス名 LPTSTR pszCounterName, // カウンター名 LPTSTR pszCounterPath, // カウンターパス受け取りバッファー DWORD dwCounterPathSize) // カウンターパス受け取りバッファーのサイズ(文字数) { PDH_COUNTER_PATH_ELEMENTS cpe; ZeroMemory(&cpe, sizeof(PDH_COUNTER_PATH_ELEMENTS)); cpe.szMachineName = NULL; cpe.szObjectName = L"Process"; cpe.szInstanceName = pszInstanceName; cpe.szParentInstance = NULL; cpe.dwInstanceIndex = 0; cpe.szCounterName = pszCounterName; // カウンターパスの作成 if (ERROR_SUCCESS != PdhMakeCounterPath(&cpe, pszCounterPath, &dwCounterPathSize, 0)) { return -1; } return 1; }
PDH_STATUS zbx_PdhMakeCounterPath(const char *function, PDH_COUNTER_PATH_ELEMENTS *cpe, char *counterpath) { DWORD dwSize = PDH_MAX_COUNTER_PATH; wchar_t *wcounterPath = NULL; PDH_STATUS pdh_status; wcounterPath = zbx_malloc(wcounterPath, sizeof(wchar_t) * PDH_MAX_COUNTER_PATH); if (ERROR_SUCCESS != (pdh_status = PdhMakeCounterPath(cpe, wcounterPath, &dwSize, 0))) { char *object, *counter; object = zbx_unicode_to_utf8(cpe->szObjectName); counter = zbx_unicode_to_utf8(cpe->szCounterName); zabbix_log(LOG_LEVEL_ERR, "%s(): cannot make counterpath for \"\\%s\\%s\": %s", function, object, counter, strerror_from_module(pdh_status, L"PDH.DLL")); zbx_free(counter); zbx_free(object); } else zbx_unicode_to_utf8_static(wcounterPath, counterpath, PDH_MAX_COUNTER_PATH); zbx_free(wcounterPath); return pdh_status; }
PDH_STATUS zbx_PdhMakeCounterPath(const char *function, PDH_COUNTER_PATH_ELEMENTS *cpe, char *counterpath) { DWORD dwSize = PDH_MAX_COUNTER_PATH; LPTSTR wcounterPath = NULL; PDH_STATUS pdh_status; wcounterPath = zbx_realloc(wcounterPath, dwSize * sizeof(TCHAR)); if (ERROR_SUCCESS != (pdh_status = PdhMakeCounterPath(cpe, wcounterPath, &dwSize, 0))) { zabbix_log(LOG_LEVEL_ERR, "%s(): cannot make counterpath '%s': %s", function, counterpath, strerror_from_module(pdh_status, L"PDH.DLL")); } zbx_unicode_to_utf8_static(wcounterPath, counterpath, PDH_MAX_COUNTER_PATH); zbx_free(wcounterPath); return pdh_status; }
/** * カウンターパスを作成する。 * * @param pszInstanceName インスタンス名 * @param pszCounterName カウンター名 * @param pszCounterPath カウンターパス名格納先 * @param dwCounterPathSize カウンターパス名格納可能サイズ * @return パスの作成に成功した場合は 1 、失敗した場合は -1 */ static bool MakeCounterPath(LPTSTR pszInstanceName, LPTSTR pszCounterName, LPTSTR pszCounterPath, DWORD dwCounterPathSize) { PDH_COUNTER_PATH_ELEMENTS cpe; ZeroMemory( &cpe, sizeof(PDH_COUNTER_PATH_ELEMENTS) ); cpe.szMachineName = NULL; cpe.szObjectName = _T("Process"); cpe.szInstanceName = pszInstanceName; cpe.szParentInstance = NULL; cpe.dwInstanceIndex = -1; cpe.szCounterName = pszCounterName; // カウンターパスの作成 if( ERROR_SUCCESS != PdhMakeCounterPath( &cpe, pszCounterPath, &dwCounterPathSize, 0 ) ) { return false; } return true; }
BOOL WINAPI GetCounterValues(LPTSTR serverName, int instancesCount, char **instances) { PDH_STATUS s; HQUERY hQuery; // Array to specify the performance object, counter and instance for // which performance data should be collected. // typedef struct _PDH_COUNTER_PATH_ELEMENTS { // LPTSTR szMachineName; // LPTSTR szObjectName; // LPTSTR szInstanceName; // LPTSTR szParentInstance; // DWORD dwInstanceIndex; // LPTSTR szCounterName; // } PDH_COUNTER_PATH_ELEMENTS, *PPDH_COUNTER_PATH_ELEMENTS; // Each element in the array is a PDH_COUNTER_PATH_ELEMENTS structure. PDH_COUNTER_PATH_ELEMENTS cpeTmpl[] = { { NULL, "%s:locks", "_total", NULL, -1, "lock waits/sec"}, { NULL, "%s:general statistics", NULL, NULL, -1, "active temp tables"}, { NULL, "%s:locks", "_total", NULL, -1, "average wait time (ms)"}, { NULL, "%s:locks", "_total", NULL, -1, "lock timeouts (timeout > 0)/sec"}, //{ NULL, "%s:wait statistics", "_total", NULL, -1, "page io latch waits"}, { NULL, "%s:databases", "_total", NULL, -1, "repl. pending xacts"}, { NULL, "%s:general statistics", NULL, NULL, -1, "logical connections"}, { NULL, "%s:locks", "_total", NULL, -1, "lock wait time (ms)"}, { NULL, "%s:general statistics", NULL, NULL, -1, "transactions"}, { NULL, "%s:general statistics", NULL, NULL, -1, "processes blocked"}, { NULL, "%s:sql statistics", NULL, NULL, -1, "sql compilations/sec"}, { NULL, "%s:general statistics", NULL, NULL, -1, "user connections"}, { NULL, "%s:locks", "_total", NULL, -1, "lock timeouts/sec"}, { NULL, "%s:databases", "_total", NULL, -1, "percent log used"} }; const int cpeTmplCount = sizeof(cpeTmpl) / sizeof(cpeTmpl[0]); const int countersCount = instancesCount * cpeTmplCount; int i, j; HCOUNTER *hCounter = malloc(sizeof(HCOUNTER) * countersCount); PDH_COUNTER_PATH_ELEMENTS *cpe = malloc(sizeof(PDH_COUNTER_PATH_ELEMENTS) * countersCount); char szFullPath[MAX_PATH]; DWORD cbPathSize; int ret = -1; PDH_FMT_COUNTERVALUE counterValue; // Only do this setup once. if ((s = PdhOpenQuery(NULL, 0, &hQuery)) != ERROR_SUCCESS) { fprintf(stderr, "POQ failed %08x\n", s); return ret; } // Process instances to generate performance counter paths. for (i = 0; i < instancesCount; i++) { LPSTR instanceName = instances[i]; for (j = 0; j < cpeTmplCount; j++) { int index = i * cpeTmplCount + j; cbPathSize = sizeof(szFullPath); PDH_COUNTER_PATH_ELEMENTS cpeTmplItem = cpeTmpl[j]; cpe[index].szMachineName = cpeTmplItem.szMachineName; LPSTR szObjectName = malloc(cbPathSize); sprintf(szObjectName, cpeTmplItem.szObjectName, instanceName); cpe[index].szInstanceName = cpeTmplItem.szInstanceName; cpe[index].szObjectName = szObjectName; cpe[index].szParentInstance = cpeTmplItem.szParentInstance; cpe[index].dwInstanceIndex = cpeTmplItem.dwInstanceIndex; cpe[index].szCounterName = cpeTmplItem.szCounterName; if ((s = PdhMakeCounterPath(&cpe[index], szFullPath, &cbPathSize, 0)) != ERROR_SUCCESS) { fprintf(stderr,"MCP failed %08x\n", s); return ret; } if ((s = PdhAddCounter(hQuery, szFullPath, 0, &hCounter[index])) != ERROR_SUCCESS) { fprintf(stderr, "PAC failed %08x for %s\n", s, cpe[index].szCounterName); //return ret; } } } for (i = 0; i < 2; i++) { Sleep(100); // Collect data as often as you need to. if ((s = PdhCollectQueryData(hQuery)) != ERROR_SUCCESS) { fprintf(stderr, "PCQD failed %08x\n", s); return ret; } if (i == 0) continue; // Extract the calculated performance counter value for each counter or instance. for (j = 0; j < countersCount; j++) { if ((s = PdhGetFormattedCounterValue(hCounter[j], PDH_FMT_DOUBLE, NULL, &counterValue)) != ERROR_SUCCESS) { fprintf(stderr, "PGFCV failed %08x %d\n", s, hCounter[j]); continue; } if (cpe[j].szInstanceName) { printf("%s(%s)\\%s:%3.3f\n", cpe[j].szObjectName, cpe[j].szInstanceName, cpe[j].szCounterName, counterValue.doubleValue); } else printf("%s\\%s:%3.3f\n", cpe[j].szObjectName, cpe[j].szCounterName, counterValue.doubleValue); } } // Remove all the counters from the query. for (i = 0; i < countersCount; i++) { PdhRemoveCounter(hCounter[i]); free(cpe[i].szObjectName); } // Only do this cleanup once. PdhCloseQuery(hQuery); free(hCounter); free(cpe); return 0; }
int PerfCounterMuninNodePlugin::GetConfig(char *buffer, int len) { if (!m_Counters.empty()) { PDH_STATUS status; DWORD infoSize = 0; status = PdhGetCounterInfo(m_Counters[0], TRUE, &infoSize, NULL); if (status != PDH_MORE_DATA && status != PDH_INSUFFICIENT_BUFFER) return -1; PDH_COUNTER_INFO *info = (PDH_COUNTER_INFO *)malloc(infoSize); status = PdhGetCounterInfo(m_Counters[0], TRUE, &infoSize, info); if (status != ERROR_SUCCESS) return -1; int printCount; std::string graphTitle = g_Config.GetValue(m_SectionName, "GraphTitle", "Disk Time"); std::string graphCategory = g_Config.GetValue(m_SectionName, "GraphCategory", "system"); std::string graphArgs = g_Config.GetValue(m_SectionName, "GraphArgs", "--base 1000 -l 0"); std::string explainText = g_Config.GetValue(m_SectionName, "GraphInfo", info->szExplainText ? W2IConvert(info->szExplainText) : m_CounterNames[0].c_str()); std::string counterName = g_Config.GetValue(m_SectionName, "GraphVLabel", W2IConvert(info->szCounterName)); printCount = _snprintf(buffer, len, "graph_title %s\n" "graph_category %s\n" "graph_args %s\n" "graph_info %s\n" "graph_vlabel %s\n", graphTitle.c_str(), graphCategory.c_str(), graphArgs.c_str(), explainText.c_str(), counterName.c_str()); len -= printCount; buffer += printCount; free(info); std::string graphDraw = g_Config.GetValue(m_SectionName, "GraphDraw", "LINE"); std::string counterType = g_Config.GetValue(m_SectionName, "CounterType", "GAUGE"); std::string warning = g_Config.GetValue(m_SectionName, "WarningValue", ""); std::string critical = g_Config.GetValue(m_SectionName, "CriticalValue", ""); assert(m_CounterNames.size() == m_Counters.size()); std::string labels; // We handle multiple counters for (size_t i = 0; i < m_CounterNames.size(); i++) { PDH_STATUS status; DWORD infoSize = 0; status = PdhGetCounterInfo(m_Counters[i], TRUE, &infoSize, NULL); if (status != PDH_MORE_DATA && status != PDH_INSUFFICIENT_BUFFER) return -1; PDH_COUNTER_INFO *info = (PDH_COUNTER_INFO *)malloc(infoSize); status = PdhGetCounterInfo(m_Counters[i], TRUE, &infoSize, info); if (status != ERROR_SUCCESS) { free(info); return -1; } _Module.LogEvent("PerfCounter plugin: %s: counter id %i", m_Name.c_str(), info->dwType); DWORD npl = 260; TCHAR *np = new TCHAR[npl]; PdhMakeCounterPath(&(info->CounterPath), np, &npl, 0); _Module.LogEvent("PerfCounter plugin: %s: counter path %ls, %ls", m_Name.c_str(), np, info->CounterPath.szObjectName); npl = 260; PdhMakeCounterPath(&(info->CounterPath), np, &npl, PDH_PATH_WBEM_INPUT); _Module.LogEvent("PerfCounter plugin: %s: counter path %ls, %ls", m_Name.c_str(), np, info->CounterPath.szObjectName); std::string explainText = info->szExplainText ? W2IConvert(info->szExplainText) : m_CounterNames[i].c_str(); char* m_finalName = new char[128]; if (i == 0) _snprintf(m_finalName, 127, "%s", m_Name.c_str()); else _snprintf(m_finalName, 127, "%s_%i_", m_Name.c_str(), i); labels = "%s.label %s\n" "%s.draw %s\n" "%s.type %s\n" "%s.info %s\n"; // First counter gets a normal name printCount = _snprintf(buffer, len, labels.c_str(), m_finalName, m_CounterNames[i].c_str(), m_finalName, graphDraw.c_str(), m_finalName, counterType.c_str(), m_finalName, explainText.c_str()); len -= printCount; buffer += printCount; if (counterType == "DERIVE") { printCount = _snprintf(buffer, len, "%s.min 0\n", m_finalName); len -= printCount; buffer += printCount; } if (!warning.empty()) { printCount = _snprintf(buffer, len, "%s.warning %s\n", m_finalName, warning.c_str()); len -= printCount; buffer += printCount; } if (!critical.empty()) { printCount = _snprintf(buffer, len, "%s.critical %s\n", m_finalName, critical.c_str()); len -= printCount; buffer += printCount; } free(info); } } strncat(buffer, ".\n", len); return 0; }
BOOL WINAPI GetCounterValues(LPTSTR serverName, int instancesCount, _TCHAR **instances) { // Set to standard out to be unbuffered so we do not have to flush // each time we write out metric measurements setbuf(stdout, NULL); PDH_STATUS status; HQUERY hQuery; // Array to specify the performance object, counter and instance for // which performance data should be collected. // typedef struct _PDH_COUNTER_PATH_ELEMENTS { // LPTSTR szMachineName; // LPTSTR szObjectName; // LPTSTR szInstanceName; // LPTSTR szParentInstance; // DWORD dwInstanceIndex; // LPTSTR szCounterName; // } PDH_COUNTER_PATH_ELEMENTS, *PPDH_COUNTER_PATH_ELEMENTS; // Each element in the array is a PDH_COUNTER_PATH_ELEMENTS structure. PDH_COUNTER_PATH_ELEMENTS cpeTmpl[] = { { NULL, _TEXT("processor"), _TEXT("_total"), NULL, -1, _TEXT("% processor time")}, { NULL, _TEXT("system"), NULL, NULL, -1, _TEXT("processor queue length")}, { NULL, _TEXT("memory"), NULL, NULL, -1, _TEXT("available bytes")}, { NULL, _TEXT("memory"), NULL, NULL, -1, _TEXT("pages/sec")}, { NULL, _TEXT("physicaldisk"), _TEXT("_total"), NULL, -1 , _TEXT("% disk time")}, { NULL, _TEXT("asp.net applications"), _TEXT("__total__"), NULL, -1, _TEXT("requests/sec")}, { NULL, _TEXT("asp.net"), NULL, NULL, -1, _TEXT("application restarts")}, { NULL, _TEXT("asp.net"), NULL, NULL, -1, _TEXT("request wait time")}, { NULL, _TEXT("asp.net"), NULL, NULL, -1, _TEXT("requests queued")}, { NULL, _TEXT(".net clr exceptions"), _TEXT("_global_"), NULL, -1, _TEXT("# of exceps thrown / sec")}, { NULL, _TEXT(".net clr memory"), _TEXT("_global_"), NULL, -1, _TEXT("# total committed bytes")}, { NULL, _TEXT("web service"), _TEXT("_total"), NULL, -1, _TEXT("get requests/sec")}, { NULL, _TEXT("web service"), _TEXT("_total"), NULL, -1, _TEXT("post requests/sec")}, { NULL, _TEXT("web service"), _TEXT("_total"), NULL, -1, _TEXT("current connections")} }; const int cpeTmplCount = sizeof(cpeTmpl) / sizeof(cpeTmpl[0]); const int countersCount = cpeTmplCount; int i, j; HCOUNTER *hCounter = malloc(sizeof(HCOUNTER) * countersCount); PDH_COUNTER_PATH_ELEMENTS *cpe = malloc(sizeof(PDH_COUNTER_PATH_ELEMENTS) * countersCount); _TCHAR szFullPath[MAX_PATH]; _TCHAR szMessage[MAX_PATH]; DWORD cbPathSize; int result = -1; PDH_FMT_COUNTERVALUE counterValue; // Only do this setup once. status = PdhOpenQuery(NULL, 0, &hQuery); if (status != ERROR_SUCCESS) { OutputError(_TEXT("PdhOpenQuery() failed"), status); return result; } for (j = 0; j < cpeTmplCount; j++) { int index = i * cpeTmplCount + j; cbPathSize = sizeof(szFullPath); PDH_COUNTER_PATH_ELEMENTS cpeTmplItem = cpeTmpl[j]; cpe[index].szMachineName = cpeTmplItem.szMachineName; cpe[index].szInstanceName = cpeTmplItem.szInstanceName; cpe[index].szObjectName = cpeTmplItem.szObjectName; cpe[index].szParentInstance = cpeTmplItem.szParentInstance; cpe[index].dwInstanceIndex = cpeTmplItem.dwInstanceIndex; cpe[index].szCounterName = cpeTmplItem.szCounterName; status = PdhMakeCounterPath(&cpe[index], szFullPath, &cbPathSize, 0); if (status != ERROR_SUCCESS) { OutputError(_TEXT("PdhMakeCounterPath() failed"), status); return result; } status = PdhAddCounter(hQuery, szFullPath, 0, &hCounter[index]); if (status != ERROR_SUCCESS) { swprintf(szMessage, sizeof(szMessage), _TEXT("PdhAddCounter() failed for \"%s\""), cpe[index].szCounterName); OutputError(szMessage, status); return result; } } for (i = 0; i < 2; i++) { Sleep(100); // Collect data as often as you need to. status = PdhCollectQueryData(hQuery); if (status != ERROR_SUCCESS) { OutputError(_TEXT("PdhCollectQuery() failed"), status); return result; } if (i == 0) continue; // Extract the calculated performance counter value for each counter or instance. for (j = 0; j < countersCount; j++) { status = PdhGetFormattedCounterValue(hCounter[j], PDH_FMT_DOUBLE, NULL, &counterValue); if (status != ERROR_SUCCESS) { wsprintf(szMessage, _TEXT("PdhGetFormattedCounterValue() failed for %d"), hCounter[j]); OutputError(szMessage, status); continue; } if (cpe[j].szInstanceName) { fwprintf(stdout, _TEXT("%s(%s)\\%s:%3.3f\n"), cpe[j].szObjectName, cpe[j].szInstanceName, cpe[j].szCounterName, counterValue.doubleValue); } else fwprintf(stdout, _TEXT("%s\\%s:%3.3f\n"), cpe[j].szObjectName, cpe[j].szCounterName, counterValue.doubleValue); } } // Remove all the counters from the query. for (i = 0; i < countersCount; i++) { PdhRemoveCounter(hCounter[i]); } // Only do this cleanup once. PdhCloseQuery(hQuery); free(hCounter); free(cpe); return ERROR_SUCCESS; }