mysql plugin
This commit is contained in:
parent
ebf4af7f13
commit
bddb4b013a
15
Makefile
15
Makefile
@ -2,6 +2,8 @@
|
||||
|
||||
WITH_RRD = yes
|
||||
|
||||
WITH_MYSQL = yes
|
||||
|
||||
# ############################
|
||||
|
||||
SAMMLER_SRC := sammler.c configfile.c logging.c network.c plugins.c
|
||||
@ -13,9 +15,13 @@ LDFLAGS := -ldl -rdynamic
|
||||
# ############################
|
||||
|
||||
ifeq ("$(WITH_RRD)", "yes")
|
||||
SAMMLER_SRC += rrdtool.c
|
||||
CFLAGS += -DWITH_RRD
|
||||
LDFLAGS += -lrrd
|
||||
SAMMLER_SRC += rrdtool.c
|
||||
CFLAGS += -DWITH_RRD
|
||||
LDFLAGS += -lrrd
|
||||
endif
|
||||
|
||||
ifeq ("$(WITH_MYSQL)", "yes")
|
||||
PLUGIN_SRC += p_mysql.c
|
||||
endif
|
||||
|
||||
# ############################
|
||||
@ -34,6 +40,9 @@ sammler: $(SAMMLER_SRC:%.c=%.o)
|
||||
%_sh.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
|
||||
$(LD) -shared -o $@ $<
|
||||
|
||||
|
241
p_mysql.c
Normal file
241
p_mysql.c
Normal 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, §ion->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
130
p_mysql_helper.c
Normal 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
33
p_mysql_helper.h
Normal 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_ */
|
@ -96,12 +96,11 @@ static int plugin_load(char *filename)
|
||||
void plugin_init(int flags)
|
||||
{
|
||||
struct conf_section *section;
|
||||
struct conf_tupel *tupel;
|
||||
|
||||
section = config_get_section("global");
|
||||
if (section == NULL)
|
||||
return;
|
||||
|
||||
struct conf_tupel *tupel;
|
||||
list_for_each_entry(tupel, §ion->tupel, list)
|
||||
if (!strcmp(tupel->option, "plugin"))
|
||||
plugin_load(tupel->parameter);
|
||||
|
@ -20,6 +20,7 @@ plugin p_mount.so
|
||||
#plugin p_ctstat.so
|
||||
#plugin p_rtstat.so
|
||||
plugin p_random.so
|
||||
#plugin p_mysql.so
|
||||
|
||||
# 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
|
||||
@ -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: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
|
||||
|
||||
[p_mysql]
|
||||
server name:host:user:pass
|
||||
|
Loading…
Reference in New Issue
Block a user