]> granicus.if.org Git - icinga2/blob - plugins/check_load.cpp
Add windows-plugin check_ping
[icinga2] / plugins / check_load.cpp
1 /******************************************************************************
2  * Icinga 2                                                                   *
3  * Copyright (C) 2012-2014 Icinga Development Team (http://www.icinga.org)    *
4  *                                                                            *
5  * This program is free software; you can redistribute it and/or              *
6  * modify it under the terms of the GNU General Public License                *
7  * as published by the Free Software Foundation; either version 2             *
8  * of the License, or (at your option) any later version.                     *
9  *                                                                            *
10  * This program is distributed in the hope that it will be useful,            *
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of             *
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the              *
13  * GNU General Public License for more details.                               *
14  *                                                                            *
15  * You should have received a copy of the GNU General Public License          *
16  * along with this program; if not, write to the Free Software Foundation     *
17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.             *
18  ******************************************************************************/
19
20 #include "thresholds.h"
21 #include <boost/program_options.hpp>
22 #include <boost/algorithm/string/split.hpp>
23 #include <boost/algorithm/string/classification.hpp>
24 #include <Pdh.h>
25 #include <Shlwapi.h>
26 #include <pdhmsg.h>
27 #include <iostream>
28
29 #define VERSION 1.0
30
31 namespace po = boost::program_options;
32
33 using std::endl; using std::cout; using std::wstring;
34 using std::wcout;
35
36 struct printInfoStruct 
37 {
38         threshold warn, crit;
39         double load;
40 };
41
42 static int parseArguments(int, wchar_t **, po::variables_map&, printInfoStruct&);
43 static int printOutput(printInfoStruct&);
44 static int check_load(printInfoStruct&);
45
46 int wmain(int argc, wchar_t **argv) 
47 {
48         printInfoStruct printInfo{ };
49         po::variables_map vm;
50
51         int ret = parseArguments(argc, argv, vm, printInfo);
52         if (ret != -1)
53                 return ret;
54
55         ret = check_load(printInfo);
56         if (ret != -1)
57                 return ret;
58
59         return printOutput(printInfo);
60 }
61
62 int parseArguments(int ac, wchar_t **av, po::variables_map& vm, printInfoStruct& printInfo) {
63         wchar_t namePath[MAX_PATH];
64         GetModuleFileName(NULL, namePath, MAX_PATH);
65         wchar_t *progName = PathFindFileName(namePath);
66
67         po::options_description desc;
68
69         desc.add_options()
70                 (",h", "print usage message and exit")
71                 ("help", "print help message and exit")
72                 ("version,v", "print version and exit")
73                 ("warning,w", po::wvalue<wstring>(), "warning value (in percent)")
74                 ("critical,c", po::wvalue<wstring>(), "critical value (in percent)")
75                 ;
76
77         po::basic_command_line_parser<wchar_t> parser(ac, av);
78
79         try {
80                 po::store(
81                         parser
82                         .options(desc)
83                         .style(
84                         po::command_line_style::unix_style |
85                         po::command_line_style::allow_long_disguise)
86                         .run(),
87                         vm);
88                 vm.notify();
89         } catch (std::exception& e) {
90                 cout << e.what() << endl << desc << endl;
91                 return 3;
92         }
93
94         if (vm.count("h")) {
95                 cout << desc << endl;
96                 return 0;
97         }
98
99         if (vm.count("help")) {
100                 wcout << progName << " Help\n\tVersion: " << VERSION << endl;
101                 wprintf(
102                         L"%s is a simple program to check a machines CPU load.\n"
103                         L"You can use the following options to define its behaviour:\n\n", progName);
104                 cout << desc;
105                 wprintf(
106                         L"\nIt will then output a string looking something like this:\n\n"
107                         L"\tLOAD WARNING 67%%|load=67%%;50%%;90%%;0;100\n\n"
108                         L"\"LOAD\" being the type of the check, \"WARNING\" the returned status\n"
109                         L"and \"67%%\" is the returned value.\n"
110                         L"The performance data is found behind the \"|\", in order:\n"
111                         L"returned value, warning threshold, critical threshold, minimal value and,\n"
112                         L"if applicable, the maximal value.\n\n"
113                         L"%s' exit codes denote the following:\n"
114                         L" 0\tOK,\n\tNo Thresholds were broken or the programs check part was not executed\n"
115                         L" 1\tWARNING,\n\tThe warning, but not the critical threshold was broken\n"
116                         L" 2\tCRITICAL,\n\tThe critical threshold was broken\n"
117                         L" 3\tUNKNOWN, \n\tThe program experienced an internal or input error\n\n"
118                         L"Threshold syntax:\n\n"
119                         L"-w THRESHOLD\n"
120                         L"warn if threshold is broken, which means VALUE > THRESHOLD\n"
121                         L"(unless stated differently)\n\n"
122                         L"-w !THRESHOLD\n"
123                         L"inverts threshold check, VALUE < THRESHOLD (analogous to above)\n\n"
124                         L"-w [THR1-THR2]\n"
125                         L"warn is VALUE is inside the range spanned by THR1 and THR2\n\n"
126                         L"-w ![THR1-THR2]\n"
127                         L"warn if VALUE is outside the range spanned by THR1 and THR2\n\n"
128                         L"-w THRESHOLD%%\n"
129                         L"if the plugin accepts percentage based thresholds those will be used.\n"
130                         L"Does nothing if the plugin does not accept percentages, or only uses\n"
131                         L"percentage thresholds. Ranges can be used with \"%%\", but both range values need\n"
132                         L"to end with a percentage sign.\n\n"
133                         L"All of these options work with the critical threshold \"-c\" too."
134                         , progName);
135                 cout << endl;
136                 return 0;
137         }
138
139         if (vm.count("version"))
140                 cout << "Version: " << VERSION << endl;
141
142         if (vm.count("warning")) {
143                 try {
144                         std::wstring wthreshold = vm["warning"].as<wstring>();
145                         std::vector<std::wstring> tokens;
146                         boost::algorithm::split(tokens, wthreshold, boost::algorithm::is_any_of(","));
147                         printInfo.warn = threshold(tokens[0]);
148                 } catch (std::invalid_argument& e) {
149                         cout << e.what() << endl;
150                         return 3;
151                 }
152         }
153         if (vm.count("critical")) {
154                 try {
155                         std::wstring cthreshold = vm["critical"].as<wstring>();
156                         std::vector<std::wstring> tokens;
157                         boost::algorithm::split(tokens, cthreshold, boost::algorithm::is_any_of(","));
158                         printInfo.crit = threshold(tokens[0]);
159                 } catch (std::invalid_argument& e) {
160                         cout << e.what() << endl;
161                         return 3;
162                 }
163         }
164
165         return -1;
166 }
167
168 int printOutput(printInfoStruct& printInfo) 
169 {
170         state state = OK;
171
172         if (printInfo.warn.rend(printInfo.load))
173                 state = WARNING;
174
175         if (printInfo.crit.rend(printInfo.load))
176                 state = CRITICAL;
177
178         std::wstringstream perf;
179         perf << L"%|load=" << printInfo.load << L"%;" << printInfo.warn.pString() << L";" 
180                 << printInfo.crit.pString() << L";0;100" << endl;
181
182         switch (state) {
183         case OK:
184                 wcout << L"LOAD OK " << printInfo.load << perf.str();
185                 break;
186         case WARNING:
187                 wcout << L"LOAD WARNING " << printInfo.load << perf.str();
188                 break;
189         case CRITICAL:
190                 wcout << L"LOAD CRITICAL " << printInfo.load << perf.str();
191                 break;
192         }
193
194         return state;
195 }
196
197 int check_load(printInfoStruct& printInfo) 
198 {
199         PDH_HQUERY phQuery;
200         PDH_HCOUNTER phCounter;
201         DWORD dwBufferSize = 0;
202         DWORD CounterType;
203         PDH_FMT_COUNTERVALUE DisplayValue;
204         PDH_STATUS err;
205
206         LPCWSTR path = L"\\Processor(_Total)\\% Idle Time";
207
208         err = PdhOpenQuery(NULL, NULL, &phQuery);
209         if (!SUCCEEDED(err))
210                 goto die;
211
212         err = PdhAddEnglishCounter(phQuery, path, NULL, &phCounter);
213         if (!SUCCEEDED(err))
214                 goto die;
215
216         err = PdhCollectQueryData(phQuery);
217         if (!SUCCEEDED(err))
218                 goto die;
219
220         Sleep(1000);
221
222         err = PdhCollectQueryData(phQuery);
223         if (!SUCCEEDED(err))
224                 goto die;
225
226         err = PdhGetFormattedCounterValue(phCounter, PDH_FMT_DOUBLE, &CounterType, &DisplayValue);
227         if (SUCCEEDED(err)) {
228                 if (DisplayValue.CStatus == PDH_CSTATUS_VALID_DATA)
229                         printInfo.load = 100.0 - DisplayValue.doubleValue;
230                 PdhCloseQuery(phQuery);
231                 return -1;
232         }
233
234 die:
235         die();
236         if (phQuery)
237                 PdhCloseQuery(phQuery);
238         return 3;
239 }