const TCHAR *PerfCounterMuninNodePlugin::GetPdhCounterLocalizedName(const TCHAR *englishName) { TCHAR *regBuffer; DWORD regBufferSize = 4096; DWORD status; do { regBuffer = new TCHAR[regBufferSize]; status = RegQueryValueEx(HKEY_PERFORMANCE_DATA, L"Counter 009", NULL, NULL, (LPBYTE)regBuffer, ®BufferSize); if (status == ERROR_MORE_DATA) { delete regBuffer; regBufferSize += 4096; } else { if (status != ERROR_SUCCESS) { delete regBuffer; _Module.LogEvent("PerfCounter plugin: %s: RegQueryValueEx error=%x", m_Name.c_str(), status); return englishName; } } } while (status != ERROR_SUCCESS); DWORD fIndex = -1; for (TCHAR *idx = regBuffer; *idx; idx += wcslen(idx) + 1) { TCHAR *cName = idx + wcslen(idx) + 1; if (_wcsicmp(cName, englishName) == 0) { fIndex = _wtol(idx); break; } idx = cName; } delete regBuffer; DWORD bufSize = 0; PdhLookupPerfNameByIndex(NULL, fIndex, NULL, &bufSize); TCHAR *localName = new TCHAR[bufSize]; status = PdhLookupPerfNameByIndex(NULL, fIndex, localName, &bufSize); if (status != ERROR_SUCCESS) { _Module.LogError("PerfCounter plugin: %s: Could not find a local name for %ls, error=%x", m_Name.c_str(), englishName, status); return englishName; } return localName; }
void InitUptimePerfCounter() { char perfcntrname[64]; DWORD pcnlen = sizeof(perfcntrname) - 8; PdhOpenQuery(NULL, 0, &hQuery); strcpy(perfcntrname, "\\System\\"); PdhLookupPerfNameByIndex(NULL, 674, perfcntrname + 8, &pcnlen); PdhAddCounter(hQuery, perfcntrname, 0, &hCounter); }
const TCHAR *PerfCounterMuninNodePlugin::GetPdhCounterLocalizedName(const TCHAR *englishName) { if (englishCounterNames.empty()) { return englishName; } DWORD fIndex = 0; // try to find the name in the map of pdh objects&counters for (std::map<DWORD, TString>::iterator it = englishCounterNames.begin(); it != englishCounterNames.end(); ++it) { if (!it->second.compare(englishName)) { if (fIndex) { _Module.LogEvent("PerfCounter plugin: %s: duplicate %ls, idx %i/%i", m_SectionName.c_str(), englishName, fIndex, it->first); break; } fIndex = it->first; } } // not found if (fIndex <= 0) return englishName; DWORD status; DWORD bufSize = 0; PdhLookupPerfNameByIndex(NULL, fIndex, NULL, &bufSize); TCHAR *localName = new TCHAR[bufSize]; status = PdhLookupPerfNameByIndex(NULL, fIndex, localName, &bufSize); if (status == PDH_INSUFFICIENT_BUFFER) { delete localName; bufSize = 1024; TCHAR *localName = new TCHAR[bufSize]; status = PdhLookupPerfNameByIndex(NULL, fIndex, localName, &bufSize); } if (status != ERROR_SUCCESS) { // can happen, i.e. if the name is "*" delete localName; _Module.LogEvent("PerfCounter plugin: %s: Could not find a local name for %ls, error=%x", m_Name.c_str(), englishName, status); return englishName; } return localName; }
JNIEXPORT jstring SIGAR_JNI(win32_Pdh_pdhLookupPerfName) (JNIEnv *env, jclass cur, jint index) { TCHAR path[MAX_PATH + 1]; DWORD len = sizeof(path) / sizeof(TCHAR); /* len is number of TCHAR's, not sizeof(path) */ PDH_STATUS status = PdhLookupPerfNameByIndex(NULL, index, path, &len); if (status == ERROR_SUCCESS) { return JENV->NewString(env, (const jchar *)path, len); } else { win32_throw_exception(env, get_error_message(status)); return NULL; } }
wchar_t *get_counter_name(DWORD pdhIndex) { const char *__function_name = "get_counter_name"; PERF_COUNTER_ID *counterName; DWORD dwSize; PDH_STATUS pdh_status; zabbix_log(LOG_LEVEL_DEBUG, "In %s() pdhIndex:%u", __function_name, pdhIndex); counterName = PerfCounterList; while (NULL != counterName) { if (counterName->pdhIndex == pdhIndex) break; counterName = counterName->next; } if (NULL == counterName) { counterName = (PERF_COUNTER_ID *)zbx_malloc(counterName, sizeof(PERF_COUNTER_ID)); memset(counterName, 0, sizeof(PERF_COUNTER_ID)); counterName->pdhIndex = pdhIndex; counterName->next = PerfCounterList; dwSize = PDH_MAX_COUNTER_NAME; if (ERROR_SUCCESS == (pdh_status = PdhLookupPerfNameByIndex(NULL, pdhIndex, counterName->name, &dwSize))) PerfCounterList = counterName; else { zabbix_log(LOG_LEVEL_ERR, "PdhLookupPerfNameByIndex() failed: %s", strerror_from_module(pdh_status, L"PDH.DLL")); zbx_free(counterName); zabbix_log(LOG_LEVEL_DEBUG, "End of %s():FAIL", __function_name); return L"UnknownPerformanceCounter"; } } zabbix_log(LOG_LEVEL_DEBUG, "End of %s():SUCCEED", __function_name); return counterName->name; }
CPUUsage::CPUUsage( void ) : m_numCounters ( 0 ), m_secondsPerUpdate ( 0.25f ) { // Prepare to monitor CPU performance. std::vector <TCHAR*> vecCounterInstanceNames; PDH_STATUS pdhStatus = ERROR_SUCCESS; LPTSTR szObjectNameBuffer = NULL; DWORD dwObjectNameSize = 0; LPTSTR szCounterListBuffer = NULL; DWORD dwCounterListSize = 0; LPTSTR szInstanceListBuffer = NULL; DWORD dwInstanceListSize = 0; LPTSTR szThisInstance = NULL; // The PDH library does not work as advertised under all conditions; at least some // of the time, it will issue "PDH_INVALID_ARGUMENT" errors on the first call, when // you would normally pass a NULL name pointer and expect a "PDH_MORE_DATA" return // and a valid size. Working around this here by allocating a buffer that's // (hopefully) always "big enough" for the name. szObjectNameBuffer = new TCHAR[m_processorObjectNameMaxSize]; dwObjectNameSize = m_processorObjectNameMaxSize; // Find the "Processor" counter object's friendly local name. Find its size, allocate // a buffer, then get the name. It has a constant index on all machines. pdhStatus = PdhLookupPerfNameByIndex( NULL, // Machine name - local machine since it's NULL m_processorObjectIndex, // Constant index of "Processor" object szObjectNameBuffer, &dwObjectNameSize ); if( pdhStatus == ERROR_SUCCESS ) { // Find the buffer size for the data. pdhStatus = PdhEnumObjectItems( NULL, // Real time source NULL, // Local machine szObjectNameBuffer, // Object to enumerate szCounterListBuffer, // Pass NULL and 0 &dwCounterListSize, // to get length required szInstanceListBuffer, // Buffer size &dwInstanceListSize, // Number of instances PERF_DETAIL_WIZARD, // Counter detail level 0 ); // Under normal conditions, the Enum call will tell us that there's more data, // and it will have set values for the sizes of buffers to return to it. // If that's not true, we'll never collect CPU data on this machine. if( pdhStatus == PDH_MORE_DATA ) { // Allocate the buffers and try the call again. szCounterListBuffer = new TCHAR[dwCounterListSize]; szInstanceListBuffer = new TCHAR[dwInstanceListSize]; if( ( szCounterListBuffer != NULL ) && ( szInstanceListBuffer != NULL ) ) { pdhStatus = PdhEnumObjectItems( NULL, // Real time source NULL, // Local machine szObjectNameBuffer, // Object to enumerate szCounterListBuffer, // Buffer to receive counter list &dwCounterListSize, szInstanceListBuffer, // Buffer to receive instance list &dwInstanceListSize, PERF_DETAIL_WIZARD, // Counter detail level 0 ); // As luck would have it, the counter we want ("% Processor Time" in // English, index #6) is the first one in szCounterListBuffer. Otherwise, // we'd have to iterate down the list to find it. // Now find all instances of that counter: (0), (1), ... (_Total). if( pdhStatus == ERROR_SUCCESS ) { // Walk the instance list. The list can contain one // or more null-terminated strings. The last string // is followed by a second null-terminator. for( szThisInstance = szInstanceListBuffer; *szThisInstance != _T( '\0' ); szThisInstance += _tcslen( szThisInstance ) + 1 ) { // Object name and counter list don't change, but build // a complete counter path from its various parts, which // will look like "\\Processor(_Total)\\% Processor Time" etc. TCHAR szFormat[] = _T( "\\%s(%s)\\%s" ); size_t pathSize = _tcslen( szFormat ) + _tcslen( szObjectNameBuffer ) + _tcslen( szThisInstance ) + _tcslen( szCounterListBuffer ) + 1; // The pathSize is actually a bit bigger than it needs to be, since the // format string characters (e.g. "%s") don't take any space in the // final string. LPTSTR szCounterPath = new TCHAR[ pathSize ]; _stprintf_s( szCounterPath, pathSize, szFormat, szObjectNameBuffer, // "Processor" in English szThisInstance, // "0", "1", etc., as well as "_Total", in all languages szCounterListBuffer ); // "% Processor Time" in English vecCounterInstanceNames.push_back( szCounterPath ); m_numCounters++; } } } } } if( szCounterListBuffer != NULL ) { delete [] szCounterListBuffer; } if( szInstanceListBuffer != NULL ) { delete [] szInstanceListBuffer; } if( szObjectNameBuffer != NULL ) { delete [] szObjectNameBuffer; } // Allocate array for CPU counter results. We always have one more counter than // CPU, since there's a counter for "_Total" CPU usage. If something gets really // wrong here, just claim one CPU. m_CPUCount = m_numCounters - 1; if( m_CPUCount <= 0 ) { m_CPUCount = 1; } m_CPUPercentCounters = new double[m_numCounters]; for( unsigned int i = 0; i < m_numCounters; i++ ) { m_CPUPercentCounters[i] = 0.0f; } // Initialize all processor counters and capture them in the global counter vector. if( m_numCounters > 0 ) { std::vector <TCHAR*>::iterator iter; for( iter = vecCounterInstanceNames.begin(); iter != vecCounterInstanceNames.end(); ++iter ) { ProcessorCounter* procCounter = new ProcessorCounter( *iter ); procCounter->Initialize(); m_vecProcessorCounters.push_back( procCounter ); } // We have the counter name copied in the ProcessorCounter object, so clean up // the name we used here. TCHAR* pTemp = NULL; while( !vecCounterInstanceNames.empty() ) { pTemp = vecCounterInstanceNames.back(); vecCounterInstanceNames.pop_back(); delete [] pTemp; } } // Capture the first value of a tick. QueryPerformanceCounter( &m_LastUpdateTick ); //Calculate the frequency QueryPerformanceFrequency( &m_Frequency ); return; }