mysql plugin

This commit is contained in:
Olaf Rempel 2006-10-08 01:58:01 +02:00
parent ebf4af7f13
commit bddb4b013a
6 changed files with 421 additions and 5 deletions

View File

@ -2,6 +2,8 @@
WITH_RRD = yes WITH_RRD = yes
WITH_MYSQL = yes
# ############################ # ############################
SAMMLER_SRC := sammler.c configfile.c logging.c network.c plugins.c SAMMLER_SRC := sammler.c configfile.c logging.c network.c plugins.c
@ -13,9 +15,13 @@ LDFLAGS := -ldl -rdynamic
# ############################ # ############################
ifeq ("$(WITH_RRD)", "yes") ifeq ("$(WITH_RRD)", "yes")
SAMMLER_SRC += rrdtool.c SAMMLER_SRC += rrdtool.c
CFLAGS += -DWITH_RRD CFLAGS += -DWITH_RRD
LDFLAGS += -lrrd LDFLAGS += -lrrd
endif
ifeq ("$(WITH_MYSQL)", "yes")
PLUGIN_SRC += p_mysql.c
endif endif
# ############################ # ############################
@ -34,6 +40,9 @@ sammler: $(SAMMLER_SRC:%.c=%.o)
%_sh.o: %.c %_sh.o: %.c
$(CC) $(CFLAGS) -fPIC -o $@ -c $< $(CC) $(CFLAGS) -fPIC -o $@ -c $<
p_mysql.so: p_mysql_sh.o p_mysql_helper_sh.o
$(LD) -shared -lmysqlclient -o $@ $^
%.so: %_sh.o %.so: %_sh.o
$(LD) -shared -o $@ $< $(LD) -shared -o $@ $<

241
p_mysql.c Normal file
View File

@ -0,0 +1,241 @@
/***************************************************************************
* Copyright (C) 10/2006 by Olaf Rempel *
* razzor@kopf-tisch.de *
* *
* 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 Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program; if not, write to the *
* Free Software Foundation, Inc., *
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
***************************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "plugins.h"
#include "configfile.h"
#include "list.h"
#include "p_mysql_helper.h"
#define DS_TRAFFIC 1
#define DS_COMMANDS 2
#define DS_QCACHE 3
#define DS_THREADS 4
struct server_entry {
struct list_head list;
void *mysql;
char name[0];
};
static LIST_HEAD(server_list);
static char *traffic_ds_def = {
"DS:bytes_received:COUNTER:90:0:U "
"DS:bytes_sent:COUNTER:90:0:U "
};
static char *commands_ds_def = {
"DS:com_delete:COUNTER:90:0:U "
"DS:com_insert:COUNTER:90:0:U "
"DS:com_select:COUNTER:90:0:U "
"DS:com_update:COUNTER:90:0:U "
"DS:connections:COUNTER:90:0:U "
"DS:questions:COUNTER:90:0:U "
};
static char *qcache_ds_def = {
"DS:qc_free_blocks:COUNTER:90:0:U "
"DS:qc_free_memory:COUNTER:90:0:U "
"DS:qc_hits:COUNTER:90:0:U "
"DS:qc_inserts:COUNTER:90:0:U "
"DS:qc_lowmem_prunes:COUNTER:90:0:U "
"DS:qc_queries_in_cache:COUNTER:90:0:U "
"DS:qc_total_blocks:COUNTER:90:0:U "
};
static char *threads_ds_def = {
"DS:threads_cached:COUNTER:90:0:U "
"DS:threads_connected:COUNTER:90:0:U "
"DS:threads_created:COUNTER:90:0:U "
"DS:threads_running:COUNTER:90:0:U "
};
static char * get_ds(int ds_id)
{
switch (ds_id) {
case DS_TRAFFIC:
return traffic_ds_def;
case DS_COMMANDS:
return commands_ds_def;
case DS_QCACHE:
return qcache_ds_def;
case DS_THREADS:
return threads_ds_def;
default:
return NULL;
}
}
struct sammler_plugin plugin;
static int probe(void)
{
struct mysql_stats stats;
char filename[32];
int len;
memset(&stats, 0, sizeof(struct mysql_stats));
struct server_entry *entry;
list_for_each_entry(entry, &server_list, list) {
if (ping_connection(entry->mysql) != 0)
continue;
if (get_stats(entry->mysql, &stats) != 0)
continue;
len = snprintf(filename, sizeof(filename), "mysql-traffic-%s.rrd", entry->name);
if (len < 0 || len >= sizeof(filename))
continue;
probe_submit(&plugin, filename, DS_TRAFFIC, "%llu:%llu",
stats.bytes_received, stats.bytes_sent);
len = snprintf(filename, sizeof(filename), "mysql-commands-%s.rrd", entry->name);
if (len < 0 || len >= sizeof(filename))
continue;
probe_submit(&plugin, filename, DS_COMMANDS, "%llu:%llu:%llu:%llu:%llu:%llu",
stats.com_delete, stats.com_insert,
stats.com_select, stats.com_update,
stats.connections, stats.questions);
len = snprintf(filename, sizeof(filename), "mysql-qcache-%s.rrd", entry->name);
if (len < 0 || len >= sizeof(filename))
continue;
probe_submit(&plugin, filename, DS_QCACHE, "%llu:%llu:%llu:%llu:%llu:%llu:%llu",
stats.qc_free_blocks, stats.qc_free_memory,
stats.qc_hits, stats.qc_inserts,
stats.qc_lowmem_prunes, stats.qc_queries_in_cache,
stats.qc_total_blocks);
len = snprintf(filename, sizeof(filename), "mysql-threads-%s.rrd", entry->name);
if (len < 0 || len >= sizeof(filename))
continue;
probe_submit(&plugin, filename, DS_THREADS, "%llu:%llu:%llu:%llu",
stats.threads_cached, stats.threads_connected,
stats.threads_created, stats.threads_running);
}
return 0;
}
static int init(void)
{
int retval = -1;
struct conf_section *section;
section = config_get_section("p_mysql");
if (section == NULL) {
log_print(LOG_ERROR, "p_mysql: no config section found");
return -1;
}
struct conf_tupel *tupel;
list_for_each_entry(tupel, &section->tupel, list) {
if (strcmp(tupel->option, "server"))
continue;
char *name = tupel->parameter;
char *host = strchr(name, ':');
if (host == NULL) {
log_print(LOG_ERROR, "p_mysql: parse error (1)");
continue;
}
*host++ = '\0';
char *user = strchr(host, ':');
if (user == NULL) {
log_print(LOG_ERROR, "p_mysql: parse error (2)");
*--host = ':';
continue;
}
*user++ = '\0';
char *pass = strchr(user, ':');
if (pass == NULL) {
log_print(LOG_ERROR, "p_mysql: parse error (3)");
*--host = ':';
*--user = ':';
continue;
}
*pass++ = '\0';
int len = strlen(name);
struct server_entry *entry = malloc(sizeof(struct server_entry) + len +1);
if (entry == NULL) {
log_print(LOG_ERROR, "p_mysql: out of memory");
*--host = ':';
*--user = ':';
*--pass = ':';
continue;
}
strcpy(entry->name, name);
entry->mysql = init_connection(host, user, pass);
if (entry->mysql < 0) {
free(entry);
*--host = ':';
*--user = ':';
*--pass = ':';
continue;
}
*--host = ':';
*--user = ':';
*--pass = ':';
log_print(LOG_DEBUG, "p_mysql: added server '%s'", entry->name);
list_add_tail(&entry->list, &server_list);
retval = 0;
}
return retval;
}
static int fini(void)
{
struct server_entry *entry, *tmp;
list_for_each_entry_safe(entry, tmp, &server_list, list)
free(entry);
return 0;
}
struct sammler_plugin plugin = {
.name = "mysql",
.interval = 60,
.init = &init,
.fini = &fini,
.probe = &probe,
.get_ds = &get_ds,
};

130
p_mysql_helper.c Normal file
View File

@ -0,0 +1,130 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <mysql/mysql.h>
#include "logging.h"
#include "p_mysql_helper.h"
void * init_connection(char *host, char *user, char *pass)
{
MYSQL *con = NULL;
con = mysql_init(con);
if (con == NULL)
return NULL;
con = mysql_real_connect(con, host, user, pass, NULL, 0, NULL, 0);
if (con == NULL) {
log_print(LOG_ERROR, "p_mysql: %s", mysql_error(con));
return NULL;
}
return con;
}
int ping_connection(void *mysql)
{
MYSQL *con = mysql;
return mysql_ping(con);
}
int get_stats(void *mysql, struct mysql_stats *stats)
{
MYSQL *con = mysql;
char *query;
if (mysql_get_server_version(con) >= 50002)
query = "SHOW GLOBAL STATUS";
else
query = "SHOW STATUS";
if (mysql_real_query(con, query, strlen(query))) {
log_print(LOG_ERROR, "p_mysql: %s", mysql_error(con));
return -1;
}
MYSQL_RES *res;
res = mysql_store_result(con);
if (res == NULL) {
log_print(LOG_ERROR, "p_mysql: %s", mysql_error(con));
return -1;
}
MYSQL_ROW row;
while ((row = mysql_fetch_row(res))) {
char *key;
unsigned long long val;
key = row[0];
val = atoll(row[1]);
if (!strncmp(key, "Bytes_", 6)) {
if (!strcmp(key +6, "received"))
stats->bytes_received = val;
else if (!strcmp(key +6, "sent"))
stats->bytes_sent = val;
} else if (!strncmp(key, "Com_", 4)) {
if (!strcmp(key +4, "delete"))
stats->com_delete = val;
else if (!strcmp(key +4, "insert"))
stats->com_insert = val;
else if (!strcmp(key +4, "select"))
stats->com_select = val;
else if (!strcmp(key +4, "update"))
stats->com_update = val;
} else if (!strcmp(key, "Connections")) {
stats->connections = val;
} else if (!strncmp(key, "Qcache_", 7)) {
if (!strcmp(key +7, "free_blocks"))
stats->qc_free_blocks = val;
else if (!strcmp(key +7, "free_memory"))
stats->qc_free_memory = val;
else if (!strcmp(key +7, "hits"))
stats->qc_hits = val;
else if (!strcmp(key +7, "inserts"))
stats->qc_inserts = val;
else if (!strcmp(key +7, "lowmem_prunes"))
stats->qc_lowmem_prunes = val;
else if (!strcmp(key +7, "queries_in_cache"))
stats->qc_queries_in_cache = val;
else if (!strcmp(key +7, "total_blocks"))
stats->qc_total_blocks = val;
} else if (!strcmp(key, "Questions")) {
stats->questions = val;
} else if (!strncmp(key, "Threads_", 8)) {
if (!strcmp(key, "Threads_cached"))
stats->threads_cached = val;
else if (!strcmp(key, "Threads_connected"))
stats->threads_connected = val;
else if (!strcmp(key, "Threads_created"))
stats->threads_created = val;
else if (!strcmp(key, "Threads_running"))
stats->threads_running = val;
}
}
mysql_free_result(res);
return 0;
}

33
p_mysql_helper.h Normal file
View File

@ -0,0 +1,33 @@
#ifndef _P_MYSQL_HELPER_H_
#define _P_MYSQL_HELPER_H_
#include <stdint.h>
struct mysql_stats {
uint64_t bytes_received;
uint64_t bytes_sent;
uint64_t com_delete;
uint64_t com_insert;
uint64_t com_select;
uint64_t com_update;
uint64_t connections;
uint64_t qc_free_blocks;
uint64_t qc_free_memory;
uint64_t qc_hits;
uint64_t qc_inserts;
uint64_t qc_lowmem_prunes;
uint64_t qc_queries_in_cache;
uint64_t qc_total_blocks;
uint64_t questions;
uint64_t threads_cached;
uint64_t threads_connected;
uint64_t threads_created;
uint64_t threads_running;
};
void * init_connection(char *host, char *user, char *pass);
int ping_connection(void *mysql);
int get_stats(void *mysql, struct mysql_stats *stats);
#endif /* _P_MYSQL_HELPER_H_ */

View File

@ -96,12 +96,11 @@ static int plugin_load(char *filename)
void plugin_init(int flags) void plugin_init(int flags)
{ {
struct conf_section *section; struct conf_section *section;
struct conf_tupel *tupel;
section = config_get_section("global"); section = config_get_section("global");
if (section == NULL) if (section == NULL)
return; return;
struct conf_tupel *tupel;
list_for_each_entry(tupel, &section->tupel, list) list_for_each_entry(tupel, &section->tupel, list)
if (!strcmp(tupel->option, "plugin")) if (!strcmp(tupel->option, "plugin"))
plugin_load(tupel->parameter); plugin_load(tupel->parameter);

View File

@ -20,6 +20,7 @@ plugin p_mount.so
#plugin p_ctstat.so #plugin p_ctstat.so
#plugin p_rtstat.so #plugin p_rtstat.so
plugin p_random.so plugin p_random.so
#plugin p_mysql.so
# 1h(10s), 12h(1min), 48h(2min), 14d(15min), 4w(60min), 2y(12h) # 1h(10s), 12h(1min), 48h(2min), 14d(15min), 4w(60min), 2y(12h)
rra RRA:MIN:0.1:1:360 RRA:AVERAGE:0.1:1:360 RRA:MAX:0.1:1:360 rra RRA:MIN:0.1:1:360 RRA:AVERAGE:0.1:1:360 RRA:MAX:0.1:1:360
@ -28,3 +29,6 @@ rra RRA:MIN:0.1:12:1440 RRA:AVERAGE:0.1:12:1440 RRA:MAX:0.1:12:1440
rra RRA:MIN:0.1:90:1344 RRA:AVERAGE:0.1:90:1344 RRA:MAX:0.1:90:1344 rra RRA:MIN:0.1:90:1344 RRA:AVERAGE:0.1:90:1344 RRA:MAX:0.1:90:1344
rra RRA:MIN:0.1:360:1440 RRA:AVERAGE:0.1:360:1440 RRA:MAX:0.1:360:1440 rra RRA:MIN:0.1:360:1440 RRA:AVERAGE:0.1:360:1440 RRA:MAX:0.1:360:1440
rra RRA:MIN:0.1:4320:1440 RRA:AVERAGE:0.1:4320:1440 RRA:MAX:0.1:4320:1440 rra RRA:MIN:0.1:4320:1440 RRA:AVERAGE:0.1:4320:1440 RRA:MAX:0.1:4320:1440
[p_mysql]
server name:host:user:pass