diff options
Diffstat (limited to 'plugins/check_pgsql.c')
-rw-r--r-- | plugins/check_pgsql.c | 275 |
1 files changed, 154 insertions, 121 deletions
diff --git a/plugins/check_pgsql.c b/plugins/check_pgsql.c index 6613634d..793a686f 100644 --- a/plugins/check_pgsql.c +++ b/plugins/check_pgsql.c | |||
@@ -28,6 +28,7 @@ | |||
28 | * | 28 | * |
29 | *****************************************************************************/ | 29 | *****************************************************************************/ |
30 | 30 | ||
31 | #include "states.h" | ||
31 | const char *progname = "check_pgsql"; | 32 | const char *progname = "check_pgsql"; |
32 | const char *copyright = "1999-2024"; | 33 | const char *copyright = "1999-2024"; |
33 | const char *email = "devel@monitoring-plugins.org"; | 34 | const char *email = "devel@monitoring-plugins.org"; |
@@ -35,51 +36,39 @@ const char *email = "devel@monitoring-plugins.org"; | |||
35 | #include "common.h" | 36 | #include "common.h" |
36 | #include "utils.h" | 37 | #include "utils.h" |
37 | #include "utils_cmd.h" | 38 | #include "utils_cmd.h" |
39 | #include "check_pgsql.d/config.h" | ||
40 | #include "thresholds.h" | ||
38 | 41 | ||
39 | #include "netutils.h" | 42 | #include "netutils.h" |
40 | #include <libpq-fe.h> | 43 | #include <libpq-fe.h> |
41 | #include <pg_config_manual.h> | 44 | #include <pg_config_manual.h> |
42 | 45 | ||
43 | #define DEFAULT_DB "template1" | ||
44 | #define DEFAULT_HOST "127.0.0.1" | 46 | #define DEFAULT_HOST "127.0.0.1" |
45 | 47 | ||
46 | /* return the PSQL server version as a 3-tuple */ | 48 | /* return the PSQL server version as a 3-tuple */ |
47 | #define PSQL_SERVER_VERSION3(server_version) \ | 49 | #define PSQL_SERVER_VERSION3(server_version) \ |
48 | (server_version) / 10000, (server_version) / 100 - (int)((server_version) / 10000) * 100, \ | 50 | (server_version) / 10000, (server_version) / 100 - (int)((server_version) / 10000) * 100, \ |
49 | (server_version) - (int)((server_version) / 100) * 100 | 51 | (server_version) - (int)((server_version) / 100) * 100 |
50 | /* return true if the given host is a UNIX domain socket */ | 52 | /* return true if the given host is a UNIX domain socket */ |
51 | #define PSQL_IS_UNIX_DOMAIN_SOCKET(host) ((NULL == (host)) || ('\0' == *(host)) || ('/' == *(host))) | 53 | #define PSQL_IS_UNIX_DOMAIN_SOCKET(host) ((NULL == (host)) || ('\0' == *(host)) || ('/' == *(host))) |
52 | /* return a 3-tuple identifying a host/port independent of the socket type */ | 54 | /* return a 3-tuple identifying a host/port independent of the socket type */ |
53 | #define PSQL_SOCKET3(host, port) \ | 55 | #define PSQL_SOCKET3(host, port) \ |
54 | ((NULL == (host)) || ('\0' == *(host))) ? DEFAULT_PGSOCKET_DIR : host, PSQL_IS_UNIX_DOMAIN_SOCKET(host) ? "/.s.PGSQL." : ":", port | 56 | ((NULL == (host)) || ('\0' == *(host))) ? DEFAULT_PGSOCKET_DIR : host, \ |
57 | PSQL_IS_UNIX_DOMAIN_SOCKET(host) ? "/.s.PGSQL." : ":", port | ||
55 | 58 | ||
56 | enum { | 59 | typedef struct { |
57 | DEFAULT_PORT = 5432, | 60 | int errorcode; |
58 | DEFAULT_WARN = 2, | 61 | check_pgsql_config config; |
59 | DEFAULT_CRIT = 8 | 62 | } check_pgsql_config_wrapper; |
60 | }; | 63 | static check_pgsql_config_wrapper process_arguments(int /*argc*/, char ** /*argv*/); |
61 | 64 | ||
62 | static int process_arguments(int /*argc*/, char ** /*argv*/); | ||
63 | static void print_help(void); | 65 | static void print_help(void); |
64 | static bool is_pg_logname(char * /*username*/); | 66 | static bool is_pg_logname(char * /*username*/); |
65 | static int do_query(PGconn * /*conn*/, char * /*query*/); | 67 | static mp_state_enum do_query(PGconn * /*conn*/, char * /*query*/, const char /*pgqueryname*/[], |
68 | thresholds * /*qthresholds*/, char * /*query_warning*/, | ||
69 | char * /*query_critical*/); | ||
66 | void print_usage(void); | 70 | void print_usage(void); |
67 | 71 | ||
68 | static char *pghost = NULL; /* host name of the backend server */ | ||
69 | static char *pgport = NULL; /* port of the backend server */ | ||
70 | static char *pgoptions = NULL; | ||
71 | static char *pgtty = NULL; | ||
72 | static char dbName[NAMEDATALEN] = DEFAULT_DB; | ||
73 | static char *pguser = NULL; | ||
74 | static char *pgpasswd = NULL; | ||
75 | static char *pgparams = NULL; | ||
76 | static double twarn = (double)DEFAULT_WARN; | ||
77 | static double tcrit = (double)DEFAULT_CRIT; | ||
78 | static char *pgquery = NULL; | ||
79 | static char *pgqueryname = NULL; | ||
80 | static char *query_warning = NULL; | ||
81 | static char *query_critical = NULL; | ||
82 | static thresholds *qthresholds = NULL; | ||
83 | static int verbose = 0; | 72 | static int verbose = 0; |
84 | 73 | ||
85 | #define OPTID_QUERYNAME -1000 | 74 | #define OPTID_QUERYNAME -1000 |
@@ -139,21 +128,19 @@ int main(int argc, char **argv) { | |||
139 | bindtextdomain(PACKAGE, LOCALEDIR); | 128 | bindtextdomain(PACKAGE, LOCALEDIR); |
140 | textdomain(PACKAGE); | 129 | textdomain(PACKAGE); |
141 | 130 | ||
142 | /* begin, by setting the parameters for a backend connection if the | ||
143 | * parameters are null, then the system will try to use reasonable | ||
144 | * defaults by looking up environment variables or, failing that, | ||
145 | * using hardwired constants */ | ||
146 | |||
147 | pgoptions = NULL; /* special options to start up the backend server */ | ||
148 | pgtty = NULL; /* debugging tty for the backend server */ | ||
149 | |||
150 | /* Parse extra opts if any */ | 131 | /* Parse extra opts if any */ |
151 | argv = np_extra_opts(&argc, argv, progname); | 132 | argv = np_extra_opts(&argc, argv, progname); |
152 | 133 | ||
153 | if (process_arguments(argc, argv) == ERROR) | 134 | check_pgsql_config_wrapper tmp_config = process_arguments(argc, argv); |
135 | if (tmp_config.errorcode == ERROR) { | ||
154 | usage4(_("Could not parse arguments")); | 136 | usage4(_("Could not parse arguments")); |
155 | if (verbose > 2) | 137 | } |
138 | |||
139 | const check_pgsql_config config = tmp_config.config; | ||
140 | |||
141 | if (verbose > 2) { | ||
156 | printf("Arguments initialized\n"); | 142 | printf("Arguments initialized\n"); |
143 | } | ||
157 | 144 | ||
158 | /* Set signal handling and alarm */ | 145 | /* Set signal handling and alarm */ |
159 | if (signal(SIGALRM, timeout_alarm_handler) == SIG_ERR) { | 146 | if (signal(SIGALRM, timeout_alarm_handler) == SIG_ERR) { |
@@ -162,25 +149,33 @@ int main(int argc, char **argv) { | |||
162 | alarm(timeout_interval); | 149 | alarm(timeout_interval); |
163 | 150 | ||
164 | char *conninfo = NULL; | 151 | char *conninfo = NULL; |
165 | if (pgparams) | 152 | if (config.pgparams) { |
166 | asprintf(&conninfo, "%s ", pgparams); | 153 | asprintf(&conninfo, "%s ", config.pgparams); |
167 | 154 | } | |
168 | asprintf(&conninfo, "%sdbname = '%s'", conninfo ? conninfo : "", dbName); | 155 | |
169 | if (pghost) | 156 | asprintf(&conninfo, "%sdbname = '%s'", conninfo ? conninfo : "", config.dbName); |
170 | asprintf(&conninfo, "%s host = '%s'", conninfo, pghost); | 157 | if (config.pghost) { |
171 | if (pgport) | 158 | asprintf(&conninfo, "%s host = '%s'", conninfo, config.pghost); |
172 | asprintf(&conninfo, "%s port = '%s'", conninfo, pgport); | 159 | } |
173 | if (pgoptions) | 160 | if (config.pgport) { |
174 | asprintf(&conninfo, "%s options = '%s'", conninfo, pgoptions); | 161 | asprintf(&conninfo, "%s port = '%s'", conninfo, config.pgport); |
162 | } | ||
163 | if (config.pgoptions) { | ||
164 | asprintf(&conninfo, "%s options = '%s'", conninfo, config.pgoptions); | ||
165 | } | ||
175 | /* if (pgtty) -- ignored by PQconnectdb */ | 166 | /* if (pgtty) -- ignored by PQconnectdb */ |
176 | if (pguser) | 167 | if (config.pguser) { |
177 | asprintf(&conninfo, "%s user = '%s'", conninfo, pguser); | 168 | asprintf(&conninfo, "%s user = '%s'", conninfo, config.pguser); |
169 | } | ||
178 | 170 | ||
179 | if (verbose) /* do not include password (see right below) in output */ | 171 | if (verbose) { /* do not include password (see right below) in output */ |
180 | printf("Connecting to PostgreSQL using conninfo: %s%s\n", conninfo, pgpasswd ? " password = <hidden>" : ""); | 172 | printf("Connecting to PostgreSQL using conninfo: %s%s\n", conninfo, |
173 | config.pgpasswd ? " password = <hidden>" : ""); | ||
174 | } | ||
181 | 175 | ||
182 | if (pgpasswd) | 176 | if (config.pgpasswd) { |
183 | asprintf(&conninfo, "%s password = '%s'", conninfo, pgpasswd); | 177 | asprintf(&conninfo, "%s password = '%s'", conninfo, config.pgpasswd); |
178 | } | ||
184 | 179 | ||
185 | /* make a connection to the database */ | 180 | /* make a connection to the database */ |
186 | struct timeval start_timeval; | 181 | struct timeval start_timeval; |
@@ -193,25 +188,27 @@ int main(int argc, char **argv) { | |||
193 | --end_timeval.tv_sec; | 188 | --end_timeval.tv_sec; |
194 | end_timeval.tv_usec += 1000000; | 189 | end_timeval.tv_usec += 1000000; |
195 | } | 190 | } |
196 | double elapsed_time = | 191 | double elapsed_time = (double)(end_timeval.tv_sec - start_timeval.tv_sec) + |
197 | (double)(end_timeval.tv_sec - start_timeval.tv_sec) + (double)(end_timeval.tv_usec - start_timeval.tv_usec) / 1000000.0; | 192 | ((double)(end_timeval.tv_usec - start_timeval.tv_usec) / 1000000.0); |
198 | 193 | ||
199 | if (verbose) | 194 | if (verbose) { |
200 | printf("Time elapsed: %f\n", elapsed_time); | 195 | printf("Time elapsed: %f\n", elapsed_time); |
196 | } | ||
201 | 197 | ||
202 | /* check to see that the backend connection was successfully made */ | 198 | /* check to see that the backend connection was successfully made */ |
203 | if (verbose) | 199 | if (verbose) { |
204 | printf("Verifying connection\n"); | 200 | printf("Verifying connection\n"); |
201 | } | ||
205 | if (PQstatus(conn) == CONNECTION_BAD) { | 202 | if (PQstatus(conn) == CONNECTION_BAD) { |
206 | printf(_("CRITICAL - no connection to '%s' (%s).\n"), dbName, PQerrorMessage(conn)); | 203 | printf(_("CRITICAL - no connection to '%s' (%s).\n"), config.dbName, PQerrorMessage(conn)); |
207 | PQfinish(conn); | 204 | PQfinish(conn); |
208 | return STATE_CRITICAL; | 205 | return STATE_CRITICAL; |
209 | } | 206 | } |
210 | 207 | ||
211 | int status = STATE_UNKNOWN; | 208 | mp_state_enum status = STATE_UNKNOWN; |
212 | if (elapsed_time > tcrit) { | 209 | if (elapsed_time > config.tcrit) { |
213 | status = STATE_CRITICAL; | 210 | status = STATE_CRITICAL; |
214 | } else if (elapsed_time > twarn) { | 211 | } else if (elapsed_time > config.twarn) { |
215 | status = STATE_WARNING; | 212 | status = STATE_WARNING; |
216 | } else { | 213 | } else { |
217 | status = STATE_OK; | 214 | status = STATE_OK; |
@@ -224,25 +221,29 @@ int main(int argc, char **argv) { | |||
224 | printf("Successfully connected to database %s (user %s) " | 221 | printf("Successfully connected to database %s (user %s) " |
225 | "at server %s%s%s (server version: %d.%d.%d, " | 222 | "at server %s%s%s (server version: %d.%d.%d, " |
226 | "protocol version: %d, pid: %d)\n", | 223 | "protocol version: %d, pid: %d)\n", |
227 | PQdb(conn), PQuser(conn), PSQL_SOCKET3(server_host, PQport(conn)), PSQL_SERVER_VERSION3(server_version), | 224 | PQdb(conn), PQuser(conn), PSQL_SOCKET3(server_host, PQport(conn)), |
228 | PQprotocolVersion(conn), PQbackendPID(conn)); | 225 | PSQL_SERVER_VERSION3(server_version), PQprotocolVersion(conn), PQbackendPID(conn)); |
229 | } | 226 | } |
230 | 227 | ||
231 | printf(_(" %s - database %s (%f sec.)|%s\n"), state_text(status), dbName, elapsed_time, | 228 | printf(_(" %s - database %s (%f sec.)|%s\n"), state_text(status), config.dbName, elapsed_time, |
232 | fperfdata("time", elapsed_time, "s", !!(twarn > 0.0), twarn, !!(tcrit > 0.0), tcrit, true, 0, false, 0)); | 229 | fperfdata("time", elapsed_time, "s", (config.twarn > 0.0), config.twarn, |
230 | (config.tcrit > 0.0), config.tcrit, true, 0, false, 0)); | ||
233 | 231 | ||
234 | int query_status = STATE_UNKNOWN; | 232 | mp_state_enum query_status = STATE_UNKNOWN; |
235 | if (pgquery) | 233 | if (config.pgquery) { |
236 | query_status = do_query(conn, pgquery); | 234 | query_status = do_query(conn, config.pgquery, config.pgqueryname, config.qthresholds, |
235 | config.query_warning, config.query_critical); | ||
236 | } | ||
237 | 237 | ||
238 | if (verbose) | 238 | if (verbose) { |
239 | printf("Closing connection\n"); | 239 | printf("Closing connection\n"); |
240 | } | ||
240 | PQfinish(conn); | 241 | PQfinish(conn); |
241 | return (pgquery && query_status > status) ? query_status : status; | 242 | return (config.pgquery && query_status > status) ? query_status : status; |
242 | } | 243 | } |
243 | 244 | ||
244 | /* process command-line arguments */ | 245 | /* process command-line arguments */ |
245 | int process_arguments(int argc, char **argv) { | 246 | check_pgsql_config_wrapper process_arguments(int argc, char **argv) { |
246 | static struct option longopts[] = {{"help", no_argument, 0, 'h'}, | 247 | static struct option longopts[] = {{"help", no_argument, 0, 'h'}, |
247 | {"version", no_argument, 0, 'V'}, | 248 | {"version", no_argument, 0, 'V'}, |
248 | {"timeout", required_argument, 0, 't'}, | 249 | {"timeout", required_argument, 0, 't'}, |
@@ -262,12 +263,19 @@ int process_arguments(int argc, char **argv) { | |||
262 | {"verbose", no_argument, 0, 'v'}, | 263 | {"verbose", no_argument, 0, 'v'}, |
263 | {0, 0, 0, 0}}; | 264 | {0, 0, 0, 0}}; |
264 | 265 | ||
266 | check_pgsql_config_wrapper result = { | ||
267 | .errorcode = OK, | ||
268 | .config = check_pgsql_config_init(), | ||
269 | }; | ||
270 | |||
265 | while (true) { | 271 | while (true) { |
266 | int option = 0; | 272 | int option = 0; |
267 | int option_char = getopt_long(argc, argv, "hVt:c:w:H:P:d:l:p:a:o:q:C:W:v", longopts, &option); | 273 | int option_char = |
274 | getopt_long(argc, argv, "hVt:c:w:H:P:d:l:p:a:o:q:C:W:v", longopts, &option); | ||
268 | 275 | ||
269 | if (option_char == EOF) | 276 | if (option_char == EOF) { |
270 | break; | 277 | break; |
278 | } | ||
271 | 279 | ||
272 | switch (option_char) { | 280 | switch (option_char) { |
273 | case '?': /* usage */ | 281 | case '?': /* usage */ |
@@ -279,68 +287,75 @@ int process_arguments(int argc, char **argv) { | |||
279 | print_revision(progname, NP_VERSION); | 287 | print_revision(progname, NP_VERSION); |
280 | exit(STATE_UNKNOWN); | 288 | exit(STATE_UNKNOWN); |
281 | case 't': /* timeout period */ | 289 | case 't': /* timeout period */ |
282 | if (!is_integer(optarg)) | 290 | if (!is_integer(optarg)) { |
283 | usage2(_("Timeout interval must be a positive integer"), optarg); | 291 | usage2(_("Timeout interval must be a positive integer"), optarg); |
284 | else | 292 | } else { |
285 | timeout_interval = atoi(optarg); | 293 | timeout_interval = atoi(optarg); |
294 | } | ||
286 | break; | 295 | break; |
287 | case 'c': /* critical time threshold */ | 296 | case 'c': /* critical time threshold */ |
288 | if (!is_nonnegative(optarg)) | 297 | if (!is_nonnegative(optarg)) { |
289 | usage2(_("Critical threshold must be a positive integer"), optarg); | 298 | usage2(_("Critical threshold must be a positive integer"), optarg); |
290 | else | 299 | } else { |
291 | tcrit = strtod(optarg, NULL); | 300 | result.config.tcrit = strtod(optarg, NULL); |
301 | } | ||
292 | break; | 302 | break; |
293 | case 'w': /* warning time threshold */ | 303 | case 'w': /* warning time threshold */ |
294 | if (!is_nonnegative(optarg)) | 304 | if (!is_nonnegative(optarg)) { |
295 | usage2(_("Warning threshold must be a positive integer"), optarg); | 305 | usage2(_("Warning threshold must be a positive integer"), optarg); |
296 | else | 306 | } else { |
297 | twarn = strtod(optarg, NULL); | 307 | result.config.twarn = strtod(optarg, NULL); |
308 | } | ||
298 | break; | 309 | break; |
299 | case 'C': /* critical query threshold */ | 310 | case 'C': /* critical query threshold */ |
300 | query_critical = optarg; | 311 | result.config.query_critical = optarg; |
301 | break; | 312 | break; |
302 | case 'W': /* warning query threshold */ | 313 | case 'W': /* warning query threshold */ |
303 | query_warning = optarg; | 314 | result.config.query_warning = optarg; |
304 | break; | 315 | break; |
305 | case 'H': /* host */ | 316 | case 'H': /* host */ |
306 | if ((*optarg != '/') && (!is_host(optarg))) | 317 | if ((*optarg != '/') && (!is_host(optarg))) { |
307 | usage2(_("Invalid hostname/address"), optarg); | 318 | usage2(_("Invalid hostname/address"), optarg); |
308 | else | 319 | } else { |
309 | pghost = optarg; | 320 | result.config.pghost = optarg; |
321 | } | ||
310 | break; | 322 | break; |
311 | case 'P': /* port */ | 323 | case 'P': /* port */ |
312 | if (!is_integer(optarg)) | 324 | if (!is_integer(optarg)) { |
313 | usage2(_("Port must be a positive integer"), optarg); | 325 | usage2(_("Port must be a positive integer"), optarg); |
314 | else | 326 | } else { |
315 | pgport = optarg; | 327 | result.config.pgport = optarg; |
328 | } | ||
316 | break; | 329 | break; |
317 | case 'd': /* database name */ | 330 | case 'd': /* database name */ |
318 | if (strlen(optarg) >= NAMEDATALEN) { | 331 | if (strlen(optarg) >= NAMEDATALEN) { |
319 | usage2(_("Database name exceeds the maximum length"), optarg); | 332 | usage2(_("Database name exceeds the maximum length"), optarg); |
320 | } | 333 | } |
321 | snprintf(dbName, NAMEDATALEN, "%s", optarg); | 334 | snprintf(result.config.dbName, NAMEDATALEN, "%s", optarg); |
322 | break; | 335 | break; |
323 | case 'l': /* login name */ | 336 | case 'l': /* login name */ |
324 | if (!is_pg_logname(optarg)) | 337 | if (!is_pg_logname(optarg)) { |
325 | usage2(_("User name is not valid"), optarg); | 338 | usage2(_("User name is not valid"), optarg); |
326 | else | 339 | } else { |
327 | pguser = optarg; | 340 | result.config.pguser = optarg; |
341 | } | ||
328 | break; | 342 | break; |
329 | case 'p': /* authentication password */ | 343 | case 'p': /* authentication password */ |
330 | case 'a': | 344 | case 'a': |
331 | pgpasswd = optarg; | 345 | result.config.pgpasswd = optarg; |
332 | break; | 346 | break; |
333 | case 'o': | 347 | case 'o': |
334 | if (pgparams) | 348 | if (result.config.pgparams) { |
335 | asprintf(&pgparams, "%s %s", pgparams, optarg); | 349 | asprintf(&result.config.pgparams, "%s %s", result.config.pgparams, optarg); |
336 | else | 350 | } else { |
337 | asprintf(&pgparams, "%s", optarg); | 351 | asprintf(&result.config.pgparams, "%s", optarg); |
352 | } | ||
338 | break; | 353 | break; |
339 | case 'q': | 354 | case 'q': |
340 | pgquery = optarg; | 355 | result.config.pgquery = optarg; |
341 | break; | 356 | break; |
342 | case OPTID_QUERYNAME: | 357 | case OPTID_QUERYNAME: |
343 | pgqueryname = optarg; | 358 | result.config.pgqueryname = optarg; |
344 | break; | 359 | break; |
345 | case 'v': | 360 | case 'v': |
346 | verbose++; | 361 | verbose++; |
@@ -348,9 +363,10 @@ int process_arguments(int argc, char **argv) { | |||
348 | } | 363 | } |
349 | } | 364 | } |
350 | 365 | ||
351 | set_thresholds(&qthresholds, query_warning, query_critical); | 366 | set_thresholds(&result.config.qthresholds, result.config.query_warning, |
367 | result.config.query_critical); | ||
352 | 368 | ||
353 | return OK; | 369 | return result; |
354 | } | 370 | } |
355 | 371 | ||
356 | /** | 372 | /** |
@@ -378,8 +394,9 @@ should be added.</para> | |||
378 | ******************************************************************************/ | 394 | ******************************************************************************/ |
379 | 395 | ||
380 | bool is_pg_logname(char *username) { | 396 | bool is_pg_logname(char *username) { |
381 | if (strlen(username) > NAMEDATALEN - 1) | 397 | if (strlen(username) > NAMEDATALEN - 1) { |
382 | return (false); | 398 | return (false); |
399 | } | ||
383 | return (true); | 400 | return (true); |
384 | } | 401 | } |
385 | 402 | ||
@@ -394,7 +411,7 @@ bool is_pg_logname(char *username) { | |||
394 | void print_help(void) { | 411 | void print_help(void) { |
395 | char *myport; | 412 | char *myport; |
396 | 413 | ||
397 | xasprintf(&myport, "%d", DEFAULT_PORT); | 414 | xasprintf(&myport, "%d", 5432); |
398 | 415 | ||
399 | print_revision(progname, NP_VERSION); | 416 | print_revision(progname, NP_VERSION); |
400 | 417 | ||
@@ -447,29 +464,39 @@ void print_help(void) { | |||
447 | 464 | ||
448 | printf(" %s\n", _("If a query is specified using the -q option, it will be executed after")); | 465 | printf(" %s\n", _("If a query is specified using the -q option, it will be executed after")); |
449 | printf(" %s\n", _("connecting to the server. The result from the query has to be numeric.")); | 466 | printf(" %s\n", _("connecting to the server. The result from the query has to be numeric.")); |
450 | printf(" %s\n", _("Multiple SQL commands, separated by semicolon, are allowed but the result ")); | 467 | printf(" %s\n", |
468 | _("Multiple SQL commands, separated by semicolon, are allowed but the result ")); | ||
451 | printf(" %s\n", _("of the last command is taken into account only. The value of the first")); | 469 | printf(" %s\n", _("of the last command is taken into account only. The value of the first")); |
452 | printf(" %s\n", _("column in the first row is used as the check result. If a second column is")); | 470 | printf(" %s\n", |
471 | _("column in the first row is used as the check result. If a second column is")); | ||
453 | printf(" %s\n", _("present in the result set, this is added to the plugin output with a")); | 472 | printf(" %s\n", _("present in the result set, this is added to the plugin output with a")); |
454 | printf(" %s\n", _("prefix of \"Extra Info:\". This information can be displayed in the system")); | 473 | printf(" %s\n", |
474 | _("prefix of \"Extra Info:\". This information can be displayed in the system")); | ||
455 | printf(" %s\n\n", _("executing the plugin.")); | 475 | printf(" %s\n\n", _("executing the plugin.")); |
456 | 476 | ||
457 | printf(" %s\n", _("See the chapter \"Monitoring Database Activity\" of the PostgreSQL manual")); | 477 | printf(" %s\n", _("See the chapter \"Monitoring Database Activity\" of the PostgreSQL manual")); |
458 | printf(" %s\n\n", _("for details about how to access internal statistics of the database server.")); | 478 | printf(" %s\n\n", |
479 | _("for details about how to access internal statistics of the database server.")); | ||
459 | 480 | ||
460 | printf(" %s\n", _("For a list of available connection parameters which may be used with the -o")); | 481 | printf(" %s\n", |
461 | printf(" %s\n", _("command line option, see the documentation for PQconnectdb() in the chapter")); | 482 | _("For a list of available connection parameters which may be used with the -o")); |
483 | printf(" %s\n", | ||
484 | _("command line option, see the documentation for PQconnectdb() in the chapter")); | ||
462 | printf(" %s\n", _("\"libpq - C Library\" of the PostgreSQL manual. For example, this may be")); | 485 | printf(" %s\n", _("\"libpq - C Library\" of the PostgreSQL manual. For example, this may be")); |
463 | printf(" %s\n", _("used to specify a service name in pg_service.conf to be used for additional")); | 486 | printf(" %s\n", |
487 | _("used to specify a service name in pg_service.conf to be used for additional")); | ||
464 | printf(" %s\n", _("connection parameters: -o 'service=<name>' or to specify the SSL mode:")); | 488 | printf(" %s\n", _("connection parameters: -o 'service=<name>' or to specify the SSL mode:")); |
465 | printf(" %s\n\n", _("-o 'sslmode=require'.")); | 489 | printf(" %s\n\n", _("-o 'sslmode=require'.")); |
466 | 490 | ||
467 | printf(" %s\n", _("The plugin will connect to a local postmaster if no host is specified. To")); | 491 | printf(" %s\n", _("The plugin will connect to a local postmaster if no host is specified. To")); |
468 | printf(" %s\n", _("connect to a remote host, be sure that the remote postmaster accepts TCP/IP")); | 492 | printf(" %s\n", |
493 | _("connect to a remote host, be sure that the remote postmaster accepts TCP/IP")); | ||
469 | printf(" %s\n\n", _("connections (start the postmaster with the -i option).")); | 494 | printf(" %s\n\n", _("connections (start the postmaster with the -i option).")); |
470 | 495 | ||
471 | printf(" %s\n", _("Typically, the monitoring user (unless the --logname option is used) should be")); | 496 | printf(" %s\n", |
472 | printf(" %s\n", _("able to connect to the database without a password. The plugin can also send")); | 497 | _("Typically, the monitoring user (unless the --logname option is used) should be")); |
498 | printf(" %s\n", | ||
499 | _("able to connect to the database without a password. The plugin can also send")); | ||
473 | printf(" %s\n", _("a password, but no effort is made to obscure or encrypt the password.")); | 500 | printf(" %s\n", _("a password, but no effort is made to obscure or encrypt the password.")); |
474 | 501 | ||
475 | printf(UT_SUPPORT); | 502 | printf(UT_SUPPORT); |
@@ -482,13 +509,16 @@ void print_usage(void) { | |||
482 | "[-q <query>] [-C <critical query range>] [-W <warning query range>]\n"); | 509 | "[-q <query>] [-C <critical query range>] [-W <warning query range>]\n"); |
483 | } | 510 | } |
484 | 511 | ||
485 | int do_query(PGconn *conn, char *query) { | 512 | mp_state_enum do_query(PGconn *conn, char *query, const char pgqueryname[], thresholds *qthresholds, |
486 | if (verbose) | 513 | char *query_warning, char *query_critical) { |
514 | if (verbose) { | ||
487 | printf("Executing SQL query \"%s\".\n", query); | 515 | printf("Executing SQL query \"%s\".\n", query); |
516 | } | ||
488 | PGresult *res = PQexec(conn, query); | 517 | PGresult *res = PQexec(conn, query); |
489 | 518 | ||
490 | if (PGRES_TUPLES_OK != PQresultStatus(res)) { | 519 | if (PGRES_TUPLES_OK != PQresultStatus(res)) { |
491 | printf(_("QUERY %s - %s: %s.\n"), _("CRITICAL"), _("Error with query"), PQerrorMessage(conn)); | 520 | printf(_("QUERY %s - %s: %s.\n"), _("CRITICAL"), _("Error with query"), |
521 | PQerrorMessage(conn)); | ||
492 | return STATE_CRITICAL; | 522 | return STATE_CRITICAL; |
493 | } | 523 | } |
494 | 524 | ||
@@ -510,8 +540,9 @@ int do_query(PGconn *conn, char *query) { | |||
510 | 540 | ||
511 | char *endptr = NULL; | 541 | char *endptr = NULL; |
512 | double value = strtod(val_str, &endptr); | 542 | double value = strtod(val_str, &endptr); |
513 | if (verbose) | 543 | if (verbose) { |
514 | printf("Query result: %f\n", value); | 544 | printf("Query result: %f\n", value); |
545 | } | ||
515 | 546 | ||
516 | if (endptr == val_str) { | 547 | if (endptr == val_str) { |
517 | printf("QUERY %s - %s: %s\n", _("CRITICAL"), _("Is not a numeric"), val_str); | 548 | printf("QUERY %s - %s: %s\n", _("CRITICAL"), _("Is not a numeric"), val_str); |
@@ -519,11 +550,12 @@ int do_query(PGconn *conn, char *query) { | |||
519 | } | 550 | } |
520 | 551 | ||
521 | if ((endptr != NULL) && (*endptr != '\0')) { | 552 | if ((endptr != NULL) && (*endptr != '\0')) { |
522 | if (verbose) | 553 | if (verbose) { |
523 | printf("Garbage after value: %s.\n", endptr); | 554 | printf("Garbage after value: %s.\n", endptr); |
555 | } | ||
524 | } | 556 | } |
525 | 557 | ||
526 | int my_status = get_status(value, qthresholds); | 558 | mp_state_enum my_status = get_status(value, qthresholds); |
527 | printf("QUERY %s - ", (my_status == STATE_OK) ? _("OK") | 559 | printf("QUERY %s - ", (my_status == STATE_OK) ? _("OK") |
528 | : (my_status == STATE_WARNING) ? _("WARNING") | 560 | : (my_status == STATE_WARNING) ? _("WARNING") |
529 | : (my_status == STATE_CRITICAL) ? _("CRITICAL") | 561 | : (my_status == STATE_CRITICAL) ? _("CRITICAL") |
@@ -534,7 +566,8 @@ int do_query(PGconn *conn, char *query) { | |||
534 | printf(_("'%s' returned %f"), query, value); | 566 | printf(_("'%s' returned %f"), query, value); |
535 | } | 567 | } |
536 | 568 | ||
537 | printf("|query=%f;%s;%s;;\n", value, query_warning ? query_warning : "", query_critical ? query_critical : ""); | 569 | printf("|query=%f;%s;%s;;\n", value, query_warning ? query_warning : "", |
570 | query_critical ? query_critical : ""); | ||
538 | if (PQnfields(res) > 1) { | 571 | if (PQnfields(res) > 1) { |
539 | char *extra_info = PQgetvalue(res, 0, 1); | 572 | char *extra_info = PQgetvalue(res, 0, 1); |
540 | if (extra_info != NULL) { | 573 | if (extra_info != NULL) { |