X-Git-Url: https://granicus.if.org/sourcecode?a=blobdiff_plain;f=plugins%2Fcheck_perfmon.cpp;h=0f94b12dc5347fefb06cb9a0f1a8fee66eb665e9;hb=a9c1e3cfa1b12ef010ec65906419aef4f25b9b18;hp=d1365163bf4c76fd53bddb8ef71e44a170755b7d;hpb=1f52e391d475037f553e015d3ba18a00625960c7;p=icinga2 diff --git a/plugins/check_perfmon.cpp b/plugins/check_perfmon.cpp index d1365163b..0f94b12dc 100644 --- a/plugins/check_perfmon.cpp +++ b/plugins/check_perfmon.cpp @@ -1,56 +1,29 @@ -/****************************************************************************** -* Icinga 2 * -* Copyright (C) 2012-2017 Icinga Development Team (https://www.icinga.com/) * -* * -* This program is free software; you can redistribute it and/or * -* modify it under the terms of the GNU General Public License * -* as published by the Free Software Foundation; either version 2 * -* of the License, or (at your option) any later version. * -* * -* This program is distributed in the hope that it will be useful, * -* but WITHOUT ANY WARRANTY; without even the implied warranty of * -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * -* GNU General Public License for more details. * -* * -* You should have received a copy of the GNU General Public License * -* along with this program; if not, write to the Free Software Foundation * -* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. * -******************************************************************************/ - -#include +/* Icinga 2 | (c) 2012 Icinga GmbH | GPLv2+ */ + +#include "plugins/thresholds.hpp" +#include #include #include - -#include "check_perfmon.h" +#include +#include +#include +#include #define VERSION 1.0 namespace po = boost::program_options; -INT wmain(INT argc, WCHAR **argv) +struct printInfoStruct { - po::variables_map variables_map; - printInfoStruct stPrintInfo; - if (!ParseArguments(argc, argv, variables_map, stPrintInfo)) - return 3; - - if (variables_map.count("print-objects")) { - PrintObjects(); - return 0; - } - - if (variables_map.count("print-object-info")) { - PrintObjectInfo(stPrintInfo); - return 0; - } - - if (QueryPerfData(stPrintInfo)) - return PrintOutput(variables_map, stPrintInfo); - else - return 3; -} - -BOOL ParseArguments(CONST INT ac, WCHAR **av, po::variables_map& vm, printInfoStruct& printInfo) + threshold tWarn; + threshold tCrit; + std::wstring wsFullPath; + double dValue; + DWORD dwPerformanceWait = 1000; + DWORD dwRequestedType = PDH_FMT_DOUBLE; +}; + +static bool parseArguments(const int ac, WCHAR **av, po::variables_map& vm, printInfoStruct& printInfo) { WCHAR szNamePath[MAX_PATH + 1]; GetModuleFileName(NULL, szNamePath, MAX_PATH); @@ -70,26 +43,26 @@ BOOL ParseArguments(CONST INT ac, WCHAR **av, po::variables_map& vm, printInfoSt ("perf-syntax", po::wvalue(), "Use this string as name for the performance counter (graphite compatibility)") ; - po::basic_command_line_parser parser(ac, av); + po::wcommand_line_parser parser(ac, av); try { po::store( parser .options(desc) .style( - po::command_line_style::unix_style | - po::command_line_style::allow_long_disguise) + po::command_line_style::unix_style | + po::command_line_style::allow_long_disguise) .run(), vm); vm.notify(); - } catch (std::exception& e) { + } catch (const std::exception& e) { std::cout << e.what() << '\n' << desc << '\n'; - return FALSE; + return false; } if (vm.count("version")) { std::wcout << "Version: " << VERSION << '\n'; - return FALSE; + return false; } if (vm.count("help")) { @@ -110,24 +83,24 @@ BOOL ParseArguments(CONST INT ac, WCHAR **av, po::variables_map& vm, printInfoSt L" 2\tCRITICAL,\n\tThe critical threshold was broken\n" L" 3\tUNKNOWN, \n\tNo check could be performed\n\n" , szProgName); - return 0; + return false; } if (vm.count("warning")) { try { printInfo.tWarn = threshold(vm["warning"].as()); - } catch (std::invalid_argument& e) { + } catch (const std::invalid_argument& e) { std::wcout << e.what() << '\n'; - return FALSE; + return false; } } if (vm.count("critical")) { try { printInfo.tCrit = threshold(vm["critical"].as()); - } catch (std::invalid_argument& e) { + } catch (const std::invalid_argument& e) { std::wcout << e.what() << '\n'; - return FALSE; + return false; } } @@ -138,7 +111,7 @@ BOOL ParseArguments(CONST INT ac, WCHAR **av, po::variables_map& vm, printInfoSt printInfo.dwRequestedType = PDH_FMT_LONG; else if (vm["fmt-countertype"].as().compare(L"double")) { std::wcout << "Unknown value type " << vm["fmt-countertype"].as() << '\n'; - return FALSE; + return false; } } @@ -148,47 +121,33 @@ BOOL ParseArguments(CONST INT ac, WCHAR **av, po::variables_map& vm, printInfoSt if (vm.count("performance-wait")) printInfo.dwPerformanceWait = vm["performance-wait"].as(); - return TRUE; + return true; } -BOOL GetIntstancesAndCountersOfObject(CONST std::wstring wsObject, - std::vector& vecInstances, - std::vector& vecCounters) +static bool getInstancesAndCountersOfObject(const std::wstring& wsObject, + std::vector& vecInstances, std::vector& vecCounters) { - LPWSTR szDataSource = NULL, szMachineName = NULL, - mszCounterList = NULL, mszInstanceList = NULL; DWORD dwCounterListLength = 0, dwInstanceListLength = 0; - std::wstringstream wssInstanceName, wssCounterName; - LPWSTR szObjectName = new WCHAR[wsObject.length() + 1]; - StrCpyW(szObjectName, wsObject.c_str()); - - PDH_STATUS status = - PdhEnumObjectItems(szDataSource, szMachineName, szObjectName, - mszCounterList, &dwCounterListLength, mszInstanceList, - &dwInstanceListLength, PERF_DETAIL_WIZARD, 0); - - if (status != PDH_MORE_DATA) { - delete[]szObjectName; - return FALSE; - } - - mszCounterList = new WCHAR[dwCounterListLength + 1]; - mszInstanceList = new WCHAR[dwInstanceListLength + 1]; + if (PdhEnumObjectItems(NULL, NULL, wsObject.c_str(), + NULL, &dwCounterListLength, NULL, + &dwInstanceListLength, PERF_DETAIL_WIZARD, 0) != PDH_MORE_DATA) + return false; - status = PdhEnumObjectItems(szDataSource, szMachineName, szObjectName, - mszCounterList, &dwCounterListLength, mszInstanceList, - &dwInstanceListLength, PERF_DETAIL_WIZARD, 0); + std::vector mszCounterList(dwCounterListLength + 1); + std::vector mszInstanceList(dwInstanceListLength + 1); - if (FAILED(status)) { - delete[]mszCounterList; - delete[]mszInstanceList; - delete[]szObjectName; - return FALSE; + if (FAILED(PdhEnumObjectItems(NULL, NULL, wsObject.c_str(), + mszCounterList.data(), &dwCounterListLength, mszInstanceList.data(), + &dwInstanceListLength, PERF_DETAIL_WIZARD, 0))) { + return false; } if (dwInstanceListLength) { - for (DWORD c = 0; c < dwInstanceListLength-1; ++c) { + std::wstringstream wssInstanceName; + + // XXX: is the "- 1" correct? + for (DWORD c = 0; c < dwInstanceListLength - 1; ++c) { if (mszInstanceList[c]) wssInstanceName << mszInstanceList[c]; else { @@ -199,41 +158,66 @@ BOOL GetIntstancesAndCountersOfObject(CONST std::wstring wsObject, } if (dwCounterListLength) { - for (DWORD c = 0; c < dwCounterListLength-1; ++c) { - if (mszCounterList[c]) { + std::wstringstream wssCounterName; + + // XXX: is the "- 1" correct? + for (DWORD c = 0; c < dwCounterListLength - 1; ++c) { + if (mszCounterList[c]) wssCounterName << mszCounterList[c]; - } else { + else { vecCounters.push_back(wssCounterName.str()); wssCounterName.str(L""); } } } - delete[]mszCounterList; - delete[]mszInstanceList; - delete[]szObjectName; + return true; +} + +static void printPDHError(PDH_STATUS status) +{ + HMODULE hPdhLibrary = NULL; + LPWSTR pMessage = NULL; - return TRUE; + hPdhLibrary = LoadLibrary(L"pdh.dll"); + if (!hPdhLibrary) { + std::wcout << "LoadLibrary failed with " << GetLastError() << '\n'; + return; + } + + if (!FormatMessage(FORMAT_MESSAGE_FROM_HMODULE | FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_ARGUMENT_ARRAY, + hPdhLibrary, status, 0, (LPWSTR)&pMessage, 0, NULL)) { + FreeLibrary(hPdhLibrary); + std::wcout << "Format message failed with " << std::hex << GetLastError() << '\n'; + return; + } + + FreeLibrary(hPdhLibrary); + + std::wcout << pMessage << '\n'; + LocalFree(pMessage); } -VOID PrintObjects() +static void printObjects() { - LPWSTR szDataSource = NULL, szMachineName = NULL, mszObjectList = NULL; DWORD dwBufferLength = 0; - PDH_STATUS status = - PdhEnumObjects(szDataSource, szMachineName, mszObjectList, + PDH_STATUS status = PdhEnumObjects(NULL, NULL, NULL, &dwBufferLength, PERF_DETAIL_WIZARD, FALSE); //HEX HEX! Only a Magicians gets all the info he wants, and only Microsoft knows what that means - if (status != PDH_MORE_DATA) - goto die; + if (status != PDH_MORE_DATA) { + printPDHError(status); + return; + } - mszObjectList = new WCHAR[dwBufferLength + 2]; - status = PdhEnumObjects(szDataSource, szMachineName, mszObjectList, - &dwBufferLength, PERF_DETAIL_WIZARD, FALSE); + std::vector mszObjectList(dwBufferLength + 2); + status = PdhEnumObjects(NULL, NULL, mszObjectList.data(), + &dwBufferLength, PERF_DETAIL_WIZARD, FALSE); - if (FAILED(status)) - goto die; + if (FAILED(status)) { + printPDHError(status); + return; + } DWORD c = 0; @@ -243,16 +227,9 @@ VOID PrintObjects() else std::wcout << mszObjectList[c]; } - - delete[]mszObjectList; - return; - -die: - FormatPDHError(status); - delete[]mszObjectList; } -VOID PrintObjectInfo(CONST printInfoStruct& pI) +static void printObjectInfo(const printInfoStruct& pI) { if (pI.wsFullPath.empty()) { std::wcout << "No object given!\n"; @@ -261,9 +238,9 @@ VOID PrintObjectInfo(CONST printInfoStruct& pI) std::vector vecInstances, vecCounters; - if (!GetIntstancesAndCountersOfObject(pI.wsFullPath, vecInstances, vecCounters)) { + if (!getInstancesAndCountersOfObject(pI.wsFullPath, vecInstances, vecCounters)) { std::wcout << "Could not enumerate instances and counters of " << pI.wsFullPath << '\n' - << "Make sure it exists!\n"; + << "Make sure it exists!\n"; return; } @@ -271,10 +248,8 @@ VOID PrintObjectInfo(CONST printInfoStruct& pI) if (vecInstances.empty()) std::wcout << "> Has no instances\n"; else { - for (std::vector::iterator it = vecInstances.begin(); - it != vecInstances.end(); ++it) { - std::wcout << "> " << *it << '\n'; - } + for (const auto& instance : vecInstances) + std::wcout << "> " << instance << '\n'; } std::wcout << std::endl; @@ -282,31 +257,34 @@ VOID PrintObjectInfo(CONST printInfoStruct& pI) if (vecCounters.empty()) std::wcout << "> Has no counters\n"; else { - for (std::vector::iterator it = vecCounters.begin(); - it != vecCounters.end(); ++it) { - std::wcout << "> " << *it << '\n'; - } + for (const auto& counter : vecCounters) + std::wcout << "> " << counter << "\n"; } std::wcout << std::endl; } -BOOL QueryPerfData(printInfoStruct& pI) +bool QueryPerfData(printInfoStruct& pI) { PDH_HQUERY hQuery = NULL; PDH_HCOUNTER hCounter = NULL; - PDH_FMT_COUNTERVALUE_ITEM *pDisplayValues = NULL; DWORD dwBufferSize = 0, dwItemCount = 0; if (pI.wsFullPath.empty()) { std::wcout << "No performance counter path given!\n"; - return FALSE; + return false; } + PDH_FMT_COUNTERVALUE_ITEM *pDisplayValues = NULL; + PDH_STATUS status = PdhOpenQuery(NULL, NULL, &hQuery); if (FAILED(status)) goto die; - status = PdhAddCounter(hQuery, pI.wsFullPath.c_str(), NULL, &hCounter); + status = PdhAddEnglishCounter(hQuery, pI.wsFullPath.c_str(), NULL, &hCounter); + + if (FAILED(status)) + status = PdhAddCounter(hQuery, pI.wsFullPath.c_str(), NULL, &hCounter); + if (FAILED(status)) goto die; @@ -314,35 +292,32 @@ BOOL QueryPerfData(printInfoStruct& pI) if (FAILED(status)) goto die; - /* - /* Most counters need two queries to provide a value. - /* Those which need only one will return the second. - */ + /* + * Most counters need two queries to provide a value. + * Those which need only one will return the second. + */ Sleep(pI.dwPerformanceWait); status = PdhCollectQueryData(hQuery); if (FAILED(status)) goto die; - status = PdhGetFormattedCounterArray(hCounter, pI.dwRequestedType, - &dwBufferSize, &dwItemCount, pDisplayValues); + status = PdhGetFormattedCounterArray(hCounter, pI.dwRequestedType, &dwBufferSize, &dwItemCount, NULL); if (status != PDH_MORE_DATA) goto die; pDisplayValues = reinterpret_cast(new BYTE[dwBufferSize]); - status = PdhGetFormattedCounterArray(hCounter, pI.dwRequestedType, - &dwBufferSize, &dwItemCount, pDisplayValues); + status = PdhGetFormattedCounterArray(hCounter, pI.dwRequestedType, &dwBufferSize, &dwItemCount, pDisplayValues); if (FAILED(status)) goto die; - switch (pI.dwRequestedType) - { + switch (pI.dwRequestedType) { case (PDH_FMT_LONG): pI.dValue = pDisplayValues[0].FmtValue.longValue; break; case (PDH_FMT_LARGE): - pI.dValue = pDisplayValues[0].FmtValue.largeValue; + pI.dValue = (double) pDisplayValues[0].FmtValue.largeValue; break; default: pI.dValue = pDisplayValues[0].FmtValue.doubleValue; @@ -351,60 +326,62 @@ BOOL QueryPerfData(printInfoStruct& pI) delete[]pDisplayValues; - return TRUE; + return true; die: - FormatPDHError(status); + printPDHError(status); delete[]pDisplayValues; - return FALSE; + return false; } -INT PrintOutput(CONST po::variables_map& vm, printInfoStruct& pi) +static int printOutput(const po::variables_map& vm, printInfoStruct& pi) { std::wstringstream wssPerfData; - if (vm.count("perf-syntax")) { - wssPerfData << "\"" << vm["perf-syntax"].as() << "\"="; - } else { - wssPerfData << "\"" << pi.wsFullPath << "\"="; - } + if (vm.count("perf-syntax")) + wssPerfData << "'" << vm["perf-syntax"].as() << "'="; + else + wssPerfData << "'" << pi.wsFullPath << "'="; wssPerfData << pi.dValue << ';' << pi.tWarn.pString() << ';' << pi.tCrit.pString() << ";;"; if (pi.tCrit.rend(pi.dValue)) { - std::wcout << "PERFMON CRITICAL \"" << (vm.count("perf-syntax") ? vm["perf-syntax"].as() : pi.wsFullPath) - << "\" = " << pi.dValue << " | " << wssPerfData.str() << '\n'; + std::wcout << "PERFMON CRITICAL for '" << (vm.count("perf-syntax") ? vm["perf-syntax"].as() : pi.wsFullPath) + << "' = " << pi.dValue << " | " << wssPerfData.str() << "\n"; return 2; } if (pi.tWarn.rend(pi.dValue)) { - std::wcout << "PERFMON WARNING \"" << (vm.count("perf-syntax") ? vm["perf-syntax"].as() : pi.wsFullPath) - << "\" = " << pi.dValue << " | " << wssPerfData.str() << '\n'; + std::wcout << "PERFMON WARNING for '" << (vm.count("perf-syntax") ? vm["perf-syntax"].as() : pi.wsFullPath) + << "' = " << pi.dValue << " | " << wssPerfData.str() << "\n"; return 1; } - std::wcout << "PERFMON OK \"" << (vm.count("perf-syntax") ? vm["perf-syntax"].as() : pi.wsFullPath) - << "\" = " << pi.dValue << " | " << wssPerfData.str() << '\n'; + std::wcout << "PERFMON OK for '" << (vm.count("perf-syntax") ? vm["perf-syntax"].as() : pi.wsFullPath) + << "' = " << pi.dValue << " | " << wssPerfData.str() << "\n"; + return 0; } -VOID FormatPDHError(PDH_STATUS status) +int wmain(int argc, WCHAR **argv) { - HANDLE hPdhLibrary = NULL; - LPWSTR pMessage = NULL; + po::variables_map variables_map; + printInfoStruct stPrintInfo; + if (!parseArguments(argc, argv, variables_map, stPrintInfo)) + return 3; - hPdhLibrary = LoadLibrary(L"pdh.dll"); - if (NULL == hPdhLibrary) { - std::wcout << "LoadLibrary failed with " << GetLastError() << '\n'; - return; + if (variables_map.count("print-objects")) { + printObjects(); + return 0; } - if (!FormatMessage(FORMAT_MESSAGE_FROM_HMODULE | FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_ARGUMENT_ARRAY, - hPdhLibrary, status, 0, (LPWSTR)&pMessage, 0, NULL)) { - std::wcout << "Format message failed with " << std::hex << GetLastError() << '\n'; - return; + if (variables_map.count("print-object-info")) { + printObjectInfo(stPrintInfo); + return 0; } - std::wcout << pMessage << '\n'; - LocalFree(pMessage); + if (QueryPerfData(stPrintInfo)) + return printOutput(variables_map, stPrintInfo); + else + return 3; }