1 /* Icinga 2 | (c) 2012 Icinga GmbH | GPLv2+ */
3 #include "plugins/thresholds.hpp"
4 #include <boost/program_options.hpp>
12 namespace po = boost::program_options;
14 struct printInfoStruct
28 SIZE_T availableSpwap;
33 BOOL EnumPageFilesProc(LPVOID pContext, PENUM_PAGE_FILE_INFORMATION pPageFileInfo, LPCWSTR lpFilename) {
34 std::vector<pageFileInfo>* pageFile = static_cast<std::vector<pageFileInfo>*>(pContext);
35 SYSTEM_INFO systemInfo;
37 GetSystemInfo(&systemInfo);
39 // pPageFileInfo output is in pages, we need to multiply it by the page size
40 pageFile->push_back({ pPageFileInfo->TotalSize * systemInfo.dwPageSize, (pPageFileInfo->TotalSize - pPageFileInfo->TotalInUse) * systemInfo.dwPageSize });
45 static int parseArguments(int ac, WCHAR **av, po::variables_map& vm, printInfoStruct& printInfo)
47 WCHAR namePath[MAX_PATH];
48 GetModuleFileName(NULL, namePath, MAX_PATH);
49 WCHAR *progName = PathFindFileName(namePath);
51 po::options_description desc;
54 ("help,h", "Print help message and exit")
55 ("version,V", "Print version and exit")
56 ("debug,d", "Verbose/Debug output")
57 ("warning,w", po::wvalue<std::wstring>(), "Warning threshold")
58 ("critical,c", po::wvalue<std::wstring>(), "Critical threshold")
59 ("unit,u", po::wvalue<std::wstring>(), "The unit to use for display (default MB)")
60 ("show-used,U", "Show used swap instead of the free swap")
63 po::wcommand_line_parser parser(ac, av);
70 po::command_line_style::unix_style |
71 po::command_line_style::allow_long_disguise)
75 } catch (const std::exception& e) {
76 std::cout << e.what() << '\n' << desc << '\n';
80 if (vm.count("help")) {
81 std::wcout << progName << " Help\n\tVersion: " << VERSION << '\n';
83 L"%s is a simple program to check a machines swap in percent.\n"
84 L"You can use the following options to define its behaviour:\n\n", progName);
87 L"\nIt will then output a string looking something like this:\n\n"
88 L"\tSWAP WARNING - 20%% free | swap=2000B;3000;500;0;10000\n\n"
89 L"\"SWAP\" being the type of the check, \"WARNING\" the returned status\n"
90 L"and \"20%%\" is the returned value.\n"
91 L"The performance data is found behind the \"|\", in order:\n"
92 L"returned value, warning threshold, critical threshold, minimal value and,\n"
93 L"if applicable, the maximal value. Performance data will only be displayed when\n"
94 L"you set at least one threshold\n\n"
95 L"%s' exit codes denote the following:\n"
96 L" 0\tOK,\n\tNo Thresholds were broken or the programs check part was not executed\n"
97 L" 1\tWARNING,\n\tThe warning, but not the critical threshold was broken\n"
98 L" 2\tCRITICAL,\n\tThe critical threshold was broken\n"
99 L" 3\tUNKNOWN, \n\tThe program experienced an internal or input error\n\n"
100 L"Threshold syntax:\n\n"
102 L"warn if threshold is broken, which means VALUE > THRESHOLD\n"
103 L"(unless stated differently)\n\n"
105 L"inverts threshold check, VALUE < THRESHOLD (analogous to above)\n\n"
107 L"warn is VALUE is inside the range spanned by THR1 and THR2\n\n"
109 L"warn if VALUE is outside the range spanned by THR1 and THR2\n\n"
111 L"if the plugin accepts percentage based thresholds those will be used.\n"
112 L"Does nothing if the plugin does not accept percentages, or only uses\n"
113 L"percentage thresholds. Ranges can be used with \"%%\", but both range values need\n"
114 L"to end with a percentage sign.\n\n"
115 L"All of these options work with the critical threshold \"-c\" too.\n"
121 if (vm.count("version"))
122 std::wcout << L"Version: " << VERSION << '\n';
124 if (vm.count("warning")) {
126 printInfo.warn = threshold(vm["warning"].as<std::wstring>());
127 } catch (const std::invalid_argument& e) {
128 std::cout << e.what() << '\n';
131 printInfo.warn.legal = !printInfo.warn.legal;
134 if (vm.count("critical")) {
136 printInfo.crit = threshold(vm["critical"].as<std::wstring>());
137 } catch (const std::invalid_argument& e) {
138 std::cout << e.what() << '\n';
141 printInfo.crit.legal = !printInfo.crit.legal;
144 l_Debug = vm.count("debug") > 0;
146 if (vm.count("unit")) {
148 printInfo.unit = parseBUnit(vm["unit"].as<std::wstring>());
149 } catch (const std::invalid_argument& e) {
150 std::cout << e.what() << '\n';
155 if (vm.count("show-used")) {
156 printInfo.showUsed = true;
157 printInfo.warn.legal = true;
158 printInfo.crit.legal = true;
164 static int printOutput(printInfoStruct& printInfo)
167 std::wcout << L"Constructing output string" << '\n';
171 std::wcout << L"SWAP ";
175 if (!printInfo.showUsed)
176 currentValue = printInfo.aSwap;
178 currentValue = printInfo.tSwap - printInfo.aSwap;
180 if (printInfo.warn.rend(currentValue, printInfo.tSwap))
183 if (printInfo.crit.rend(currentValue, printInfo.tSwap))
186 std::wcout << stateToString(state) << " - ";
188 if (!printInfo.showUsed)
189 std::wcout << printInfo.percentFree << L"% free ";
191 std::wcout << 100 - printInfo.percentFree << L"% used ";
193 std::wcout << "| 'swap'=" << currentValue << BunitStr(printInfo.unit) << L";"
194 << printInfo.warn.pString(printInfo.tSwap) << L";" << printInfo.crit.pString(printInfo.tSwap)
195 << L";0;" << printInfo.tSwap << '\n';
200 static int check_swap(printInfoStruct& printInfo)
202 // Needs explicit cast: http://msinilo.pl/blog2/post/p1348/
203 PENUM_PAGE_FILE_CALLBACKW pageFileCallback = (PENUM_PAGE_FILE_CALLBACKW)EnumPageFilesProc;
204 std::vector<pageFileInfo> pageFiles;
206 if(!EnumPageFilesW(pageFileCallback, &pageFiles)) {
211 for (int i = 0; i < pageFiles.size(); i++) {
212 printInfo.tSwap += round(pageFiles.at(i).totalSwap / pow(1024.0, printInfo.unit));
213 printInfo.aSwap += round(pageFiles.at(i).availableSpwap / pow(1024.0, printInfo.unit));
216 if (printInfo.aSwap > 0 && printInfo.tSwap > 0)
217 printInfo.percentFree = 100.0 * printInfo.aSwap / printInfo.tSwap;
219 printInfo.percentFree = 0;
224 int wmain(int argc, WCHAR **argv)
226 printInfoStruct printInfo = { };
227 po::variables_map vm;
229 int ret = parseArguments(argc, argv, vm, printInfo);
233 ret = check_swap(printInfo);
237 return printOutput(printInfo);