Status PerfCounterCollector::collectCounters(const std::vector<CounterInfo>& counters, BSONObjBuilder* builder) { for (const auto& counterInfo : counters) { DWORD dwType = 0; PDH_RAW_COUNTER rawCounter = {0}; PDH_STATUS status = PdhGetRawCounterValue(counterInfo.handle, &dwType, &rawCounter); if (status != ERROR_SUCCESS) { return {ErrorCodes::WindowsPdhError, formatFunctionCallError("PdhGetRawCounterValue", status)}; } if (counterInfo.hasSecondValue) { // Delta, Rate, and Elapsed Time counters require the second value in the raw counter // information builder->append(counterInfo.firstName, rawCounter.FirstValue); builder->append(counterInfo.secondName, rawCounter.SecondValue); } else { builder->append(counterInfo.firstName, rawCounter.FirstValue); } } return Status::OK(); }
__int64 PerfCounter::GetRawValue(int id) { if(id == 0) return 0; PDH_RAW_COUNTER value; PdhGetRawCounterValue(m_counters[id - 1], NULL, &value); return value.FirstValue; }
PerfCounter::PerfCounter() { PdhOpenQuery(NULL, NULL, &m_query); HMODULE hProcess = GetModuleHandle(NULL); wchar_t fileNameBuf[MAX_PATH]; GetModuleFileName((HMODULE) hProcess, fileNameBuf, MAX_PATH); wchar_t baseNameBuf[MAX_PATH]; _wsplitpath_s(fileNameBuf, NULL, 0, NULL, 0, baseNameBuf, MAX_PATH, NULL, 0); m_processName = baseNameBuf; DWORD processId = GetProcessId(GetCurrentProcess()); //we need to figure out the correct instance name //start by asking for all the counters which match the process name std::wstring wildcard = (boost::wformat(L"\\Process(%1%*)\\ID Process") % m_processName).str(); wchar_t paths[1024]; DWORD size = 1024; PdhExpandWildCardPath(NULL, wildcard.c_str(), paths, &size, 0); //create each ProcessID counter, check its value to see if it's the one we want size_t len = wcslen(paths); wchar_t* pathPtr = paths; bool found = false; while(len != 0) { PDH_HCOUNTER counter; PdhAddCounter(m_query, pathPtr, NULL, &counter); PdhCollectQueryData(m_query); PDH_RAW_COUNTER counterValue; PdhGetRawCounterValue(counter, 0, &counterValue); PdhRemoveCounter(counter); if(counterValue.FirstValue == processId) { found = true; break; } pathPtr += len + 1; len = wcslen(pathPtr); } if(found) { //we've got our desired instance name, which is ProcessName#N const wchar_t* instStart = wcschr(wildcard.c_str(), L'(') + 1; const wchar_t* instEnd = wcschr(wildcard.c_str(), L')') - 1; m_instName = std::wstring(instStart, instEnd - instStart); } else { //oh well, just roll with what we've got m_instName = m_processName; } }
JNIEXPORT jdouble JNICALL Java_org_hyperic_hq_plugin_mssql_PDH_pdhGetRawCounterValue(JNIEnv *env, jclass, jlong counter) { HCOUNTER h_counter = (HCOUNTER)counter; PDH_RAW_COUNTER raw_value; DWORD type; PDH_STATUS status = PdhGetRawCounterValue(h_counter, &type, &raw_value); if (status != ERROR_SUCCESS) { plugin_throw_exception(env, get_error_message(status)); return 0; } return (jdouble)raw_value.FirstValue; }
JNIEXPORT jdouble SIGAR_JNI(win32_Pdh_pdhGetValue) (JNIEnv *env, jclass cur, jlong query, jlong counter, jboolean fmt) { HCOUNTER h_counter = (HCOUNTER)counter; HQUERY h_query = (HQUERY)query; PDH_STATUS status; PDH_RAW_COUNTER raw_value; PDH_FMT_COUNTERVALUE fmt_value; DWORD type; status = PdhCollectQueryData(h_query); if (status != ERROR_SUCCESS) { win32_throw_exception(env, get_error_message(status)); return 0; } if (fmt) { /* may require 2 counters, see msdn docs */ int i=0; for (i=0; i<2; i++) { status = PdhGetFormattedCounterValue(h_counter, PDH_FMT_DOUBLE, (LPDWORD)NULL, &fmt_value); if (status == ERROR_SUCCESS) { break; } PdhCollectQueryData(h_query); } } else { status = PdhGetRawCounterValue(h_counter, &type, &raw_value); } if (status != ERROR_SUCCESS) { win32_throw_exception(env, get_error_message(status)); return 0; } if (fmt) { return fmt_value.doubleValue; } else { return (jdouble)raw_value.FirstValue; } }
PDH_STATUS zbx_PdhGetRawCounterValue(const char *function, const char *counterpath, PDH_HCOUNTER handle, PPDH_RAW_COUNTER value) { PDH_STATUS pdh_status; if (ERROR_SUCCESS != (pdh_status = PdhGetRawCounterValue(handle, NULL, value)) || (PDH_CSTATUS_VALID_DATA != value->CStatus && PDH_CSTATUS_NEW_DATA != value->CStatus)) { if (ERROR_SUCCESS == pdh_status) pdh_status = value->CStatus; zabbix_log(LOG_LEVEL_DEBUG, "%s(): cannot get counter value '%s': %s", function, counterpath, strerror_from_module(pdh_status, L"PDH.DLL")); } return pdh_status; }
uint64_t readSingleCounter(char* path) { PDH_HQUERY Query = NULL; PDH_HCOUNTER Counter; DWORD dwType; PDH_RAW_COUNTER Value; LONGLONG ret = 0; if(PdhOpenQuery(NULL, 0, &Query) == ERROR_SUCCESS) { if(PdhAddCounter(Query, path, 0, &Counter) == ERROR_SUCCESS && PdhCollectQueryData(Query) == ERROR_SUCCESS && PdhGetRawCounterValue(Counter, &dwType, &Value) == ERROR_SUCCESS) { ret = Value.FirstValue; } if (Query) PdhCloseQuery(Query); } return (uint64_t)ret; }
Status PerfCounterCollector::collectCounters(const std::vector<CounterInfo>& counters, BSONObjBuilder* builder) { for (const auto& counterInfo : counters) { DWORD dwType = 0; // Elapsed Time is an unusual counter in that being able to control the sample period for // the counter is uninteresting even though it is computed from two values. Just return the // computed value instead. if (counterInfo.type == PERF_ELAPSED_TIME) { PDH_FMT_COUNTERVALUE counterValue = {0}; PDH_STATUS status = PdhGetFormattedCounterValue( counterInfo.handle, PDH_FMT_DOUBLE, &dwType, &counterValue); if (status != ERROR_SUCCESS) { return {ErrorCodes::WindowsPdhError, formatFunctionCallError("PdhGetFormattedCounterValue", status)}; } builder->append(counterInfo.firstName, counterValue.doubleValue); } else { PDH_RAW_COUNTER rawCounter = {0}; PDH_STATUS status = PdhGetRawCounterValue(counterInfo.handle, &dwType, &rawCounter); if (status != ERROR_SUCCESS) { return {ErrorCodes::WindowsPdhError, formatFunctionCallError("PdhGetRawCounterValue", status)}; } if (counterInfo.hasSecondValue) { // Precise counters require the second value in the raw counter information builder->append(counterInfo.firstName, rawCounter.FirstValue); builder->append(counterInfo.secondName, rawCounter.SecondValue); } else { builder->append(counterInfo.firstName, rawCounter.FirstValue); } } } return Status::OK(); }
// Function name : CPerfMon::UpdateRawValue // Description : Update the raw values for the counter in pCounter // Return type : BOOL ; false fail ; true success // Argument : PPDHCOUNTERSTRUCT pCounter // // R E V I S I O N S: // DATE PROGRAMMER CHANGES // BOOL CPerfMon::UpdateRawValue(PPDHCOUNTERSTRUCT pCounter) { PPDH_RAW_COUNTER ppdhRawCounter; // Assign the next value into the array ppdhRawCounter = &(pCounter->a_RawValue[pCounter->nNextIndex]); if (PdhGetRawCounterValue(pCounter->hCounter, NULL, ppdhRawCounter) != ERROR_SUCCESS) return false; // update raw counter - up to MAX_RAW_VALUES pCounter->nRawCount = min(pCounter->nRawCount + 1, MAX_RAW_VALUES); // Update next index - rolls back to zero upon reaching MAX_RAW_VALUES pCounter->nNextIndex = (pCounter->nNextIndex + 1) % MAX_RAW_VALUES; // The Oldest index remains zero until the array is filled. // It will now be the same as the 'next' index since it was previously assigned. if (pCounter->nRawCount >= MAX_RAW_VALUES) pCounter->nOldestIndex = pCounter->nNextIndex; return true; }
/* * Instantiate a value for a single metric-instance pair */ int windows_collect_metric(pdh_metric_t *mp, LPSTR pat, pdh_value_t *vp) { PDH_STATUS pdhsts; PDH_HQUERY queryhdl = NULL; PDH_HCOUNTER counthdl = NULL; int sts = -1; if (mp->flags & M_NOVALUES) return sts; pdhsts = PdhOpenQueryA(NULL, 0, &queryhdl); if (pdhsts != ERROR_SUCCESS) { __pmNotifyErr(LOG_ERR, "windows_open: PdhOpenQueryA failed: %s\n", pdherrstr(pdhsts)); return sts; } pdhsts = PdhAddCounterA(queryhdl, pat, vp->inst, &counthdl); if (pdhsts != ERROR_SUCCESS) { __pmNotifyErr(LOG_ERR, "windows_open: Warning: PdhAddCounterA " "@ pmid=%s pat=\"%s\": %s\n", pmIDStr(mp->desc.pmid), pat, pdherrstr(pdhsts)); PdhCloseQuery(queryhdl); return sts; } pdhsts = PdhCollectQueryData(queryhdl); if (pdhsts != ERROR_SUCCESS) { if ((vp->flags & V_ERROR_SEEN) == 0) { __pmNotifyErr(LOG_ERR, "pdh_fetch: Error: PdhCollectQueryData " "failed for metric %s pat %s: %s\n", pmIDStr(mp->desc.pmid), pat, pdherrstr(pdhsts)); vp->flags |= V_ERROR_SEEN; } } else if ((mp->ctype == PERF_ELAPSED_TIME) || mp->ctype == PERF_LARGE_RAW_FRACTION) { PDH_FMT_COUNTERVALUE fmt; DWORD type; if (mp->ctype == PERF_ELAPSED_TIME) type = PDH_FMT_LARGE; else /* PERF_LARGE_RAW_FRACTION */ type = PDH_FMT_DOUBLE; pdhsts = PdhGetFormattedCounterValue(counthdl, type, NULL, &fmt); if (pdhsts != ERROR_SUCCESS) { __pmNotifyErr(LOG_ERR, "Error: PdhGetFormattedCounterValue " "failed for metric %s inst %d: %s\n", pmIDStr(mp->desc.pmid), vp->inst, pdherrstr(pdhsts)); vp->flags = V_NONE; /* no values for you! */ } else if (mp->ctype == PERF_ELAPSED_TIME) { vp->atom.ull = fmt.largeValue; sts = 0; } else { /* PERF_LARGE_RAW_FRACTION */ vp->atom.d = fmt.doubleValue; sts = 0; } } else { PDH_RAW_COUNTER raw; pdhsts = PdhGetRawCounterValue(counthdl, NULL, &raw); if (pdhsts != ERROR_SUCCESS) { __pmNotifyErr(LOG_ERR, "pdh_fetch: Error: PdhGetRawCounterValue " "failed for metric %s inst %d: %s\n", pmIDStr(mp->desc.pmid), vp->inst, pdherrstr(pdhsts)); vp->flags = V_NONE; /* no values for you! */ } else { switch (mp->ctype) { case PERF_COUNTER_COUNTER: case PERF_COUNTER_RAWCOUNT: /* these counters are only 32-bit */ vp->atom.ul = (__uint32_t)raw.FirstValue; break; case PERF_100NSEC_TIMER: case PERF_PRECISION_100NS_TIMER: /* convert 100nsec units to usec */ vp->atom.ull = raw.FirstValue / 10; break; case PERF_RAW_FRACTION: /* v1 / v2 as percentage */ vp->atom.f = (float)raw.FirstValue / raw.SecondValue; break; case PERF_COUNTER_BULK_COUNT: case PERF_COUNTER_LARGE_RAWCOUNT: default: vp->atom.ull = raw.FirstValue; } sts = 0; } } PdhRemoveCounter(counthdl); PdhCloseQuery(queryhdl); return sts; }
bool CCPUInfo::readProcStat(unsigned long long& user, unsigned long long& nice, unsigned long long& system, unsigned long long& idle, unsigned long long& io) { #ifdef TARGET_WINDOWS FILETIME idleTime; FILETIME kernelTime; FILETIME userTime; if (GetSystemTimes(&idleTime, &kernelTime, &userTime) == 0) return false; idle = (uint64_t(idleTime.dwHighDateTime) << 32) + uint64_t(idleTime.dwLowDateTime); // returned "kernelTime" includes "idleTime" system = (uint64_t(kernelTime.dwHighDateTime) << 32) + uint64_t(kernelTime.dwLowDateTime) - idle; user = (uint64_t(userTime.dwHighDateTime) << 32) + uint64_t(userTime.dwLowDateTime); nice = 0; io = 0; if (m_cpuFreqCounter && PdhCollectQueryData(m_cpuQueryLoad) == ERROR_SUCCESS) { for (std::map<int, CoreInfo>::iterator it = m_cores.begin(); it != m_cores.end(); ++it) { CoreInfo& curCore = it->second; // simplify usage PDH_RAW_COUNTER cnt; DWORD cntType; if (curCore.m_coreCounter && PdhGetRawCounterValue(curCore.m_coreCounter, &cntType, &cnt) == ERROR_SUCCESS && (cnt.CStatus == PDH_CSTATUS_VALID_DATA || cnt.CStatus == PDH_CSTATUS_NEW_DATA)) { const LONGLONG coreTotal = cnt.SecondValue, coreIdle = cnt.FirstValue; const LONGLONG deltaTotal = coreTotal - curCore.m_total, deltaIdle = coreIdle - curCore.m_idle; const double load = (double(deltaTotal - deltaIdle) * 100.0) / double(deltaTotal); // win32 has some problems with calculation of load if load close to zero curCore.m_fPct = (load < 0) ? 0 : load; if (load >= 0 || deltaTotal > 5 * 10 * 1000 * 1000) // do not update (smooth) values for 5 seconds on negative loads { curCore.m_total = coreTotal; curCore.m_idle = coreIdle; } } else curCore.m_fPct = double(m_lastUsedPercentage); // use CPU average as fallback } } else for (std::map<int, CoreInfo>::iterator it = m_cores.begin(); it != m_cores.end(); ++it) it->second.m_fPct = double(m_lastUsedPercentage); // use CPU average as fallback #elif defined(TARGET_FREEBSD) long *cptimes; size_t len; int i; len = sizeof(long) * 32 * CPUSTATES; if (sysctlbyname("kern.cp_times", NULL, &len, NULL, 0) != 0) return false; cptimes = (long*)malloc(len); if (cptimes == NULL) return false; if (sysctlbyname("kern.cp_times", cptimes, &len, NULL, 0) != 0) { free(cptimes); return false; } user = 0; nice = 0; system = 0; idle = 0; io = 0; for (i = 0; i < m_cpuCount; i++) { long coreUser, coreNice, coreSystem, coreIdle, coreIO; double total; coreUser = cptimes[i * CPUSTATES + CP_USER]; coreNice = cptimes[i * CPUSTATES + CP_NICE]; coreSystem = cptimes[i * CPUSTATES + CP_SYS]; coreIO = cptimes[i * CPUSTATES + CP_INTR]; coreIdle = cptimes[i * CPUSTATES + CP_IDLE]; std::map<int, CoreInfo>::iterator iter = m_cores.find(i); if (iter != m_cores.end()) { coreUser -= iter->second.m_user; coreNice -= iter->second.m_nice; coreSystem -= iter->second.m_system; coreIdle -= iter->second.m_idle; coreIO -= iter->second.m_io; total = (double)(coreUser + coreNice + coreSystem + coreIdle + coreIO); if(total != 0.0f) iter->second.m_fPct = ((double)(coreUser + coreNice + coreSystem) * 100.0) / total; iter->second.m_user += coreUser; iter->second.m_nice += coreNice; iter->second.m_system += coreSystem; iter->second.m_idle += coreIdle; iter->second.m_io += coreIO; user += coreUser; nice += coreNice; system += coreSystem; idle += coreIdle; io += coreIO; } } free(cptimes); #else if (m_fProcStat == NULL) return false; #ifdef TARGET_ANDROID // Just another (vanilla) NDK quirk: // rewind + fflush do not actually flush the buffers, // the same initial content is returned rather than re-read fclose(m_fProcStat); m_fProcStat = fopen("/proc/stat", "r"); #else rewind(m_fProcStat); fflush(m_fProcStat); #endif char buf[256]; if (!fgets(buf, sizeof(buf), m_fProcStat)) return false; int num = sscanf(buf, "cpu %llu %llu %llu %llu %llu %*s\n", &user, &nice, &system, &idle, &io); if (num < 5) io = 0; while (fgets(buf, sizeof(buf), m_fProcStat) && num >= 4) { unsigned long long coreUser, coreNice, coreSystem, coreIdle, coreIO; int nCpu=0; num = sscanf(buf, "cpu%d %llu %llu %llu %llu %llu %*s\n", &nCpu, &coreUser, &coreNice, &coreSystem, &coreIdle, &coreIO); if (num < 6) coreIO = 0; std::map<int, CoreInfo>::iterator iter = m_cores.find(nCpu); if (num > 4 && iter != m_cores.end()) { coreUser -= iter->second.m_user; coreNice -= iter->second.m_nice; coreSystem -= iter->second.m_system; coreIdle -= iter->second.m_idle; coreIO -= iter->second.m_io; double total = (double)(coreUser + coreNice + coreSystem + coreIdle + coreIO); if(total == 0.0f) iter->second.m_fPct = 0.0f; else iter->second.m_fPct = ((double)(coreUser + coreNice + coreSystem) * 100.0) / total; iter->second.m_user += coreUser; iter->second.m_nice += coreNice; iter->second.m_system += coreSystem; iter->second.m_idle += coreIdle; iter->second.m_io += coreIO; } } #endif return true; }
float CCPUInfo::getCPUFrequency() { // Get CPU frequency, scaled to MHz. #if defined(TARGET_DARWIN) long long hz = 0; size_t len = sizeof(hz); if (sysctlbyname("hw.cpufrequency", &hz, &len, NULL, 0) == -1) return 0.f; return hz / 1000000.0; #elif defined TARGET_WINDOWS if (m_cpuFreqCounter && PdhCollectQueryData(m_cpuQueryFreq) == ERROR_SUCCESS) { PDH_RAW_COUNTER cnt; DWORD cntType; if (PdhGetRawCounterValue(m_cpuFreqCounter, &cntType, &cnt) == ERROR_SUCCESS && (cnt.CStatus == PDH_CSTATUS_VALID_DATA || cnt.CStatus == PDH_CSTATUS_NEW_DATA)) { return float(cnt.FirstValue); } } if (!m_cores.empty()) return float(m_cores.begin()->second.m_fSpeed); else return 0.f; #elif defined(TARGET_FREEBSD) int hz = 0; size_t len = sizeof(hz); if (sysctlbyname("dev.cpu.0.freq", &hz, &len, NULL, 0) != 0) hz = 0; return (float)hz; #else int value = 0; if (m_fCPUFreq && !m_cpuInfoForFreq) { rewind(m_fCPUFreq); fflush(m_fCPUFreq); fscanf(m_fCPUFreq, "%d", &value); value /= 1000.0; } if (m_fCPUFreq && m_cpuInfoForFreq) { rewind(m_fCPUFreq); fflush(m_fCPUFreq); float mhz, avg=0.0; int n, cpus=0; while(EOF!=(n=fscanf(m_fCPUFreq," MHz : %f ", &mhz))) { if (n>0) { cpus++; avg += mhz; } fscanf(m_fCPUFreq,"%*s"); } if (cpus > 0) value = avg/cpus; } return value; #endif }
int PERF_MONITOR(const char *cmd, const char *param, unsigned flags, AGENT_RESULT *result) { HQUERY query; HCOUNTER counter; PDH_STATUS status; PDH_RAW_COUNTER rawData, rawData2; PDH_FMT_COUNTERVALUE counterValue; char counter_name[MAX_STRING_LEN]; int ret = SYSINFO_RET_FAIL; if(num_param(param) > 1) { return SYSINFO_RET_FAIL; } if(get_param(param, 1, counter_name, sizeof(counter_name)) != 0) { counter_name[0] = '\0'; } if(counter_name[0] == '\0') { return SYSINFO_RET_FAIL; } if (ERROR_SUCCESS == PdhOpenQuery(NULL,0,&query)) { if (ERROR_SUCCESS == (status = PdhAddCounter(query,counter_name,0,&counter))) { if (ERROR_SUCCESS == (status = PdhCollectQueryData(query))) { if(ERROR_SUCCESS == (status = PdhGetRawCounterValue(counter, NULL, &rawData)) && (rawData.CStatus == PDH_CSTATUS_VALID_DATA || rawData.CStatus == PDH_CSTATUS_NEW_DATA)) { if( PDH_CSTATUS_INVALID_DATA == (status = PdhCalculateCounterFromRawValue( counter, PDH_FMT_DOUBLE, &rawData, NULL, &counterValue )) ) { zbx_sleep(1); PdhCollectQueryData(query); PdhGetRawCounterValue(counter, NULL, &rawData2); status = PdhCalculateCounterFromRawValue( counter, PDH_FMT_DOUBLE, &rawData2, &rawData, &counterValue); } if(ERROR_SUCCESS == status) { SET_DBL_RESULT(result, counterValue.doubleValue); ret = SYSINFO_RET_OK; } else { zabbix_log(LOG_LEVEL_DEBUG, "Can't format counter value [%s] [%s]", counter_name, strerror_from_module(status,"PDH.DLL")); } } else { if(ERROR_SUCCESS == status) status = rawData.CStatus; zabbix_log(LOG_LEVEL_DEBUG, "Can't get counter value [%s] [%s]", counter_name, strerror_from_module(status,"PDH.DLL")); } } else { zabbix_log(LOG_LEVEL_DEBUG, "Can't collect data [%s] [%s]", counter_name, strerror_from_module(status,"PDH.DLL")); } PdhRemoveCounter(&counter); } else { zabbix_log(LOG_LEVEL_DEBUG, "Can't add counter [%s] [%s]", counter_name, strerror_from_module(status,"PDH.DLL")); } PdhCloseQuery(query); } return ret; }