/**
* collectd - src/mysql.c
* Copyright (C) 2006-2009 Florian octo Forster
- * Copyright (C) 2009 Doug MacEachern
- * Copyright (C) 2009 Sebastian tokkee Harl
+ * Copyright (C) 2008 Mirko Buffoni
+ * Copyright (C) 2009 Doug MacEachern
+ * Copyright (C) 2009 Sebastian tokkee Harl
+ * Copyright (C) 2009 Rodolphe QuiƩdeville
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Mirko Buffoni <briareos at eswat.org>
* Doug MacEachern <dougm at hyperic.com>
* Sebastian tokkee Harl <sh at tokkee.org>
+ * Rodolphe QuiƩdeville <rquiedeville at bearstech.com>
**/
#include "collectd.h"
int master_stats;
int slave_stats;
+ int slave_notif;
+ int slave_io_running;
+ int slave_sql_running;
+
MYSQL *con;
int state;
};
db->socket = NULL;
db->con = NULL;
+ /* trigger a notification, if it's not running */
+ db->slave_io_running = 1;
+ db->slave_sql_running = 1;
+
plugin_block = 1;
if (strcasecmp ("Plugin", ci->key) == 0)
{
return (status);
}
assert (db->instance != NULL);
- db->database = strdup (db->instance);
}
else
{
status = mysql_config_set_boolean (&db->master_stats, child);
else if (strcasecmp ("SlaveStats", child->key) == 0)
status = mysql_config_set_boolean (&db->slave_stats, child);
+ else if (strcasecmp ("SlaveNotifications", child->key) == 0)
+ status = mysql_config_set_boolean (&db->slave_notif, child);
else
{
WARNING ("mysql plugin: Option `%s' not allowed here.", child->key);
db->port);
status = -1;
}
- if (db->database == NULL)
- {
- ERROR ("mysql plugin: No `Database' configured");
- status = -1;
- }
break;
} /* while (status == 0) */
user_data_t ud;
char cb_name[DATA_MAX_NAME_LEN];
- DEBUG ("mysql plugin: Registering new read callback: %s", db->database);
+ DEBUG ("mysql plugin: Registering new read callback: %s",
+ (db->database != NULL) ? db->database : "<default>");
memset (&ud, 0, sizeof (ud));
ud.data = (void *) db;
if (mysql_real_connect (db->con, db->host, db->user, db->pass,
db->database, db->port, db->socket, 0) == NULL)
{
- ERROR ("mysql_real_connect failed: %s", mysql_error (db->con));
+ ERROR ("mysql plugin: Failed to connect to database %s "
+ "at server %s: %s",
+ (db->database != NULL) ? db->database : "<none>",
+ (db->host != NULL) ? db->host : "localhost",
+ mysql_error (db->con));
db->state = 0;
return (NULL);
}
else
{
+ INFO ("mysql plugin: Sucessfully connected to database %s "
+ "at server %s (server version: %s, protocol version: %d)",
+ (db->database != NULL) ? db->database : "<none>",
+ mysql_get_host_info (db->con),
+ mysql_get_server_info (db->con),
+ mysql_get_proto_info (db->con));
db->state = 1;
return (db->con);
}
} /* static MYSQL *getconnection (mysql_database_t *db) */
-static void set_host (mysql_database_t *db, value_list_t *vl)
+static void set_host (mysql_database_t *db, char *buf, size_t buflen)
{
/* XXX legacy mode - use hostname_g */
if (db->instance == NULL)
- sstrncpy (vl->host, hostname_g, sizeof (vl->host));
+ sstrncpy (buf, hostname_g, buflen);
else
{
if ((db->host == NULL)
|| (strcmp ("", db->host) == 0)
|| (strcmp ("localhost", db->host) == 0))
- sstrncpy (vl->host, hostname_g, sizeof (vl->host));
+ sstrncpy (buf, hostname_g, buflen);
else
- sstrncpy (vl->host, db->host, sizeof (vl->host));
+ sstrncpy (buf, db->host, buflen);
}
}
-static void set_plugin_instance (mysql_database_t *db, value_list_t *vl)
+static void set_plugin_instance (mysql_database_t *db,
+ char *buf, size_t buflen)
{
/* XXX legacy mode - no plugin_instance */
if (db->instance == NULL)
- sstrncpy (vl->plugin_instance, "",
- sizeof (vl->plugin_instance));
+ sstrncpy (buf, "", buflen);
else
- sstrncpy (vl->plugin_instance, db->instance,
- sizeof (vl->plugin_instance));
+ sstrncpy (buf, db->instance, buflen);
}
static void submit (const char *type, const char *type_instance,
vl.values = values;
vl.values_len = values_len;
- set_host (db, &vl);
+ set_host (db, vl.host, sizeof (vl.host));
sstrncpy (vl.plugin, "mysql", sizeof (vl.plugin));
- set_plugin_instance (db, &vl);
+ set_plugin_instance (db, vl.plugin_instance, sizeof (vl.plugin_instance));
sstrncpy (vl.type, type, sizeof (vl.type));
if (type_instance != NULL)
/* WTF? libmysqlclient does not seem to provide any means to
* translate a column name to a column index ... :-/ */
const int READ_MASTER_LOG_POS_IDX = 6;
+ const int SLAVE_IO_RUNNING_IDX = 10;
+ const int SLAVE_SQL_RUNNING_IDX = 11;
const int EXEC_MASTER_LOG_POS_IDX = 21;
const int SECONDS_BEHIND_MASTER_IDX = 32;
- unsigned long long counter;
- double gauge;
-
query = "SHOW SLAVE STATUS";
res = exec_query (con, query);
return (-1);
}
- counter = atoll (row[READ_MASTER_LOG_POS_IDX]);
- counter_submit ("mysql_log_position", "slave-read", counter, db);
+ if (db->slave_stats)
+ {
+ unsigned long long counter;
+ double gauge;
- counter = atoll (row[EXEC_MASTER_LOG_POS_IDX]);
- counter_submit ("mysql_log_position", "slave-exec", counter, db);
+ counter = atoll (row[READ_MASTER_LOG_POS_IDX]);
+ counter_submit ("mysql_log_position", "slave-read", counter, db);
- if (row[SECONDS_BEHIND_MASTER_IDX] != NULL)
+ counter = atoll (row[EXEC_MASTER_LOG_POS_IDX]);
+ counter_submit ("mysql_log_position", "slave-exec", counter, db);
+
+ if (row[SECONDS_BEHIND_MASTER_IDX] != NULL)
+ {
+ gauge = atof (row[SECONDS_BEHIND_MASTER_IDX]);
+ gauge_submit ("time_offset", NULL, gauge, db);
+ }
+ }
+
+ if (db->slave_notif)
{
- gauge = atof (row[SECONDS_BEHIND_MASTER_IDX]);
- gauge_submit ("time_offset", NULL, gauge, db);
+ notification_t n = { 0, time (NULL), "", "",
+ "mysql", "", "time_offset", "", NULL };
+
+ char *io, *sql;
+
+ io = row[SLAVE_IO_RUNNING_IDX];
+ sql = row[SLAVE_SQL_RUNNING_IDX];
+
+ set_host (db, n.host, sizeof (n.host));
+ set_plugin_instance (db,
+ n.plugin_instance, sizeof (n.plugin_instance));
+
+ if (((io == NULL) || (strcasecmp (io, "yes") != 0))
+ && (db->slave_io_running))
+ {
+ n.severity = NOTIF_WARNING;
+ ssnprintf (n.message, sizeof (n.message),
+ "slave I/O thread not started or not connected to master");
+ plugin_dispatch_notification (&n);
+ db->slave_io_running = 0;
+ }
+ else if (((io != NULL) && (strcasecmp (io, "yes") == 0))
+ && (! db->slave_io_running))
+ {
+ n.severity = NOTIF_OKAY;
+ ssnprintf (n.message, sizeof (n.message),
+ "slave I/O thread started and connected to master");
+ plugin_dispatch_notification (&n);
+ db->slave_io_running = 1;
+ }
+
+ if (((sql == NULL) || (strcasecmp (sql, "yes") != 0))
+ && (db->slave_sql_running))
+ {
+ n.severity = NOTIF_WARNING;
+ ssnprintf (n.message, sizeof (n.message),
+ "slave SQL thread not started");
+ plugin_dispatch_notification (&n);
+ db->slave_sql_running = 0;
+ }
+ else if (((sql != NULL) && (strcasecmp (sql, "yes") == 0))
+ && (! db->slave_sql_running))
+ {
+ n.severity = NOTIF_OKAY;
+ ssnprintf (n.message, sizeof (n.message),
+ "slave SQL thread started");
+ plugin_dispatch_notification (&n);
+ db->slave_sql_running = 0;
+ }
}
row = mysql_fetch_row (res);
key = row[0];
val = atoll (row[1]);
- if (strncmp (key, "Com_", 4) == 0)
+ if (strncmp (key, "Com_",
+ strlen ("Com_")) == 0)
{
if (val == 0ULL)
continue;
/* Ignore `prepared statements' */
- if (strncmp (key, "Com_stmt_", 9) != 0)
- counter_submit ("mysql_commands", key + 4, val, db);
+ if (strncmp (key, "Com_stmt_", strlen ("Com_stmt_")) != 0)
+ counter_submit ("mysql_commands",
+ key + strlen ("Com_"),
+ val, db);
}
- else if (strncmp (key, "Handler_", 8) == 0)
+ else if (strncmp (key, "Handler_",
+ strlen ("Handler_")) == 0)
{
if (val == 0ULL)
continue;
- counter_submit ("mysql_handler", key + 8, val, db);
+ counter_submit ("mysql_handler",
+ key + strlen ("Handler_"),
+ val, db);
}
- else if (strncmp (key, "Qcache_", 7) == 0)
+ else if (strncmp (key, "Qcache_",
+ strlen ("Qcache_")) == 0)
{
if (strcmp (key, "Qcache_hits") == 0)
qcache_hits = val;
else if (strcmp (key, "Qcache_queries_in_cache") == 0)
qcache_queries_in_cache = (int) val;
}
- else if (strncmp (key, "Bytes_", 6) == 0)
+ else if (strncmp (key, "Bytes_",
+ strlen ("Bytes_")) == 0)
{
if (strcmp (key, "Bytes_received") == 0)
traffic_incoming += val;
else if (strcmp (key, "Bytes_sent") == 0)
traffic_outgoing += val;
}
- else if (strncmp (key, "Threads_", 8) == 0)
+ else if (strncmp (key, "Threads_",
+ strlen ("Threads_")) == 0)
{
if (strcmp (key, "Threads_running") == 0)
threads_running = (int) val;
else if (strcmp (key, "Threads_created") == 0)
threads_created = val;
}
+ else if (strncmp (key, "Table_locks_",
+ strlen ("Table_locks_")) == 0)
+ {
+ counter_submit ("mysql_locks",
+ key + strlen ("Table_locks_"),
+ val, db);
+ }
}
mysql_free_result (res); res = NULL;
if (db->master_stats)
mysql_read_master_stats (db, con);
- if (db->slave_stats)
+ if ((db->slave_stats) || (db->slave_notif))
mysql_read_slave_stats (db, con);
return (0);