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.c143
1 files changed, 66 insertions, 77 deletions
diff --git a/plugins/check_pgsql.c b/plugins/check_pgsql.c
index 0c0ef415..84305adb 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"
31const char *progname = "check_pgsql"; 32const char *progname = "check_pgsql";
32const char *copyright = "1999-2024"; 33const char *copyright = "1999-2024";
33const char *email = "devel@monitoring-plugins.org"; 34const char *email = "devel@monitoring-plugins.org";
@@ -35,12 +36,13 @@ 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 */
@@ -53,33 +55,18 @@ const char *email = "devel@monitoring-plugins.org";
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, PSQL_IS_UNIX_DOMAIN_SOCKET(host) ? "/.s.PGSQL." : ":", port
55 57
56enum { 58typedef struct {
57 DEFAULT_PORT = 5432, 59 int errorcode;
58 DEFAULT_WARN = 2, 60 check_pgsql_config config;
59 DEFAULT_CRIT = 8 61} check_pgsql_config_wrapper;
60}; 62static check_pgsql_config_wrapper process_arguments(int /*argc*/, char ** /*argv*/);
61 63
62static int process_arguments(int /*argc*/, char ** /*argv*/);
63static void print_help(void); 64static void print_help(void);
64static bool is_pg_logname(char * /*username*/); 65static bool is_pg_logname(char * /*username*/);
65static int do_query(PGconn * /*conn*/, char * /*query*/); 66static mp_state_enum do_query(PGconn * /*conn*/, char * /*query*/, const char /*pgqueryname*/[], thresholds * /*qthresholds*/,
67 char * /*query_warning*/, char * /*query_critical*/);
66void print_usage(void); 68void print_usage(void);
67 69
68static char *pghost = NULL; /* host name of the backend server */
69static char *pgport = NULL; /* port of the backend server */
70static char *pgoptions = NULL;
71static char *pgtty = NULL;
72static char dbName[NAMEDATALEN] = DEFAULT_DB;
73static char *pguser = NULL;
74static char *pgpasswd = NULL;
75static char *pgparams = NULL;
76static double twarn = (double)DEFAULT_WARN;
77static double tcrit = (double)DEFAULT_CRIT;
78static char *pgquery = NULL;
79static char *pgqueryname = NULL;
80static char *query_warning = NULL;
81static char *query_critical = NULL;
82static thresholds *qthresholds = NULL;
83static int verbose = 0; 70static int verbose = 0;
84 71
85#define OPTID_QUERYNAME -1000 72#define OPTID_QUERYNAME -1000
@@ -139,20 +126,16 @@ int main(int argc, char **argv) {
139 bindtextdomain(PACKAGE, LOCALEDIR); 126 bindtextdomain(PACKAGE, LOCALEDIR);
140 textdomain(PACKAGE); 127 textdomain(PACKAGE);
141 128
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 */ 129 /* Parse extra opts if any */
151 argv = np_extra_opts(&argc, argv, progname); 130 argv = np_extra_opts(&argc, argv, progname);
152 131
153 if (process_arguments(argc, argv) == ERROR) { 132 check_pgsql_config_wrapper tmp_config = process_arguments(argc, argv);
133 if (tmp_config.errorcode == ERROR) {
154 usage4(_("Could not parse arguments")); 134 usage4(_("Could not parse arguments"));
155 } 135 }
136
137 const check_pgsql_config config = tmp_config.config;
138
156 if (verbose > 2) { 139 if (verbose > 2) {
157 printf("Arguments initialized\n"); 140 printf("Arguments initialized\n");
158 } 141 }
@@ -164,31 +147,31 @@ int main(int argc, char **argv) {
164 alarm(timeout_interval); 147 alarm(timeout_interval);
165 148
166 char *conninfo = NULL; 149 char *conninfo = NULL;
167 if (pgparams) { 150 if (config.pgparams) {
168 asprintf(&conninfo, "%s ", pgparams); 151 asprintf(&conninfo, "%s ", config.pgparams);
169 } 152 }
170 153
171 asprintf(&conninfo, "%sdbname = '%s'", conninfo ? conninfo : "", dbName); 154 asprintf(&conninfo, "%sdbname = '%s'", conninfo ? conninfo : "", config.dbName);
172 if (pghost) { 155 if (config.pghost) {
173 asprintf(&conninfo, "%s host = '%s'", conninfo, pghost); 156 asprintf(&conninfo, "%s host = '%s'", conninfo, config.pghost);
174 } 157 }
175 if (pgport) { 158 if (config.pgport) {
176 asprintf(&conninfo, "%s port = '%s'", conninfo, pgport); 159 asprintf(&conninfo, "%s port = '%s'", conninfo, config.pgport);
177 } 160 }
178 if (pgoptions) { 161 if (config.pgoptions) {
179 asprintf(&conninfo, "%s options = '%s'", conninfo, pgoptions); 162 asprintf(&conninfo, "%s options = '%s'", conninfo, config.pgoptions);
180 } 163 }
181 /* if (pgtty) -- ignored by PQconnectdb */ 164 /* if (pgtty) -- ignored by PQconnectdb */
182 if (pguser) { 165 if (config.pguser) {
183 asprintf(&conninfo, "%s user = '%s'", conninfo, pguser); 166 asprintf(&conninfo, "%s user = '%s'", conninfo, config.pguser);
184 } 167 }
185 168
186 if (verbose) { /* do not include password (see right below) in output */ 169 if (verbose) { /* do not include password (see right below) in output */
187 printf("Connecting to PostgreSQL using conninfo: %s%s\n", conninfo, pgpasswd ? " password = <hidden>" : ""); 170 printf("Connecting to PostgreSQL using conninfo: %s%s\n", conninfo, config.pgpasswd ? " password = <hidden>" : "");
188 } 171 }
189 172
190 if (pgpasswd) { 173 if (config.pgpasswd) {
191 asprintf(&conninfo, "%s password = '%s'", conninfo, pgpasswd); 174 asprintf(&conninfo, "%s password = '%s'", conninfo, config.pgpasswd);
192 } 175 }
193 176
194 /* make a connection to the database */ 177 /* make a connection to the database */
@@ -203,7 +186,7 @@ int main(int argc, char **argv) {
203 end_timeval.tv_usec += 1000000; 186 end_timeval.tv_usec += 1000000;
204 } 187 }
205 double elapsed_time = 188 double elapsed_time =
206 (double)(end_timeval.tv_sec - start_timeval.tv_sec) + (double)(end_timeval.tv_usec - start_timeval.tv_usec) / 1000000.0; 189 (double)(end_timeval.tv_sec - start_timeval.tv_sec) + ((double)(end_timeval.tv_usec - start_timeval.tv_usec) / 1000000.0);
207 190
208 if (verbose) { 191 if (verbose) {
209 printf("Time elapsed: %f\n", elapsed_time); 192 printf("Time elapsed: %f\n", elapsed_time);
@@ -214,15 +197,15 @@ int main(int argc, char **argv) {
214 printf("Verifying connection\n"); 197 printf("Verifying connection\n");
215 } 198 }
216 if (PQstatus(conn) == CONNECTION_BAD) { 199 if (PQstatus(conn) == CONNECTION_BAD) {
217 printf(_("CRITICAL - no connection to '%s' (%s).\n"), dbName, PQerrorMessage(conn)); 200 printf(_("CRITICAL - no connection to '%s' (%s).\n"), config.dbName, PQerrorMessage(conn));
218 PQfinish(conn); 201 PQfinish(conn);
219 return STATE_CRITICAL; 202 return STATE_CRITICAL;
220 } 203 }
221 204
222 int status = STATE_UNKNOWN; 205 mp_state_enum status = STATE_UNKNOWN;
223 if (elapsed_time > tcrit) { 206 if (elapsed_time > config.tcrit) {
224 status = STATE_CRITICAL; 207 status = STATE_CRITICAL;
225 } else if (elapsed_time > twarn) { 208 } else if (elapsed_time > config.twarn) {
226 status = STATE_WARNING; 209 status = STATE_WARNING;
227 } else { 210 } else {
228 status = STATE_OK; 211 status = STATE_OK;
@@ -239,23 +222,23 @@ int main(int argc, char **argv) {
239 PQprotocolVersion(conn), PQbackendPID(conn)); 222 PQprotocolVersion(conn), PQbackendPID(conn));
240 } 223 }
241 224
242 printf(_(" %s - database %s (%f sec.)|%s\n"), state_text(status), dbName, elapsed_time, 225 printf(_(" %s - database %s (%f sec.)|%s\n"), state_text(status), config.dbName, elapsed_time,
243 fperfdata("time", elapsed_time, "s", !!(twarn > 0.0), twarn, !!(tcrit > 0.0), tcrit, true, 0, false, 0)); 226 fperfdata("time", elapsed_time, "s", (config.twarn > 0.0), config.twarn, (config.tcrit > 0.0), config.tcrit, true, 0, false, 0));
244 227
245 int query_status = STATE_UNKNOWN; 228 mp_state_enum query_status = STATE_UNKNOWN;
246 if (pgquery) { 229 if (config.pgquery) {
247 query_status = do_query(conn, pgquery); 230 query_status = do_query(conn, config.pgquery, config.pgqueryname, config.qthresholds, config.query_warning, config.query_critical);
248 } 231 }
249 232
250 if (verbose) { 233 if (verbose) {
251 printf("Closing connection\n"); 234 printf("Closing connection\n");
252 } 235 }
253 PQfinish(conn); 236 PQfinish(conn);
254 return (pgquery && query_status > status) ? query_status : status; 237 return (config.pgquery && query_status > status) ? query_status : status;
255} 238}
256 239
257/* process command-line arguments */ 240/* process command-line arguments */
258int process_arguments(int argc, char **argv) { 241check_pgsql_config_wrapper process_arguments(int argc, char **argv) {
259 static struct option longopts[] = {{"help", no_argument, 0, 'h'}, 242 static struct option longopts[] = {{"help", no_argument, 0, 'h'},
260 {"version", no_argument, 0, 'V'}, 243 {"version", no_argument, 0, 'V'},
261 {"timeout", required_argument, 0, 't'}, 244 {"timeout", required_argument, 0, 't'},
@@ -275,6 +258,11 @@ int process_arguments(int argc, char **argv) {
275 {"verbose", no_argument, 0, 'v'}, 258 {"verbose", no_argument, 0, 'v'},
276 {0, 0, 0, 0}}; 259 {0, 0, 0, 0}};
277 260
261 check_pgsql_config_wrapper result = {
262 .errorcode = OK,
263 .config = check_pgsql_config_init(),
264 };
265
278 while (true) { 266 while (true) {
279 int option = 0; 267 int option = 0;
280 int option_char = getopt_long(argc, argv, "hVt:c:w:H:P:d:l:p:a:o:q:C:W:v", longopts, &option); 268 int option_char = getopt_long(argc, argv, "hVt:c:w:H:P:d:l:p:a:o:q:C:W:v", longopts, &option);
@@ -303,65 +291,65 @@ int process_arguments(int argc, char **argv) {
303 if (!is_nonnegative(optarg)) { 291 if (!is_nonnegative(optarg)) {
304 usage2(_("Critical threshold must be a positive integer"), optarg); 292 usage2(_("Critical threshold must be a positive integer"), optarg);
305 } else { 293 } else {
306 tcrit = strtod(optarg, NULL); 294 result.config.tcrit = strtod(optarg, NULL);
307 } 295 }
308 break; 296 break;
309 case 'w': /* warning time threshold */ 297 case 'w': /* warning time threshold */
310 if (!is_nonnegative(optarg)) { 298 if (!is_nonnegative(optarg)) {
311 usage2(_("Warning threshold must be a positive integer"), optarg); 299 usage2(_("Warning threshold must be a positive integer"), optarg);
312 } else { 300 } else {
313 twarn = strtod(optarg, NULL); 301 result.config.twarn = strtod(optarg, NULL);
314 } 302 }
315 break; 303 break;
316 case 'C': /* critical query threshold */ 304 case 'C': /* critical query threshold */
317 query_critical = optarg; 305 result.config.query_critical = optarg;
318 break; 306 break;
319 case 'W': /* warning query threshold */ 307 case 'W': /* warning query threshold */
320 query_warning = optarg; 308 result.config.query_warning = optarg;
321 break; 309 break;
322 case 'H': /* host */ 310 case 'H': /* host */
323 if ((*optarg != '/') && (!is_host(optarg))) { 311 if ((*optarg != '/') && (!is_host(optarg))) {
324 usage2(_("Invalid hostname/address"), optarg); 312 usage2(_("Invalid hostname/address"), optarg);
325 } else { 313 } else {
326 pghost = optarg; 314 result.config.pghost = optarg;
327 } 315 }
328 break; 316 break;
329 case 'P': /* port */ 317 case 'P': /* port */
330 if (!is_integer(optarg)) { 318 if (!is_integer(optarg)) {
331 usage2(_("Port must be a positive integer"), optarg); 319 usage2(_("Port must be a positive integer"), optarg);
332 } else { 320 } else {
333 pgport = optarg; 321 result.config.pgport = optarg;
334 } 322 }
335 break; 323 break;
336 case 'd': /* database name */ 324 case 'd': /* database name */
337 if (strlen(optarg) >= NAMEDATALEN) { 325 if (strlen(optarg) >= NAMEDATALEN) {
338 usage2(_("Database name exceeds the maximum length"), optarg); 326 usage2(_("Database name exceeds the maximum length"), optarg);
339 } 327 }
340 snprintf(dbName, NAMEDATALEN, "%s", optarg); 328 snprintf(result.config.dbName, NAMEDATALEN, "%s", optarg);
341 break; 329 break;
342 case 'l': /* login name */ 330 case 'l': /* login name */
343 if (!is_pg_logname(optarg)) { 331 if (!is_pg_logname(optarg)) {
344 usage2(_("User name is not valid"), optarg); 332 usage2(_("User name is not valid"), optarg);
345 } else { 333 } else {
346 pguser = optarg; 334 result.config.pguser = optarg;
347 } 335 }
348 break; 336 break;
349 case 'p': /* authentication password */ 337 case 'p': /* authentication password */
350 case 'a': 338 case 'a':
351 pgpasswd = optarg; 339 result.config.pgpasswd = optarg;
352 break; 340 break;
353 case 'o': 341 case 'o':
354 if (pgparams) { 342 if (result.config.pgparams) {
355 asprintf(&pgparams, "%s %s", pgparams, optarg); 343 asprintf(&result.config.pgparams, "%s %s", result.config.pgparams, optarg);
356 } else { 344 } else {
357 asprintf(&pgparams, "%s", optarg); 345 asprintf(&result.config.pgparams, "%s", optarg);
358 } 346 }
359 break; 347 break;
360 case 'q': 348 case 'q':
361 pgquery = optarg; 349 result.config.pgquery = optarg;
362 break; 350 break;
363 case OPTID_QUERYNAME: 351 case OPTID_QUERYNAME:
364 pgqueryname = optarg; 352 result.config.pgqueryname = optarg;
365 break; 353 break;
366 case 'v': 354 case 'v':
367 verbose++; 355 verbose++;
@@ -369,9 +357,9 @@ int process_arguments(int argc, char **argv) {
369 } 357 }
370 } 358 }
371 359
372 set_thresholds(&qthresholds, query_warning, query_critical); 360 set_thresholds(&result.config.qthresholds, result.config.query_warning, result.config.query_critical);
373 361
374 return OK; 362 return result;
375} 363}
376 364
377/** 365/**
@@ -416,7 +404,7 @@ bool is_pg_logname(char *username) {
416void print_help(void) { 404void print_help(void) {
417 char *myport; 405 char *myport;
418 406
419 xasprintf(&myport, "%d", DEFAULT_PORT); 407 xasprintf(&myport, "%d", 5432);
420 408
421 print_revision(progname, NP_VERSION); 409 print_revision(progname, NP_VERSION);
422 410
@@ -504,7 +492,8 @@ void print_usage(void) {
504 "[-q <query>] [-C <critical query range>] [-W <warning query range>]\n"); 492 "[-q <query>] [-C <critical query range>] [-W <warning query range>]\n");
505} 493}
506 494
507int do_query(PGconn *conn, char *query) { 495mp_state_enum do_query(PGconn *conn, char *query, const char pgqueryname[], thresholds *qthresholds, char *query_warning,
496 char *query_critical) {
508 if (verbose) { 497 if (verbose) {
509 printf("Executing SQL query \"%s\".\n", query); 498 printf("Executing SQL query \"%s\".\n", query);
510 } 499 }
@@ -548,7 +537,7 @@ int do_query(PGconn *conn, char *query) {
548 } 537 }
549 } 538 }
550 539
551 int my_status = get_status(value, qthresholds); 540 mp_state_enum my_status = get_status(value, qthresholds);
552 printf("QUERY %s - ", (my_status == STATE_OK) ? _("OK") 541 printf("QUERY %s - ", (my_status == STATE_OK) ? _("OK")
553 : (my_status == STATE_WARNING) ? _("WARNING") 542 : (my_status == STATE_WARNING) ? _("WARNING")
554 : (my_status == STATE_CRITICAL) ? _("CRITICAL") 543 : (my_status == STATE_CRITICAL) ? _("CRITICAL")