From de392a81ede00fef1c25e220ee253d487453f6cd Mon Sep 17 00:00:00 2001 From: Lorenz Kästle <12514511+RincewindsHat@users.noreply.github.com> Date: Wed, 12 Mar 2025 02:16:41 +0100 Subject: Refactor check_pgsql --- plugins/Makefile.am | 1 + plugins/check_pgsql.c | 143 +++++++++++++++++++---------------------- plugins/check_pgsql.d/config.h | 61 ++++++++++++++++++ 3 files changed, 128 insertions(+), 77 deletions(-) create mode 100644 plugins/check_pgsql.d/config.h (limited to 'plugins') diff --git a/plugins/Makefile.am b/plugins/Makefile.am index 5d4449bf..6ee121ba 100644 --- a/plugins/Makefile.am +++ b/plugins/Makefile.am @@ -61,6 +61,7 @@ EXTRA_DIST = t \ check_mysql_query.d \ check_mrtg.d \ check_apt.d \ + check_pgsql.d \ check_by_ssh.d \ check_smtp.d \ check_mysql.d \ 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 @@ * *****************************************************************************/ +#include "states.h" const char *progname = "check_pgsql"; const char *copyright = "1999-2024"; const char *email = "devel@monitoring-plugins.org"; @@ -35,12 +36,13 @@ const char *email = "devel@monitoring-plugins.org"; #include "common.h" #include "utils.h" #include "utils_cmd.h" +#include "check_pgsql.d/config.h" +#include "thresholds.h" #include "netutils.h" #include #include -#define DEFAULT_DB "template1" #define DEFAULT_HOST "127.0.0.1" /* return the PSQL server version as a 3-tuple */ @@ -53,33 +55,18 @@ const char *email = "devel@monitoring-plugins.org"; #define PSQL_SOCKET3(host, port) \ ((NULL == (host)) || ('\0' == *(host))) ? DEFAULT_PGSOCKET_DIR : host, PSQL_IS_UNIX_DOMAIN_SOCKET(host) ? "/.s.PGSQL." : ":", port -enum { - DEFAULT_PORT = 5432, - DEFAULT_WARN = 2, - DEFAULT_CRIT = 8 -}; +typedef struct { + int errorcode; + check_pgsql_config config; +} check_pgsql_config_wrapper; +static check_pgsql_config_wrapper process_arguments(int /*argc*/, char ** /*argv*/); -static int process_arguments(int /*argc*/, char ** /*argv*/); static void print_help(void); static bool is_pg_logname(char * /*username*/); -static int do_query(PGconn * /*conn*/, char * /*query*/); +static mp_state_enum do_query(PGconn * /*conn*/, char * /*query*/, const char /*pgqueryname*/[], thresholds * /*qthresholds*/, + char * /*query_warning*/, char * /*query_critical*/); void print_usage(void); -static char *pghost = NULL; /* host name of the backend server */ -static char *pgport = NULL; /* port of the backend server */ -static char *pgoptions = NULL; -static char *pgtty = NULL; -static char dbName[NAMEDATALEN] = DEFAULT_DB; -static char *pguser = NULL; -static char *pgpasswd = NULL; -static char *pgparams = NULL; -static double twarn = (double)DEFAULT_WARN; -static double tcrit = (double)DEFAULT_CRIT; -static char *pgquery = NULL; -static char *pgqueryname = NULL; -static char *query_warning = NULL; -static char *query_critical = NULL; -static thresholds *qthresholds = NULL; static int verbose = 0; #define OPTID_QUERYNAME -1000 @@ -139,20 +126,16 @@ int main(int argc, char **argv) { bindtextdomain(PACKAGE, LOCALEDIR); textdomain(PACKAGE); - /* begin, by setting the parameters for a backend connection if the - * parameters are null, then the system will try to use reasonable - * defaults by looking up environment variables or, failing that, - * using hardwired constants */ - - pgoptions = NULL; /* special options to start up the backend server */ - pgtty = NULL; /* debugging tty for the backend server */ - /* Parse extra opts if any */ argv = np_extra_opts(&argc, argv, progname); - if (process_arguments(argc, argv) == ERROR) { + check_pgsql_config_wrapper tmp_config = process_arguments(argc, argv); + if (tmp_config.errorcode == ERROR) { usage4(_("Could not parse arguments")); } + + const check_pgsql_config config = tmp_config.config; + if (verbose > 2) { printf("Arguments initialized\n"); } @@ -164,31 +147,31 @@ int main(int argc, char **argv) { alarm(timeout_interval); char *conninfo = NULL; - if (pgparams) { - asprintf(&conninfo, "%s ", pgparams); + if (config.pgparams) { + asprintf(&conninfo, "%s ", config.pgparams); } - asprintf(&conninfo, "%sdbname = '%s'", conninfo ? conninfo : "", dbName); - if (pghost) { - asprintf(&conninfo, "%s host = '%s'", conninfo, pghost); + asprintf(&conninfo, "%sdbname = '%s'", conninfo ? conninfo : "", config.dbName); + if (config.pghost) { + asprintf(&conninfo, "%s host = '%s'", conninfo, config.pghost); } - if (pgport) { - asprintf(&conninfo, "%s port = '%s'", conninfo, pgport); + if (config.pgport) { + asprintf(&conninfo, "%s port = '%s'", conninfo, config.pgport); } - if (pgoptions) { - asprintf(&conninfo, "%s options = '%s'", conninfo, pgoptions); + if (config.pgoptions) { + asprintf(&conninfo, "%s options = '%s'", conninfo, config.pgoptions); } /* if (pgtty) -- ignored by PQconnectdb */ - if (pguser) { - asprintf(&conninfo, "%s user = '%s'", conninfo, pguser); + if (config.pguser) { + asprintf(&conninfo, "%s user = '%s'", conninfo, config.pguser); } if (verbose) { /* do not include password (see right below) in output */ - printf("Connecting to PostgreSQL using conninfo: %s%s\n", conninfo, pgpasswd ? " password = " : ""); + printf("Connecting to PostgreSQL using conninfo: %s%s\n", conninfo, config.pgpasswd ? " password = " : ""); } - if (pgpasswd) { - asprintf(&conninfo, "%s password = '%s'", conninfo, pgpasswd); + if (config.pgpasswd) { + asprintf(&conninfo, "%s password = '%s'", conninfo, config.pgpasswd); } /* make a connection to the database */ @@ -203,7 +186,7 @@ int main(int argc, char **argv) { end_timeval.tv_usec += 1000000; } double elapsed_time = - (double)(end_timeval.tv_sec - start_timeval.tv_sec) + (double)(end_timeval.tv_usec - start_timeval.tv_usec) / 1000000.0; + (double)(end_timeval.tv_sec - start_timeval.tv_sec) + ((double)(end_timeval.tv_usec - start_timeval.tv_usec) / 1000000.0); if (verbose) { printf("Time elapsed: %f\n", elapsed_time); @@ -214,15 +197,15 @@ int main(int argc, char **argv) { printf("Verifying connection\n"); } if (PQstatus(conn) == CONNECTION_BAD) { - printf(_("CRITICAL - no connection to '%s' (%s).\n"), dbName, PQerrorMessage(conn)); + printf(_("CRITICAL - no connection to '%s' (%s).\n"), config.dbName, PQerrorMessage(conn)); PQfinish(conn); return STATE_CRITICAL; } - int status = STATE_UNKNOWN; - if (elapsed_time > tcrit) { + mp_state_enum status = STATE_UNKNOWN; + if (elapsed_time > config.tcrit) { status = STATE_CRITICAL; - } else if (elapsed_time > twarn) { + } else if (elapsed_time > config.twarn) { status = STATE_WARNING; } else { status = STATE_OK; @@ -239,23 +222,23 @@ int main(int argc, char **argv) { PQprotocolVersion(conn), PQbackendPID(conn)); } - printf(_(" %s - database %s (%f sec.)|%s\n"), state_text(status), dbName, elapsed_time, - fperfdata("time", elapsed_time, "s", !!(twarn > 0.0), twarn, !!(tcrit > 0.0), tcrit, true, 0, false, 0)); + printf(_(" %s - database %s (%f sec.)|%s\n"), state_text(status), config.dbName, elapsed_time, + fperfdata("time", elapsed_time, "s", (config.twarn > 0.0), config.twarn, (config.tcrit > 0.0), config.tcrit, true, 0, false, 0)); - int query_status = STATE_UNKNOWN; - if (pgquery) { - query_status = do_query(conn, pgquery); + mp_state_enum query_status = STATE_UNKNOWN; + if (config.pgquery) { + query_status = do_query(conn, config.pgquery, config.pgqueryname, config.qthresholds, config.query_warning, config.query_critical); } if (verbose) { printf("Closing connection\n"); } PQfinish(conn); - return (pgquery && query_status > status) ? query_status : status; + return (config.pgquery && query_status > status) ? query_status : status; } /* process command-line arguments */ -int process_arguments(int argc, char **argv) { +check_pgsql_config_wrapper process_arguments(int argc, char **argv) { static struct option longopts[] = {{"help", no_argument, 0, 'h'}, {"version", no_argument, 0, 'V'}, {"timeout", required_argument, 0, 't'}, @@ -275,6 +258,11 @@ int process_arguments(int argc, char **argv) { {"verbose", no_argument, 0, 'v'}, {0, 0, 0, 0}}; + check_pgsql_config_wrapper result = { + .errorcode = OK, + .config = check_pgsql_config_init(), + }; + while (true) { int option = 0; 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) { if (!is_nonnegative(optarg)) { usage2(_("Critical threshold must be a positive integer"), optarg); } else { - tcrit = strtod(optarg, NULL); + result.config.tcrit = strtod(optarg, NULL); } break; case 'w': /* warning time threshold */ if (!is_nonnegative(optarg)) { usage2(_("Warning threshold must be a positive integer"), optarg); } else { - twarn = strtod(optarg, NULL); + result.config.twarn = strtod(optarg, NULL); } break; case 'C': /* critical query threshold */ - query_critical = optarg; + result.config.query_critical = optarg; break; case 'W': /* warning query threshold */ - query_warning = optarg; + result.config.query_warning = optarg; break; case 'H': /* host */ if ((*optarg != '/') && (!is_host(optarg))) { usage2(_("Invalid hostname/address"), optarg); } else { - pghost = optarg; + result.config.pghost = optarg; } break; case 'P': /* port */ if (!is_integer(optarg)) { usage2(_("Port must be a positive integer"), optarg); } else { - pgport = optarg; + result.config.pgport = optarg; } break; case 'd': /* database name */ if (strlen(optarg) >= NAMEDATALEN) { usage2(_("Database name exceeds the maximum length"), optarg); } - snprintf(dbName, NAMEDATALEN, "%s", optarg); + snprintf(result.config.dbName, NAMEDATALEN, "%s", optarg); break; case 'l': /* login name */ if (!is_pg_logname(optarg)) { usage2(_("User name is not valid"), optarg); } else { - pguser = optarg; + result.config.pguser = optarg; } break; case 'p': /* authentication password */ case 'a': - pgpasswd = optarg; + result.config.pgpasswd = optarg; break; case 'o': - if (pgparams) { - asprintf(&pgparams, "%s %s", pgparams, optarg); + if (result.config.pgparams) { + asprintf(&result.config.pgparams, "%s %s", result.config.pgparams, optarg); } else { - asprintf(&pgparams, "%s", optarg); + asprintf(&result.config.pgparams, "%s", optarg); } break; case 'q': - pgquery = optarg; + result.config.pgquery = optarg; break; case OPTID_QUERYNAME: - pgqueryname = optarg; + result.config.pgqueryname = optarg; break; case 'v': verbose++; @@ -369,9 +357,9 @@ int process_arguments(int argc, char **argv) { } } - set_thresholds(&qthresholds, query_warning, query_critical); + set_thresholds(&result.config.qthresholds, result.config.query_warning, result.config.query_critical); - return OK; + return result; } /** @@ -416,7 +404,7 @@ bool is_pg_logname(char *username) { void print_help(void) { char *myport; - xasprintf(&myport, "%d", DEFAULT_PORT); + xasprintf(&myport, "%d", 5432); print_revision(progname, NP_VERSION); @@ -504,7 +492,8 @@ void print_usage(void) { "[-q ] [-C ] [-W ]\n"); } -int do_query(PGconn *conn, char *query) { +mp_state_enum do_query(PGconn *conn, char *query, const char pgqueryname[], thresholds *qthresholds, char *query_warning, + char *query_critical) { if (verbose) { printf("Executing SQL query \"%s\".\n", query); } @@ -548,7 +537,7 @@ int do_query(PGconn *conn, char *query) { } } - int my_status = get_status(value, qthresholds); + mp_state_enum my_status = get_status(value, qthresholds); printf("QUERY %s - ", (my_status == STATE_OK) ? _("OK") : (my_status == STATE_WARNING) ? _("WARNING") : (my_status == STATE_CRITICAL) ? _("CRITICAL") diff --git a/plugins/check_pgsql.d/config.h b/plugins/check_pgsql.d/config.h new file mode 100644 index 00000000..2d4b8b89 --- /dev/null +++ b/plugins/check_pgsql.d/config.h @@ -0,0 +1,61 @@ +#pragma once + +#include "../../config.h" +#include "thresholds.h" +#include +#include + +#define DEFAULT_DB "template1" + +enum { + DEFAULT_WARN = 2, + DEFAULT_CRIT = 8, +}; + +typedef struct { + char *pghost; /* host name of the backend server */ + char *pgport; /* port of the backend server */ + char *pgoptions; /* special options to start up the backend server */ + char *pgtty; /* debugging tty for the backend server */ + char dbName[NAMEDATALEN]; + char *pguser; + char *pgpasswd; + char *pgparams; + char *pgquery; + char *pgqueryname; + + double twarn; + double tcrit; + thresholds *qthresholds; + char *query_warning; + char *query_critical; +} check_pgsql_config; + +/* begin, by setting the parameters for a backend connection if the + * parameters are null, then the system will try to use reasonable + * defaults by looking up environment variables or, failing that, + * using hardwired constants + * this targets .pgoptions and .pgtty + */ + +check_pgsql_config check_pgsql_config_init() { + check_pgsql_config tmp = { + .pghost = NULL, + .pgport = NULL, + .pgoptions = NULL, + .pgtty = NULL, + .dbName = DEFAULT_DB, + .pguser = NULL, + .pgpasswd = NULL, + .pgparams = NULL, + .pgquery = NULL, + .pgqueryname = NULL, + + .twarn = (double)DEFAULT_WARN, + .tcrit = (double)DEFAULT_CRIT, + .qthresholds = NULL, + .query_warning = NULL, + .query_critical = NULL, + }; + return tmp; +} -- cgit v1.2.3-74-g34f1