mysql plugin
This commit is contained in:
parent
ebf4af7f13
commit
bddb4b013a
9
Makefile
9
Makefile
@ -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
|
||||||
@ -18,6 +20,10 @@ ifeq ("$(WITH_RRD)", "yes")
|
|||||||
LDFLAGS += -lrrd
|
LDFLAGS += -lrrd
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
ifeq ("$(WITH_MYSQL)", "yes")
|
||||||
|
PLUGIN_SRC += p_mysql.c
|
||||||
|
endif
|
||||||
|
|
||||||
# ############################
|
# ############################
|
||||||
|
|
||||||
all: sammler $(PLUGIN_SRC:%.c=%.so)
|
all: sammler $(PLUGIN_SRC:%.c=%.so)
|
||||||
@ -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
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)
|
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, §ion->tupel, list)
|
list_for_each_entry(tupel, §ion->tupel, list)
|
||||||
if (!strcmp(tupel->option, "plugin"))
|
if (!strcmp(tupel->option, "plugin"))
|
||||||
plugin_load(tupel->parameter);
|
plugin_load(tupel->parameter);
|
||||||
|
@ -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
|
||||||
|
Loading…
Reference in New Issue
Block a user