-/******************************************************************************
-* Icinga 2 *
-* Copyright (C) 2012-2015 Icinga Development Team (http://www.icinga.org) *
-* *
-* 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 <Shlwapi.h>
+/* Icinga 2 | (c) 2012 Icinga GmbH | GPLv2+ */
+
+#include "plugins/thresholds.hpp"
+#include <boost/program_options.hpp>
#include <iostream>
#include <vector>
-
-#include "check_perfmon.h"
+#include <windows.h>
+#include <pdh.h>
+#include <pdhmsg.h>
+#include <shlwapi.h>
#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);
("fmt-countertype", po::wvalue<std::wstring>(), "Value type of counter: 'double'(default), 'long', 'int64'")
("print-objects", "Prints all available objects to console")
("print-object-info", "Prints all available instances and counters of --performance-counter, do not use a full perfomance counter string here")
+ ("perf-syntax", po::wvalue<std::wstring>(), "Use this string as name for the performance counter (graphite compatibility)")
;
- po::basic_command_line_parser<wchar_t> 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")) {
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<std::wstring>());
- } 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<std::wstring>());
- } catch (std::invalid_argument& e) {
+ } catch (const std::invalid_argument& e) {
std::wcout << e.what() << '\n';
- return FALSE;
+ return false;
}
}
if (vm.count("fmt-countertype")) {
- if (vm["fmt-countertype"].as<std::wstring>().compare(L"double"))
- printInfo.dwRequestedType = PDH_FMT_DOUBLE;
- else if (vm["fmt-countertype"].as<std::wstring>().compare(L"int64"))
+ if (!vm["fmt-countertype"].as<std::wstring>().compare(L"int64"))
printInfo.dwRequestedType = PDH_FMT_LARGE;
- else if (vm["fmt-countertype"].as<std::wstring>().compare(L"long"))
+ else if (!vm["fmt-countertype"].as<std::wstring>().compare(L"long"))
printInfo.dwRequestedType = PDH_FMT_LONG;
- else {
+ else if (vm["fmt-countertype"].as<std::wstring>().compare(L"double")) {
std::wcout << "Unknown value type " << vm["fmt-countertype"].as<std::wstring>() << '\n';
- return FALSE;
+ return false;
}
}
if (vm.count("performance-wait"))
printInfo.dwPerformanceWait = vm["performance-wait"].as<DWORD>();
- return TRUE;
+ return true;
}
-BOOL GetIntstancesAndCountersOfObject(CONST std::wstring wsObject,
- std::vector<std::wstring>& vecInstances,
- std::vector<std::wstring>& vecCounters)
+static bool getInstancesAndCountersOfObject(const std::wstring& wsObject,
+ std::vector<std::wstring>& vecInstances, std::vector<std::wstring>& 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());
+ if (PdhEnumObjectItems(NULL, NULL, wsObject.c_str(),
+ NULL, &dwCounterListLength, NULL,
+ &dwInstanceListLength, PERF_DETAIL_WIZARD, 0) != PDH_MORE_DATA)
+ return false;
- PDH_STATUS status =
- PdhEnumObjectItems(szDataSource, szMachineName, szObjectName,
- mszCounterList, &dwCounterListLength, mszInstanceList,
- &dwInstanceListLength, PERF_DETAIL_WIZARD, 0);
+ std::vector<WCHAR> mszCounterList(dwCounterListLength + 1);
+ std::vector<WCHAR> mszInstanceList(dwInstanceListLength + 1);
- if (status != PDH_MORE_DATA) {
- delete[]szObjectName;
- return FALSE;
- }
-
- mszCounterList = new WCHAR[dwCounterListLength + 1];
- mszInstanceList = new WCHAR[dwInstanceListLength + 1];
-
- status = PdhEnumObjectItems(szDataSource, szMachineName, szObjectName,
- mszCounterList, &dwCounterListLength, mszInstanceList,
- &dwInstanceListLength, PERF_DETAIL_WIZARD, 0);
-
- 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 {
}
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<WCHAR> 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;
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";
std::vector<std::wstring> 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;
}
if (vecInstances.empty())
std::wcout << "> Has no instances\n";
else {
- for (std::vector<std::wstring>::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;
if (vecCounters.empty())
std::wcout << "> Has no counters\n";
else {
- for (std::vector<std::wstring>::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;
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<PDH_FMT_COUNTERVALUE_ITEM*>(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;
- case (PDH_FMT_LARGE) :
- pI.dValue = pDisplayValues[0].FmtValue.largeValue;
+ break;
+ case (PDH_FMT_LARGE):
+ pI.dValue = (double) pDisplayValues[0].FmtValue.largeValue;
+ break;
default:
pI.dValue = pDisplayValues[0].FmtValue.doubleValue;
+ break;
}
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;
- wssPerfData << "perfmon=" << pi.dValue << ';'
- << pi.tWarn.pString() << ';' << pi.tCrit.pString() << ";; "
- << '"' << pi.wsFullPath << "\"=" << pi.dValue;
+
+ if (vm.count("perf-syntax"))
+ wssPerfData << "'" << vm["perf-syntax"].as<std::wstring>() << "'=";
+ else
+ wssPerfData << "'" << pi.wsFullPath << "'=";
+
+ wssPerfData << pi.dValue << ';' << pi.tWarn.pString() << ';' << pi.tCrit.pString() << ";;";
if (pi.tCrit.rend(pi.dValue)) {
- std::wcout << "PERFMON CRITICAL \"" << pi.wsFullPath << "\" = "
- << pi.dValue << " | " << wssPerfData.str() << '\n';
+ std::wcout << "PERFMON CRITICAL for '" << (vm.count("perf-syntax") ? vm["perf-syntax"].as<std::wstring>() : pi.wsFullPath)
+ << "' = " << pi.dValue << " | " << wssPerfData.str() << "\n";
return 2;
}
if (pi.tWarn.rend(pi.dValue)) {
- std::wcout << "PERFMON WARNING \"" << pi.wsFullPath << "\" = "
- << pi.dValue << " | " << wssPerfData.str() << '\n';
+ std::wcout << "PERFMON WARNING for '" << (vm.count("perf-syntax") ? vm["perf-syntax"].as<std::wstring>() : pi.wsFullPath)
+ << "' = " << pi.dValue << " | " << wssPerfData.str() << "\n";
return 1;
}
- std::wcout << "PERFMON OK \"" << pi.wsFullPath << "\" = "
- << pi.dValue << " | " << wssPerfData.str() << '\n';
+ std::wcout << "PERFMON OK for '" << (vm.count("perf-syntax") ? vm["perf-syntax"].as<std::wstring>() : 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;
}