]> granicus.if.org Git - icinga2/blob - plugins/check_load.cpp
Change some things up in the windows-plugins
[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                 ("help,h", "print usage message and exit")
71                 ("version,V", "print version and exit")
72                 ("warning,w", po::wvalue<wstring>(), "warning value (in percent)")
73                 ("critical,c", po::wvalue<wstring>(), "critical value (in percent)")
74                 ;
75
76         po::basic_command_line_parser<wchar_t> parser(ac, av);
77
78         try {
79                 po::store(
80                         parser
81                         .options(desc)
82                         .style(
83                         po::command_line_style::unix_style |
84                         po::command_line_style::allow_long_disguise)
85                         .run(),
86                         vm);
87                 vm.notify();
88         } catch (std::exception& e) {
89                 cout << e.what() << endl << desc << endl;
90                 return 3;
91         }
92
93         if (vm.count("help")) {
94                 wcout << progName << " Help\n\tVersion: " << VERSION << endl;
95                 wprintf(
96                         L"%s is a simple program to check a machines CPU load.\n"
97                         L"You can use the following options to define its behaviour:\n\n", progName);
98                 cout << desc;
99                 wprintf(
100                         L"\nIt will then output a string looking something like this:\n\n"
101                         L"\tLOAD WARNING 67%%|load=67%%;50%%;90%%;0;100\n\n"
102                         L"\"LOAD\" being the type of the check, \"WARNING\" the returned status\n"
103                         L"and \"67%%\" is the returned value.\n"
104                         L"The performance data is found behind the \"|\", in order:\n"
105                         L"returned value, warning threshold, critical threshold, minimal value and,\n"
106                         L"if applicable, the maximal value.\n\n"
107                         L"%s' exit codes denote the following:\n"
108                         L" 0\tOK,\n\tNo Thresholds were broken or the programs check part was not executed\n"
109                         L" 1\tWARNING,\n\tThe warning, but not the critical threshold was broken\n"
110                         L" 2\tCRITICAL,\n\tThe critical threshold was broken\n"
111                         L" 3\tUNKNOWN, \n\tThe program experienced an internal or input error\n\n"
112                         L"Threshold syntax:\n\n"
113                         L"-w THRESHOLD\n"
114                         L"warn if threshold is broken, which means VALUE > THRESHOLD\n"
115                         L"(unless stated differently)\n\n"
116                         L"-w !THRESHOLD\n"
117                         L"inverts threshold check, VALUE < THRESHOLD (analogous to above)\n\n"
118                         L"-w [THR1-THR2]\n"
119                         L"warn is VALUE is inside the range spanned by THR1 and THR2\n\n"
120                         L"-w ![THR1-THR2]\n"
121                         L"warn if VALUE is outside the range spanned by THR1 and THR2\n\n"
122                         L"-w THRESHOLD%%\n"
123                         L"if the plugin accepts percentage based thresholds those will be used.\n"
124                         L"Does nothing if the plugin does not accept percentages, or only uses\n"
125                         L"percentage thresholds. Ranges can be used with \"%%\", but both range values need\n"
126                         L"to end with a percentage sign.\n\n"
127                         L"All of these options work with the critical threshold \"-c\" too."
128                         , progName);
129                 cout << endl;
130                 return 0;
131         }
132
133         if (vm.count("version"))
134                 cout << "Version: " << VERSION << endl;
135
136         if (vm.count("warning")) {
137                 try {
138                         std::wstring wthreshold = vm["warning"].as<wstring>();
139                         std::vector<std::wstring> tokens;
140                         boost::algorithm::split(tokens, wthreshold, boost::algorithm::is_any_of(","));
141                         printInfo.warn = threshold(tokens[0]);
142                 } catch (std::invalid_argument& e) {
143                         cout << e.what() << endl;
144                         return 3;
145                 }
146         }
147         if (vm.count("critical")) {
148                 try {
149                         std::wstring cthreshold = vm["critical"].as<wstring>();
150                         std::vector<std::wstring> tokens;
151                         boost::algorithm::split(tokens, cthreshold, boost::algorithm::is_any_of(","));
152                         printInfo.crit = threshold(tokens[0]);
153                 } catch (std::invalid_argument& e) {
154                         cout << e.what() << endl;
155                         return 3;
156                 }
157         }
158
159         return -1;
160 }
161
162 int printOutput(printInfoStruct& printInfo) 
163 {
164         state state = OK;
165
166         if (printInfo.warn.rend(printInfo.load))
167                 state = WARNING;
168
169         if (printInfo.crit.rend(printInfo.load))
170                 state = CRITICAL;
171
172         std::wstringstream perf;
173         perf << L"% | load=" << printInfo.load << L"%;" << printInfo.warn.pString() << L";" 
174                 << printInfo.crit.pString() << L";0;100" << endl;
175
176         switch (state) {
177         case OK:
178                 wcout << L"LOAD OK " << printInfo.load << perf.str();
179                 break;
180         case WARNING:
181                 wcout << L"LOAD WARNING " << printInfo.load << perf.str();
182                 break;
183         case CRITICAL:
184                 wcout << L"LOAD CRITICAL " << printInfo.load << perf.str();
185                 break;
186         }
187
188         return state;
189 }
190
191 int check_load(printInfoStruct& printInfo) 
192 {
193         PDH_HQUERY phQuery;
194         PDH_HCOUNTER phCounter;
195         DWORD dwBufferSize = 0;
196         DWORD CounterType;
197         PDH_FMT_COUNTERVALUE DisplayValue;
198         PDH_STATUS err;
199
200         LPCWSTR path = L"\\Processor(_Total)\\% Idle Time";
201
202         err = PdhOpenQuery(NULL, NULL, &phQuery);
203         if (!SUCCEEDED(err))
204                 goto die;
205
206         err = PdhAddEnglishCounter(phQuery, path, NULL, &phCounter);
207         if (!SUCCEEDED(err))
208                 goto die;
209
210         err = PdhCollectQueryData(phQuery);
211         if (!SUCCEEDED(err))
212                 goto die;
213
214         Sleep(1000);
215
216         err = PdhCollectQueryData(phQuery);
217         if (!SUCCEEDED(err))
218                 goto die;
219
220         err = PdhGetFormattedCounterValue(phCounter, PDH_FMT_DOUBLE, &CounterType, &DisplayValue);
221         if (SUCCEEDED(err)) {
222                 if (DisplayValue.CStatus == PDH_CSTATUS_VALID_DATA)
223                         printInfo.load = 100.0 - DisplayValue.doubleValue;
224                 PdhCloseQuery(phQuery);
225                 return -1;
226         }
227
228 die:
229         die();
230         if (phQuery)
231                 PdhCloseQuery(phQuery);
232         return 3;
233 }