summaryrefslogtreecommitdiffstats
path: root/plugins/check_pgsql.c
diff options
context:
space:
mode:
Diffstat (limited to 'plugins/check_pgsql.c')
-rw-r--r--plugins/check_pgsql.c337
1 files changed, 235 insertions, 102 deletions
diff --git a/plugins/check_pgsql.c b/plugins/check_pgsql.c
index 84305adb..0ce75e0a 100644
--- a/plugins/check_pgsql.c
+++ b/plugins/check_pgsql.c
@@ -28,32 +28,35 @@
28 * 28 *
29 *****************************************************************************/ 29 *****************************************************************************/
30 30
31#include "output.h"
32#include "perfdata.h"
31#include "states.h" 33#include "states.h"
32const char *progname = "check_pgsql";
33const char *copyright = "1999-2024";
34const char *email = "devel@monitoring-plugins.org";
35
36#include "common.h" 34#include "common.h"
37#include "utils.h" 35#include "utils.h"
38#include "utils_cmd.h" 36#include "utils_cmd.h"
39#include "check_pgsql.d/config.h" 37#include "check_pgsql.d/config.h"
40#include "thresholds.h" 38#include "thresholds.h"
41
42#include "netutils.h" 39#include "netutils.h"
43#include <libpq-fe.h> 40#include <libpq-fe.h>
44#include <pg_config_manual.h> 41#include <pg_config_manual.h>
45 42
43const char *progname = "check_pgsql";
44const char *copyright = "1999-2024";
45const char *email = "devel@monitoring-plugins.org";
46
46#define DEFAULT_HOST "127.0.0.1" 47#define DEFAULT_HOST "127.0.0.1"
47 48
48/* return the PSQL server version as a 3-tuple */ 49/* return the PSQL server version as a 3-tuple */
49#define PSQL_SERVER_VERSION3(server_version) \ 50#define PSQL_SERVER_VERSION3(server_version) \
50 (server_version) / 10000, (server_version) / 100 - (int)((server_version) / 10000) * 100, \ 51 ((server_version) / 10000), \
51 (server_version) - (int)((server_version) / 100) * 100 52 (((server_version) / 100) - (int)(((server_version) / 10000) * 100)), \
53 (server_version) - (int)(((server_version) / 100) * 100)
52/* return true if the given host is a UNIX domain socket */ 54/* return true if the given host is a UNIX domain socket */
53#define PSQL_IS_UNIX_DOMAIN_SOCKET(host) ((NULL == (host)) || ('\0' == *(host)) || ('/' == *(host))) 55#define PSQL_IS_UNIX_DOMAIN_SOCKET(host) ((NULL == (host)) || ('\0' == *(host)) || ('/' == *(host)))
54/* return a 3-tuple identifying a host/port independent of the socket type */ 56/* return a 3-tuple identifying a host/port independent of the socket type */
55#define PSQL_SOCKET3(host, port) \ 57#define PSQL_SOCKET3(host, port) \
56 ((NULL == (host)) || ('\0' == *(host))) ? DEFAULT_PGSOCKET_DIR : host, PSQL_IS_UNIX_DOMAIN_SOCKET(host) ? "/.s.PGSQL." : ":", port 58 ((NULL == (host)) || ('\0' == *(host))) ? DEFAULT_PGSOCKET_DIR : host, \
59 PSQL_IS_UNIX_DOMAIN_SOCKET(host) ? "/.s.PGSQL." : ":", port
57 60
58typedef struct { 61typedef struct {
59 int errorcode; 62 int errorcode;
@@ -63,14 +66,25 @@ static check_pgsql_config_wrapper process_arguments(int /*argc*/, char ** /*argv
63 66
64static void print_help(void); 67static void print_help(void);
65static bool is_pg_logname(char * /*username*/); 68static bool is_pg_logname(char * /*username*/);
66static mp_state_enum do_query(PGconn * /*conn*/, char * /*query*/, const char /*pgqueryname*/[], thresholds * /*qthresholds*/, 69
67 char * /*query_warning*/, char * /*query_critical*/); 70typedef enum {
71 QUERY_OK,
72 ERROR_WITH_QUERY, // critical
73 NO_ROWS_RETURNED, // warning
74 NO_COLUMNS_RETURNED, // warning
75 NO_DATA_RETURNED, // critica/
76 RESULT_IS_NOT_NUMERIC // critical
77} do_query_errorcode;
78
79typedef struct {
80 do_query_errorcode error_code;
81 double numerical_result;
82} do_query_wrapper;
83static do_query_wrapper do_query(PGconn * /*conn*/, char * /*query*/);
68void print_usage(void); 84void print_usage(void);
69 85
70static int verbose = 0; 86static int verbose = 0;
71 87
72#define OPTID_QUERYNAME -1000
73
74/****************************************************************************** 88/******************************************************************************
75 89
76The (pseudo?)literate programming XML is contained within \@\@\- <XML> \-\@\@ 90The (pseudo?)literate programming XML is contained within \@\@\- <XML> \-\@\@
@@ -136,8 +150,8 @@ int main(int argc, char **argv) {
136 150
137 const check_pgsql_config config = tmp_config.config; 151 const check_pgsql_config config = tmp_config.config;
138 152
139 if (verbose > 2) { 153 if (config.output_format_is_set) {
140 printf("Arguments initialized\n"); 154 mp_set_format(config.output_format);
141 } 155 }
142 156
143 /* Set signal handling and alarm */ 157 /* Set signal handling and alarm */
@@ -167,7 +181,8 @@ int main(int argc, char **argv) {
167 } 181 }
168 182
169 if (verbose) { /* do not include password (see right below) in output */ 183 if (verbose) { /* do not include password (see right below) in output */
170 printf("Connecting to PostgreSQL using conninfo: %s%s\n", conninfo, config.pgpasswd ? " password = <hidden>" : ""); 184 printf("Connecting to PostgreSQL using conninfo: %s%s\n", conninfo,
185 config.pgpasswd ? " password = <hidden>" : "");
171 } 186 }
172 187
173 if (config.pgpasswd) { 188 if (config.pgpasswd) {
@@ -185,8 +200,8 @@ int main(int argc, char **argv) {
185 --end_timeval.tv_sec; 200 --end_timeval.tv_sec;
186 end_timeval.tv_usec += 1000000; 201 end_timeval.tv_usec += 1000000;
187 } 202 }
188 double elapsed_time = 203 double elapsed_time = (double)(end_timeval.tv_sec - start_timeval.tv_sec) +
189 (double)(end_timeval.tv_sec - start_timeval.tv_sec) + ((double)(end_timeval.tv_usec - start_timeval.tv_usec) / 1000000.0); 204 ((double)(end_timeval.tv_usec - start_timeval.tv_usec) / 1000000.0);
190 205
191 if (verbose) { 206 if (verbose) {
192 printf("Time elapsed: %f\n", elapsed_time); 207 printf("Time elapsed: %f\n", elapsed_time);
@@ -196,21 +211,41 @@ int main(int argc, char **argv) {
196 if (verbose) { 211 if (verbose) {
197 printf("Verifying connection\n"); 212 printf("Verifying connection\n");
198 } 213 }
214
215 mp_check overall = mp_check_init();
216
217 mp_subcheck sc_connection = mp_subcheck_init();
218
199 if (PQstatus(conn) == CONNECTION_BAD) { 219 if (PQstatus(conn) == CONNECTION_BAD) {
200 printf(_("CRITICAL - no connection to '%s' (%s).\n"), config.dbName, PQerrorMessage(conn)); 220 sc_connection = mp_set_subcheck_state(sc_connection, STATE_CRITICAL);
221 xasprintf(&sc_connection.output, "no connection to '%s' (%s)", config.dbName,
222 PQerrorMessage(conn));
201 PQfinish(conn); 223 PQfinish(conn);
202 return STATE_CRITICAL; 224 mp_add_subcheck_to_check(&overall, sc_connection);
203 } 225 mp_exit(overall);
204
205 mp_state_enum status = STATE_UNKNOWN;
206 if (elapsed_time > config.tcrit) {
207 status = STATE_CRITICAL;
208 } else if (elapsed_time > config.twarn) {
209 status = STATE_WARNING;
210 } else { 226 } else {
211 status = STATE_OK; 227 sc_connection = mp_set_subcheck_state(sc_connection, STATE_OK);
228 xasprintf(&sc_connection.output, "connected to '%s'", config.dbName);
229 mp_add_subcheck_to_check(&overall, sc_connection);
212 } 230 }
213 231
232 mp_subcheck sc_connection_time = mp_subcheck_init();
233 sc_connection_time = mp_set_subcheck_default_state(sc_connection_time, STATE_UNKNOWN);
234
235 xasprintf(&sc_connection_time.output, "connection time: %.10g", elapsed_time);
236
237 mp_perfdata pd_connection_time = perfdata_init();
238 pd_connection_time.label = "time";
239 pd_connection_time.uom = "s";
240 pd_connection_time = mp_set_pd_value(pd_connection_time, elapsed_time);
241 pd_connection_time = mp_pd_set_thresholds(pd_connection_time, config.time_thresholds);
242
243 mp_add_perfdata_to_subcheck(&sc_connection_time, pd_connection_time);
244 sc_connection_time =
245 mp_set_subcheck_state(sc_connection_time, mp_get_pd_status(pd_connection_time));
246
247 mp_add_subcheck_to_check(&overall, sc_connection_time);
248
214 if (verbose) { 249 if (verbose) {
215 char *server_host = PQhost(conn); 250 char *server_host = PQhost(conn);
216 int server_version = PQserverVersion(conn); 251 int server_version = PQserverVersion(conn);
@@ -218,27 +253,91 @@ int main(int argc, char **argv) {
218 printf("Successfully connected to database %s (user %s) " 253 printf("Successfully connected to database %s (user %s) "
219 "at server %s%s%s (server version: %d.%d.%d, " 254 "at server %s%s%s (server version: %d.%d.%d, "
220 "protocol version: %d, pid: %d)\n", 255 "protocol version: %d, pid: %d)\n",
221 PQdb(conn), PQuser(conn), PSQL_SOCKET3(server_host, PQport(conn)), PSQL_SERVER_VERSION3(server_version), 256 PQdb(conn), PQuser(conn), PSQL_SOCKET3(server_host, PQport(conn)),
222 PQprotocolVersion(conn), PQbackendPID(conn)); 257 PSQL_SERVER_VERSION3(server_version), PQprotocolVersion(conn), PQbackendPID(conn));
223 } 258 }
224 259
225 printf(_(" %s - database %s (%f sec.)|%s\n"), state_text(status), config.dbName, elapsed_time,
226 fperfdata("time", elapsed_time, "s", (config.twarn > 0.0), config.twarn, (config.tcrit > 0.0), config.tcrit, true, 0, false, 0));
227
228 mp_state_enum query_status = STATE_UNKNOWN;
229 if (config.pgquery) { 260 if (config.pgquery) {
230 query_status = do_query(conn, config.pgquery, config.pgqueryname, config.qthresholds, config.query_warning, config.query_critical); 261 mp_subcheck sc_query = mp_subcheck_init();
262 sc_query = mp_set_subcheck_default_state(sc_query, STATE_UNKNOWN);
263 if (config.pgqueryname) {
264 xasprintf(&sc_query.output, "query '%s'", config.pgqueryname);
265 } else {
266 xasprintf(&sc_query.output, "query '%s'", config.pgquery);
267 }
268
269 do_query_wrapper query_result = do_query(conn, config.pgquery);
270
271 switch (query_result.error_code) {
272 case QUERY_OK: {
273 // Query was successful and there is a numerical result
274 sc_query = mp_set_subcheck_state(sc_query, STATE_OK);
275 xasprintf(&sc_query.output, "%s succeeded", sc_query.output);
276
277 mp_perfdata pd_query = perfdata_init();
278 pd_query = mp_set_pd_value(pd_query, query_result.numerical_result);
279 pd_query = mp_pd_set_thresholds(pd_query, config.qthresholds);
280 pd_query.label = "query";
281
282 mp_subcheck sc_query_compare = mp_subcheck_init();
283 mp_state_enum query_compare_state = mp_get_pd_status(pd_query);
284
285 sc_query_compare = mp_set_subcheck_state(sc_query_compare, query_compare_state);
286 mp_add_perfdata_to_subcheck(&sc_query_compare, pd_query);
287
288 if (query_compare_state == STATE_OK) {
289 xasprintf(&sc_query_compare.output, "query result '%f' is within thresholds",
290 query_result.numerical_result);
291 } else {
292 xasprintf(&sc_query_compare.output, "query result '%f' is violating thresholds",
293 query_result.numerical_result);
294 }
295 mp_add_subcheck_to_check(&overall, sc_query_compare);
296
297 } break;
298 case ERROR_WITH_QUERY:
299 xasprintf(&sc_query.output, "%s - Error with query: %s", sc_query.output,
300 PQerrorMessage(conn));
301 sc_query = mp_set_subcheck_state(sc_query, STATE_CRITICAL);
302 break;
303 case NO_ROWS_RETURNED:
304 xasprintf(&sc_query.output, "%s - no rows were returned by the query", sc_query.output);
305 sc_query = mp_set_subcheck_state(sc_query, STATE_WARNING);
306 break;
307 case NO_COLUMNS_RETURNED:
308 xasprintf(&sc_query.output, "%s - no columns were returned by the query",
309 sc_query.output);
310 sc_query = mp_set_subcheck_state(sc_query, STATE_WARNING);
311 break;
312 case NO_DATA_RETURNED:
313 xasprintf(&sc_query.output, "%s - no data was returned by the query", sc_query.output);
314 sc_query = mp_set_subcheck_state(sc_query, STATE_WARNING);
315 break;
316 case RESULT_IS_NOT_NUMERIC:
317 xasprintf(&sc_query.output, "%s - result of the query is not numeric", sc_query.output);
318 sc_query = mp_set_subcheck_state(sc_query, STATE_CRITICAL);
319 break;
320 };
321
322 mp_add_subcheck_to_check(&overall, sc_query);
231 } 323 }
232 324
233 if (verbose) { 325 if (verbose) {
234 printf("Closing connection\n"); 326 printf("Closing connection\n");
235 } 327 }
236 PQfinish(conn); 328 PQfinish(conn);
237 return (config.pgquery && query_status > status) ? query_status : status; 329
330 mp_exit(overall);
238} 331}
239 332
240/* process command-line arguments */ 333/* process command-line arguments */
241check_pgsql_config_wrapper process_arguments(int argc, char **argv) { 334static check_pgsql_config_wrapper process_arguments(int argc, char **argv) {
335
336 enum {
337 OPTID_QUERYNAME = CHAR_MAX + 1,
338 output_format_index,
339 };
340
242 static struct option longopts[] = {{"help", no_argument, 0, 'h'}, 341 static struct option longopts[] = {{"help", no_argument, 0, 'h'},
243 {"version", no_argument, 0, 'V'}, 342 {"version", no_argument, 0, 'V'},
244 {"timeout", required_argument, 0, 't'}, 343 {"timeout", required_argument, 0, 't'},
@@ -256,6 +355,7 @@ check_pgsql_config_wrapper process_arguments(int argc, char **argv) {
256 {"query_critical", required_argument, 0, 'C'}, 355 {"query_critical", required_argument, 0, 'C'},
257 {"query_warning", required_argument, 0, 'W'}, 356 {"query_warning", required_argument, 0, 'W'},
258 {"verbose", no_argument, 0, 'v'}, 357 {"verbose", no_argument, 0, 'v'},
358 {"output-format", required_argument, 0, output_format_index},
259 {0, 0, 0, 0}}; 359 {0, 0, 0, 0}};
260 360
261 check_pgsql_config_wrapper result = { 361 check_pgsql_config_wrapper result = {
@@ -265,13 +365,25 @@ check_pgsql_config_wrapper process_arguments(int argc, char **argv) {
265 365
266 while (true) { 366 while (true) {
267 int option = 0; 367 int option = 0;
268 int option_char = getopt_long(argc, argv, "hVt:c:w:H:P:d:l:p:a:o:q:C:W:v", longopts, &option); 368 int option_char =
369 getopt_long(argc, argv, "hVt:c:w:H:P:d:l:p:a:o:q:C:W:v", longopts, &option);
269 370
270 if (option_char == EOF) { 371 if (option_char == EOF) {
271 break; 372 break;
272 } 373 }
273 374
274 switch (option_char) { 375 switch (option_char) {
376 case output_format_index: {
377 parsed_output_format parser = mp_parse_output_format(optarg);
378 if (!parser.parsing_success) {
379 printf("Invalid output format: %s\n", optarg);
380 exit(STATE_UNKNOWN);
381 }
382
383 result.config.output_format_is_set = true;
384 result.config.output_format = parser.output_format;
385 break;
386 }
275 case '?': /* usage */ 387 case '?': /* usage */
276 usage5(); 388 usage5();
277 case 'h': /* help */ 389 case 'h': /* help */
@@ -287,26 +399,40 @@ check_pgsql_config_wrapper process_arguments(int argc, char **argv) {
287 timeout_interval = atoi(optarg); 399 timeout_interval = atoi(optarg);
288 } 400 }
289 break; 401 break;
290 case 'c': /* critical time threshold */ 402 case 'c': /* critical time threshold */ {
291 if (!is_nonnegative(optarg)) { 403 mp_range_parsed tmp = mp_parse_range_string(optarg);
292 usage2(_("Critical threshold must be a positive integer"), optarg); 404 if (tmp.error != MP_PARSING_SUCCES) {
293 } else { 405 die(STATE_UNKNOWN, "failed to parse critical time threshold");
294 result.config.tcrit = strtod(optarg, NULL);
295 } 406 }
296 break; 407 result.config.time_thresholds =
297 case 'w': /* warning time threshold */ 408 mp_thresholds_set_crit(result.config.time_thresholds, tmp.range);
298 if (!is_nonnegative(optarg)) { 409 } break;
299 usage2(_("Warning threshold must be a positive integer"), optarg); 410 case 'w': /* warning time threshold */ {
300 } else { 411 mp_range_parsed tmp = mp_parse_range_string(optarg);
301 result.config.twarn = strtod(optarg, NULL); 412 if (tmp.error != MP_PARSING_SUCCES) {
413 die(STATE_UNKNOWN, "failed to parse warning time threshold");
302 } 414 }
303 break; 415 result.config.time_thresholds =
304 case 'C': /* critical query threshold */ 416 mp_thresholds_set_warn(result.config.time_thresholds, tmp.range);
305 result.config.query_critical = optarg; 417 } break;
306 break; 418 case 'C': /* critical query threshold */ {
307 case 'W': /* warning query threshold */ 419 mp_range_parsed tmp = mp_parse_range_string(optarg);
308 result.config.query_warning = optarg; 420 if (tmp.error != MP_PARSING_SUCCES) {
309 break; 421 die(STATE_UNKNOWN, "failed to parse critical query threshold");
422 }
423
424 result.config.qthresholds =
425 mp_thresholds_set_crit(result.config.qthresholds, tmp.range);
426
427 } break;
428 case 'W': /* warning query threshold */ {
429 mp_range_parsed tmp = mp_parse_range_string(optarg);
430 if (tmp.error != MP_PARSING_SUCCES) {
431 die(STATE_UNKNOWN, "failed to parse warning query threshold");
432 }
433 result.config.qthresholds =
434 mp_thresholds_set_warn(result.config.qthresholds, tmp.range);
435 } break;
310 case 'H': /* host */ 436 case 'H': /* host */
311 if ((*optarg != '/') && (!is_host(optarg))) { 437 if ((*optarg != '/') && (!is_host(optarg))) {
312 usage2(_("Invalid hostname/address"), optarg); 438 usage2(_("Invalid hostname/address"), optarg);
@@ -357,8 +483,6 @@ check_pgsql_config_wrapper process_arguments(int argc, char **argv) {
357 } 483 }
358 } 484 }
359 485
360 set_thresholds(&result.config.qthresholds, result.config.query_warning, result.config.query_critical);
361
362 return result; 486 return result;
363} 487}
364 488
@@ -386,7 +510,7 @@ should be added.</para>
386-@@ 510-@@
387******************************************************************************/ 511******************************************************************************/
388 512
389bool is_pg_logname(char *username) { 513static bool is_pg_logname(char *username) {
390 if (strlen(username) > NAMEDATALEN - 1) { 514 if (strlen(username) > NAMEDATALEN - 1) {
391 return (false); 515 return (false);
392 } 516 }
@@ -440,12 +564,13 @@ void print_help(void) {
440 printf(" %s\n", "--queryname=STRING"); 564 printf(" %s\n", "--queryname=STRING");
441 printf(" %s\n", _("A name for the query, this string is used instead of the query")); 565 printf(" %s\n", _("A name for the query, this string is used instead of the query"));
442 printf(" %s\n", _("in the long output of the plugin")); 566 printf(" %s\n", _("in the long output of the plugin"));
443 printf(" %s\n", "-W, --query-warning=RANGE"); 567 printf(" %s\n", "-W, --query_warning=RANGE");
444 printf(" %s\n", _("SQL query value to result in warning status (double)")); 568 printf(" %s\n", _("SQL query value to result in warning status (double)"));
445 printf(" %s\n", "-C, --query-critical=RANGE"); 569 printf(" %s\n", "-C, --query_critical=RANGE");
446 printf(" %s\n", _("SQL query value to result in critical status (double)")); 570 printf(" %s\n", _("SQL query value to result in critical status (double)"));
447 571
448 printf(UT_VERBOSE); 572 printf(UT_VERBOSE);
573 printf(UT_OUTPUT_FORMAT);
449 574
450 printf("\n"); 575 printf("\n");
451 printf(" %s\n", _("All parameters are optional.")); 576 printf(" %s\n", _("All parameters are optional."));
@@ -457,29 +582,39 @@ void print_help(void) {
457 582
458 printf(" %s\n", _("If a query is specified using the -q option, it will be executed after")); 583 printf(" %s\n", _("If a query is specified using the -q option, it will be executed after"));
459 printf(" %s\n", _("connecting to the server. The result from the query has to be numeric.")); 584 printf(" %s\n", _("connecting to the server. The result from the query has to be numeric."));
460 printf(" %s\n", _("Multiple SQL commands, separated by semicolon, are allowed but the result ")); 585 printf(" %s\n",
586 _("Multiple SQL commands, separated by semicolon, are allowed but the result "));
461 printf(" %s\n", _("of the last command is taken into account only. The value of the first")); 587 printf(" %s\n", _("of the last command is taken into account only. The value of the first"));
462 printf(" %s\n", _("column in the first row is used as the check result. If a second column is")); 588 printf(" %s\n",
589 _("column in the first row is used as the check result. If a second column is"));
463 printf(" %s\n", _("present in the result set, this is added to the plugin output with a")); 590 printf(" %s\n", _("present in the result set, this is added to the plugin output with a"));
464 printf(" %s\n", _("prefix of \"Extra Info:\". This information can be displayed in the system")); 591 printf(" %s\n",
592 _("prefix of \"Extra Info:\". This information can be displayed in the system"));
465 printf(" %s\n\n", _("executing the plugin.")); 593 printf(" %s\n\n", _("executing the plugin."));
466 594
467 printf(" %s\n", _("See the chapter \"Monitoring Database Activity\" of the PostgreSQL manual")); 595 printf(" %s\n", _("See the chapter \"Monitoring Database Activity\" of the PostgreSQL manual"));
468 printf(" %s\n\n", _("for details about how to access internal statistics of the database server.")); 596 printf(" %s\n\n",
597 _("for details about how to access internal statistics of the database server."));
469 598
470 printf(" %s\n", _("For a list of available connection parameters which may be used with the -o")); 599 printf(" %s\n",
471 printf(" %s\n", _("command line option, see the documentation for PQconnectdb() in the chapter")); 600 _("For a list of available connection parameters which may be used with the -o"));
601 printf(" %s\n",
602 _("command line option, see the documentation for PQconnectdb() in the chapter"));
472 printf(" %s\n", _("\"libpq - C Library\" of the PostgreSQL manual. For example, this may be")); 603 printf(" %s\n", _("\"libpq - C Library\" of the PostgreSQL manual. For example, this may be"));
473 printf(" %s\n", _("used to specify a service name in pg_service.conf to be used for additional")); 604 printf(" %s\n",
605 _("used to specify a service name in pg_service.conf to be used for additional"));
474 printf(" %s\n", _("connection parameters: -o 'service=<name>' or to specify the SSL mode:")); 606 printf(" %s\n", _("connection parameters: -o 'service=<name>' or to specify the SSL mode:"));
475 printf(" %s\n\n", _("-o 'sslmode=require'.")); 607 printf(" %s\n\n", _("-o 'sslmode=require'."));
476 608
477 printf(" %s\n", _("The plugin will connect to a local postmaster if no host is specified. To")); 609 printf(" %s\n", _("The plugin will connect to a local postmaster if no host is specified. To"));
478 printf(" %s\n", _("connect to a remote host, be sure that the remote postmaster accepts TCP/IP")); 610 printf(" %s\n",
611 _("connect to a remote host, be sure that the remote postmaster accepts TCP/IP"));
479 printf(" %s\n\n", _("connections (start the postmaster with the -i option).")); 612 printf(" %s\n\n", _("connections (start the postmaster with the -i option)."));
480 613
481 printf(" %s\n", _("Typically, the monitoring user (unless the --logname option is used) should be")); 614 printf(" %s\n",
482 printf(" %s\n", _("able to connect to the database without a password. The plugin can also send")); 615 _("Typically, the monitoring user (unless the --logname option is used) should be"));
616 printf(" %s\n",
617 _("able to connect to the database without a password. The plugin can also send"));
483 printf(" %s\n", _("a password, but no effort is made to obscure or encrypt the password.")); 618 printf(" %s\n", _("a password, but no effort is made to obscure or encrypt the password."));
484 619
485 printf(UT_SUPPORT); 620 printf(UT_SUPPORT);
@@ -492,32 +627,44 @@ void print_usage(void) {
492 "[-q <query>] [-C <critical query range>] [-W <warning query range>]\n"); 627 "[-q <query>] [-C <critical query range>] [-W <warning query range>]\n");
493} 628}
494 629
495mp_state_enum do_query(PGconn *conn, char *query, const char pgqueryname[], thresholds *qthresholds, char *query_warning, 630static do_query_wrapper do_query(PGconn *conn, char *query) {
496 char *query_critical) {
497 if (verbose) { 631 if (verbose) {
498 printf("Executing SQL query \"%s\".\n", query); 632 printf("Executing SQL query \"%s\".\n", query);
499 } 633 }
500 PGresult *res = PQexec(conn, query); 634 PGresult *res = PQexec(conn, query);
501 635
636 do_query_wrapper result = {
637 .error_code = QUERY_OK,
638 };
639
502 if (PGRES_TUPLES_OK != PQresultStatus(res)) { 640 if (PGRES_TUPLES_OK != PQresultStatus(res)) {
503 printf(_("QUERY %s - %s: %s.\n"), _("CRITICAL"), _("Error with query"), PQerrorMessage(conn)); 641 // TODO
504 return STATE_CRITICAL; 642 // printf(_("QUERY %s - %s: %s.\n"), _("CRITICAL"), _("Error with query"),
643 // PQerrorMessage(conn));
644 result.error_code = ERROR_WITH_QUERY;
645 return result;
505 } 646 }
506 647
507 if (PQntuples(res) < 1) { 648 if (PQntuples(res) < 1) {
508 printf("QUERY %s - %s.\n", _("WARNING"), _("No rows returned")); 649 // TODO
509 return STATE_WARNING; 650 // printf("QUERY %s - %s.\n", _("WARNING"), _("No rows returned"));
651 result.error_code = NO_ROWS_RETURNED;
652 return result;
510 } 653 }
511 654
512 if (PQnfields(res) < 1) { 655 if (PQnfields(res) < 1) {
513 printf("QUERY %s - %s.\n", _("WARNING"), _("No columns returned")); 656 // TODO
514 return STATE_WARNING; 657 // printf("QUERY %s - %s.\n", _("WARNING"), _("No columns returned"));
658 result.error_code = NO_COLUMNS_RETURNED;
659 return result;
515 } 660 }
516 661
517 char *val_str = PQgetvalue(res, 0, 0); 662 char *val_str = PQgetvalue(res, 0, 0);
518 if (!val_str) { 663 if (!val_str) {
519 printf("QUERY %s - %s.\n", _("CRITICAL"), _("No data returned")); 664 // TODO
520 return STATE_CRITICAL; 665 // printf("QUERY %s - %s.\n", _("CRITICAL"), _("No data returned"));
666 result.error_code = NO_DATA_RETURNED;
667 return result;
521 } 668 }
522 669
523 char *endptr = NULL; 670 char *endptr = NULL;
@@ -527,8 +674,10 @@ mp_state_enum do_query(PGconn *conn, char *query, const char pgqueryname[], thre
527 } 674 }
528 675
529 if (endptr == val_str) { 676 if (endptr == val_str) {
530 printf("QUERY %s - %s: %s\n", _("CRITICAL"), _("Is not a numeric"), val_str); 677 // TODO
531 return STATE_CRITICAL; 678 // printf("QUERY %s - %s: %s\n", _("CRITICAL"), _("Is not a numeric"), val_str);
679 result.error_code = RESULT_IS_NOT_NUMERIC;
680 return result;
532 } 681 }
533 682
534 if ((endptr != NULL) && (*endptr != '\0')) { 683 if ((endptr != NULL) && (*endptr != '\0')) {
@@ -537,23 +686,7 @@ mp_state_enum do_query(PGconn *conn, char *query, const char pgqueryname[], thre
537 } 686 }
538 } 687 }
539 688
540 mp_state_enum my_status = get_status(value, qthresholds); 689 result.numerical_result = value;
541 printf("QUERY %s - ", (my_status == STATE_OK) ? _("OK")
542 : (my_status == STATE_WARNING) ? _("WARNING")
543 : (my_status == STATE_CRITICAL) ? _("CRITICAL")
544 : _("UNKNOWN"));
545 if (pgqueryname) {
546 printf(_("%s returned %f"), pgqueryname, value);
547 } else {
548 printf(_("'%s' returned %f"), query, value);
549 }
550 690
551 printf("|query=%f;%s;%s;;\n", value, query_warning ? query_warning : "", query_critical ? query_critical : ""); 691 return result;
552 if (PQnfields(res) > 1) {
553 char *extra_info = PQgetvalue(res, 0, 1);
554 if (extra_info != NULL) {
555 printf("Extra Info: %s\n", extra_info);
556 }
557 }
558 return my_status;
559} 692}