summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLorenz Kästle <12514511+RincewindsHat@users.noreply.github.com>2025-11-07 15:01:36 +0100
committerLorenz Kästle <12514511+RincewindsHat@users.noreply.github.com>2025-11-07 15:01:36 +0100
commit9d827acbe1aac0edaa91a8765a87412a189cadf1 (patch)
tree89d4c09957e7b9e1787742e6ce1bdf14e18fc537
parentb5e7f4e6cc8c586fdb20949369e05105157a61a7 (diff)
downloadmonitoring-plugins-9d827acbe1aac0edaa91a8765a87412a189cadf1.tar.gz
check_mysql_query: implement modern output
-rw-r--r--plugins/check_mysql_query.c105
-rw-r--r--plugins/check_mysql_query.d/config.h4
-rw-r--r--plugins/t/check_mysql_query.t2
3 files changed, 65 insertions, 46 deletions
diff --git a/plugins/check_mysql_query.c b/plugins/check_mysql_query.c
index c7e84deb..cb79b4b4 100644
--- a/plugins/check_mysql_query.c
+++ b/plugins/check_mysql_query.c
@@ -29,11 +29,11 @@
29 * 29 *
30 *****************************************************************************/ 30 *****************************************************************************/
31 31
32const char *progname = "check_mysql_query";
33const char *copyright = "1999-2024";
34const char *email = "devel@monitoring-plugins.org";
35
36#include "common.h" 32#include "common.h"
33#include "output.h"
34#include "perfdata.h"
35#include "states.h"
36#include "thresholds.h"
37#include "utils.h" 37#include "utils.h"
38#include "utils_base.h" 38#include "utils_base.h"
39#include "netutils.h" 39#include "netutils.h"
@@ -42,6 +42,10 @@ const char *email = "devel@monitoring-plugins.org";
42#include <mysql.h> 42#include <mysql.h>
43#include <errmsg.h> 43#include <errmsg.h>
44 44
45const char *progname = "check_mysql_query";
46const char *copyright = "1999-2024";
47const char *email = "devel@monitoring-plugins.org";
48
45typedef struct { 49typedef struct {
46 int errorcode; 50 int errorcode;
47 check_mysql_query_config config; 51 check_mysql_query_config config;
@@ -83,27 +87,38 @@ int main(int argc, char **argv) {
83 mysql_options(&mysql, MYSQL_READ_DEFAULT_GROUP, "client"); 87 mysql_options(&mysql, MYSQL_READ_DEFAULT_GROUP, "client");
84 } 88 }
85 89
90 mp_check overall = mp_check_init();
91 mp_subcheck sc_connect = mp_subcheck_init();
92
86 /* establish a connection to the server and error checking */ 93 /* establish a connection to the server and error checking */
87 if (!mysql_real_connect(&mysql, config.db_host, config.db_user, config.db_pass, config.db, 94 if (!mysql_real_connect(&mysql, config.db_host, config.db_user, config.db_pass, config.db,
88 config.db_port, config.db_socket, 0)) { 95 config.db_port, config.db_socket, 0)) {
96 xasprintf(&sc_connect.output, "query failed: %s", mysql_error(&mysql));
97
89 if (mysql_errno(&mysql) == CR_UNKNOWN_HOST) { 98 if (mysql_errno(&mysql) == CR_UNKNOWN_HOST) {
90 die(STATE_WARNING, "QUERY %s: %s\n", _("WARNING"), mysql_error(&mysql)); 99 sc_connect = mp_set_subcheck_state(sc_connect, STATE_WARNING);
91 } else if (mysql_errno(&mysql) == CR_VERSION_ERROR) { 100 } else if (mysql_errno(&mysql) == CR_VERSION_ERROR) {
92 die(STATE_WARNING, "QUERY %s: %s\n", _("WARNING"), mysql_error(&mysql)); 101 sc_connect = mp_set_subcheck_state(sc_connect, STATE_WARNING);
93 } else if (mysql_errno(&mysql) == CR_OUT_OF_MEMORY) { 102 } else if (mysql_errno(&mysql) == CR_OUT_OF_MEMORY) {
94 die(STATE_WARNING, "QUERY %s: %s\n", _("WARNING"), mysql_error(&mysql)); 103 sc_connect = mp_set_subcheck_state(sc_connect, STATE_WARNING);
95 } else if (mysql_errno(&mysql) == CR_IPSOCK_ERROR) { 104 } else if (mysql_errno(&mysql) == CR_IPSOCK_ERROR) {
96 die(STATE_WARNING, "QUERY %s: %s\n", _("WARNING"), mysql_error(&mysql)); 105 sc_connect = mp_set_subcheck_state(sc_connect, STATE_WARNING);
97 } else if (mysql_errno(&mysql) == CR_SOCKET_CREATE_ERROR) { 106 } else if (mysql_errno(&mysql) == CR_SOCKET_CREATE_ERROR) {
98 die(STATE_WARNING, "QUERY %s: %s\n", _("WARNING"), mysql_error(&mysql)); 107 sc_connect = mp_set_subcheck_state(sc_connect, STATE_WARNING);
99 } else { 108 } else {
100 die(STATE_CRITICAL, "QUERY %s: %s\n", _("CRITICAL"), mysql_error(&mysql)); 109 sc_connect = mp_set_subcheck_state(sc_connect, STATE_CRITICAL);
101 } 110 }
111
112 mp_add_subcheck_to_check(&overall, sc_connect);
113 mp_exit(overall);
102 } 114 }
103 115
104 char *error = NULL; 116 sc_connect = mp_set_subcheck_state(sc_connect, STATE_OK);
117 xasprintf(&sc_connect.output, "query succeeded");
118 mp_add_subcheck_to_check(&overall, sc_connect);
119
105 if (mysql_query(&mysql, config.sql_query) != 0) { 120 if (mysql_query(&mysql, config.sql_query) != 0) {
106 error = strdup(mysql_error(&mysql)); 121 char *error = strdup(mysql_error(&mysql));
107 mysql_close(&mysql); 122 mysql_close(&mysql);
108 die(STATE_CRITICAL, "QUERY %s: %s - %s\n", _("CRITICAL"), _("Error with query"), error); 123 die(STATE_CRITICAL, "QUERY %s: %s - %s\n", _("CRITICAL"), _("Error with query"), error);
109 } 124 }
@@ -111,7 +126,7 @@ int main(int argc, char **argv) {
111 MYSQL_RES *res; 126 MYSQL_RES *res;
112 /* store the result */ 127 /* store the result */
113 if ((res = mysql_store_result(&mysql)) == NULL) { 128 if ((res = mysql_store_result(&mysql)) == NULL) {
114 error = strdup(mysql_error(&mysql)); 129 char *error = strdup(mysql_error(&mysql));
115 mysql_close(&mysql); 130 mysql_close(&mysql);
116 die(STATE_CRITICAL, "QUERY %s: Error with store_result - %s\n", _("CRITICAL"), error); 131 die(STATE_CRITICAL, "QUERY %s: Error with store_result - %s\n", _("CRITICAL"), error);
117 } 132 }
@@ -122,17 +137,24 @@ int main(int argc, char **argv) {
122 die(STATE_WARNING, "QUERY %s: %s\n", _("WARNING"), _("No rows returned")); 137 die(STATE_WARNING, "QUERY %s: %s\n", _("WARNING"), _("No rows returned"));
123 } 138 }
124 139
140 mp_subcheck sc_value = mp_subcheck_init();
125 MYSQL_ROW row; 141 MYSQL_ROW row;
126 /* fetch the first row */ 142 /* fetch the first row */
127 if ((row = mysql_fetch_row(res)) == NULL) { 143 if ((row = mysql_fetch_row(res)) == NULL) {
128 error = strdup(mysql_error(&mysql)); 144 xasprintf(&sc_value.output, "fetch row error - %s", mysql_error(&mysql));
129 mysql_free_result(res); 145 mysql_free_result(res);
130 mysql_close(&mysql); 146 mysql_close(&mysql);
131 die(STATE_CRITICAL, "QUERY %s: Fetch row error - %s\n", _("CRITICAL"), error); 147
148 sc_value = mp_set_subcheck_state(sc_value, STATE_CRITICAL);
149 mp_add_subcheck_to_check(&overall, sc_value);
150 mp_exit(overall);
132 } 151 }
133 152
134 if (!is_numeric(row[0])) { 153 if (!is_numeric(row[0])) {
135 die(STATE_CRITICAL, "QUERY %s: %s - '%s'\n", _("CRITICAL"), _("Is not a numeric"), row[0]); 154 xasprintf(&sc_value.output, "query result is not numeric");
155 sc_value = mp_set_subcheck_state(sc_value, STATE_CRITICAL);
156 mp_add_subcheck_to_check(&overall, sc_value);
157 mp_exit(overall);
136 } 158 }
137 159
138 double value = strtod(row[0], NULL); 160 double value = strtod(row[0], NULL);
@@ -147,24 +169,18 @@ int main(int argc, char **argv) {
147 printf("mysql result: %f\n", value); 169 printf("mysql result: %f\n", value);
148 } 170 }
149 171
150 int status = get_status(value, config.my_thresholds); 172 mp_perfdata pd_query_result = perfdata_init();
173 pd_query_result = mp_set_pd_value(pd_query_result, value);
174 pd_query_result = mp_pd_set_thresholds(pd_query_result, config.thresholds);
175 pd_query_result.label = "result";
176 mp_add_perfdata_to_subcheck(&sc_value, pd_query_result);
151 177
152 if (status == STATE_OK) { 178 sc_value = mp_set_subcheck_state(sc_value, mp_get_pd_status(pd_query_result));
153 printf("QUERY %s: ", _("OK")); 179 xasprintf(&sc_value.output, "'%s' returned '%f'", config.sql_query, value);
154 } else if (status == STATE_WARNING) { 180
155 printf("QUERY %s: ", _("WARNING")); 181 mp_add_subcheck_to_check(&overall, sc_value);
156 } else if (status == STATE_CRITICAL) {
157 printf("QUERY %s: ", _("CRITICAL"));
158 }
159 printf(_("'%s' returned %f | %s"), config.sql_query, value,
160 fperfdata("result", value, "", config.my_thresholds->warning,
161 config.my_thresholds->warning ? config.my_thresholds->warning->end : 0,
162 config.my_thresholds->critical,
163 config.my_thresholds->critical ? config.my_thresholds->critical->end : 0,
164 false, 0, false, 0));
165 printf("\n");
166 182
167 return status; 183 mp_exit(overall);
168} 184}
169 185
170/* process command-line arguments */ 186/* process command-line arguments */
@@ -195,9 +211,6 @@ check_mysql_query_config_wrapper process_arguments(int argc, char **argv) {
195 return result; 211 return result;
196 } 212 }
197 213
198 char *warning = NULL;
199 char *critical = NULL;
200
201 while (true) { 214 while (true) {
202 int option = 0; 215 int option = 0;
203 int option_char = getopt_long(argc, argv, "hvVP:p:u:d:H:s:q:w:c:f:g:", longopts, &option); 216 int option_char = getopt_long(argc, argv, "hvVP:p:u:d:H:s:q:w:c:f:g:", longopts, &option);
@@ -253,19 +266,25 @@ check_mysql_query_config_wrapper process_arguments(int argc, char **argv) {
253 case 'q': 266 case 'q':
254 xasprintf(&result.config.sql_query, "%s", optarg); 267 xasprintf(&result.config.sql_query, "%s", optarg);
255 break; 268 break;
256 case 'w': 269 case 'w': {
257 warning = optarg; 270 mp_range_parsed tmp = mp_parse_range_string(optarg);
258 break; 271 if (tmp.error != MP_PARSING_SUCCES) {
259 case 'c': 272 die(STATE_UNKNOWN, "failed to parse warnign threshold");
260 critical = optarg; 273 }
261 break; 274 result.config.thresholds = mp_thresholds_set_warn(result.config.thresholds, tmp.range);
275 } break;
276 case 'c': {
277 mp_range_parsed tmp = mp_parse_range_string(optarg);
278 if (tmp.error != MP_PARSING_SUCCES) {
279 die(STATE_UNKNOWN, "failed to parse critical threshold");
280 }
281 result.config.thresholds = mp_thresholds_set_crit(result.config.thresholds, tmp.range);
282 } break;
262 case '?': /* help */ 283 case '?': /* help */
263 usage5(); 284 usage5();
264 } 285 }
265 } 286 }
266 287
267 set_thresholds(&result.config.my_thresholds, warning, critical);
268
269 return validate_arguments(result); 288 return validate_arguments(result);
270} 289}
271 290
diff --git a/plugins/check_mysql_query.d/config.h b/plugins/check_mysql_query.d/config.h
index be019160..1c9952e5 100644
--- a/plugins/check_mysql_query.d/config.h
+++ b/plugins/check_mysql_query.d/config.h
@@ -15,7 +15,7 @@ typedef struct {
15 unsigned int db_port; 15 unsigned int db_port;
16 16
17 char *sql_query; 17 char *sql_query;
18 thresholds *my_thresholds; 18 mp_thresholds thresholds;
19} check_mysql_query_config; 19} check_mysql_query_config;
20 20
21check_mysql_query_config check_mysql_query_config_init() { 21check_mysql_query_config check_mysql_query_config_init() {
@@ -30,7 +30,7 @@ check_mysql_query_config check_mysql_query_config_init() {
30 .db_port = MYSQL_PORT, 30 .db_port = MYSQL_PORT,
31 31
32 .sql_query = NULL, 32 .sql_query = NULL,
33 .my_thresholds = NULL, 33 .thresholds = mp_thresholds_init(),
34 }; 34 };
35 return tmp; 35 return tmp;
36} 36}
diff --git a/plugins/t/check_mysql_query.t b/plugins/t/check_mysql_query.t
index c30245b2..6de48bf6 100644
--- a/plugins/t/check_mysql_query.t
+++ b/plugins/t/check_mysql_query.t
@@ -54,5 +54,5 @@ like( $result->output, "/No rows returned/", "No rows error message");
54 54
55$result = NPTest->testCmd("./check_mysql_query -q 'SHOW VARIABLES' -H $mysqlserver $mysql_login_details"); 55$result = NPTest->testCmd("./check_mysql_query -q 'SHOW VARIABLES' -H $mysqlserver $mysql_login_details");
56cmp_ok( $result->return_code, '==', 2, "Data not numeric"); 56cmp_ok( $result->return_code, '==', 2, "Data not numeric");
57like( $result->output, "/Is not a numeric/", "Data not numeric error message"); 57like( $result->output, "/is not numeric/", "Data not numeric error message");
58 58