|
From: Martijn <wa...@we...> - 2004-06-12 12:40:29
|
wasted 2004/06/12 04:32:50 PDT
Modified files:
src Makefile.am Makefile.in main.c messages.h
statserv.c
Added files:
src rrdgraph.c rrdgraph.h
Log:
Add RRDGraph functionality, bump version.
Revision Changes Path
1.2 +1 -0 wStats-pgsql/src/Makefile.am
1.2 +6 -3 wStats-pgsql/src/Makefile.in
1.2 +3 -1 wStats-pgsql/src/main.c
1.2 +3 -1 wStats-pgsql/src/messages.h
1.1 +489 -0 wStats-pgsql/src/rrdgraph.c (new)
1.1 +23 -0 wStats-pgsql/src/rrdgraph.h (new)
1.2 +12 -2 wStats-pgsql/src/statserv.c
Index: rrdgraph.c
====================================================================
/* rrdgraph.c - RRDTool graphs
* Copyright 2004 Martijn Smit, WhatNET Coder-Com
*
* 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. Important limitations are
* listed in the COPYING file that accompanies this software.
*
* 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
*
* $Id: rrdgraph.c,v 1.1 2004/06/12 11:32:50 wasted Exp $
*/
#include "conf.h"
#include "gline.h"
#include "modcmd.h"
#include "pgsql.h"
#include "rrdgraph.h"
#include "timeq.h"
#ifdef HAVE_SYS_TIMES_H
#include <sys/times.h>
#endif
#ifdef HAVE_NETINET_IN_H
#include <netinet/in.h>
#endif
#ifdef HAVE_ARPA_INET_H
#include <arpa/inet.h>
#endif
struct module *rrd_module;
static struct log_type *RRD_LOG;
static struct {
unsigned int active;
unsigned long update_duration;
struct string_list *ignore_servers;
char *rrdtool_path;
char *servername;
char *output_dir;
} rrd_conf;
#define RRD_CONF_NAME "rrdgraphs"
#define KEY_IGNORE_SERVERS "ignore_servers"
#define KEY_ACTIVE "active"
#define KEY_GRAPH_UPDATE "graph_update"
#define KEY_OUTPUTDIR "output_dir"
#define KEY_SERVERNAME "servername"
#define KEY_RRD_PATH "rrd_path"
#define DEF_COLORS "-c BACK#FFFFFF -c CANVAS#F3F3F3 -c SHADEA#C8C8C8 -c SHADEB#969696 -c GRID#8C8C8C -c MGRID#821E1E -c FONT#000000 -c FRAME#000000 -c ARROW#FF0000"
static void make_graphs(UNUSED_ARG(void *data));
unsigned int
check_rrdtool(const char *path)
{
FILE *fp;
if (!(fp = fopen(path, "r"))) {
log_module(RRD_LOG, LOG_ERROR, "Unable to open rrdtool (%s) for reading: %s", path, strerror(errno));
return 0;
}
fclose(fp);
if(access(path, X_OK) == -1) {
log_module(RRD_LOG, LOG_ERROR, "access() failed on rrdtool (%s): %s", path, strerror(errno));
return 0;
}
return 1;
}
unsigned int
rrd_exists(char *name)
{
char file[512];
FILE *fp;
sprintf(file, "%s/%s.rrd", rrd_conf.output_dir, name);
if (!(fp = fopen(file, "r"))) {
return 0;
}
fclose(fp);
return 1;
}
unsigned int
rrd_ignore_server(char *servername)
{
unsigned int i;
if(rrd_conf.ignore_servers)
{
for (i = 0; i < rrd_conf.ignore_servers->used; i++)
{
if(!irccasecmp(servername, rrd_conf.ignore_servers->list[i])) {
return 1;
}
}
}
return 0;
}
void
frput(FILE *fp, const char *str, ...)
{
va_list arg_list;
unsigned char buffer[MAXLEN];
int pos;
buffer[0] = '\0';
va_start(arg_list, str);
pos = vsnprintf(buffer, MAXLEN - 2, str, arg_list);
if (pos < 0 || pos > (MAXLEN - 2)) pos = MAXLEN - 2;
buffer[pos++] = '\n';
buffer[pos] = 0;
va_end(arg_list);
fputs(buffer, fp);
}
void
collect_graphs(void)
{
dict_iterator_t it;
char str[MAXLEN];
if(!rrd_exists(rrd_conf.servername)) {
sprintf(str, "%s create %s/%s.rrd DS:ircops:GAUGE:600:U:U DS:users:GAUGE:600:U:U DS:channels:GAUGE:600:U:U DS:invisible:GAUGE:600:U:U DS:normal:GAUGE:600:U:U DS:servers:GAUGE:600:U:U RRA:AVERAGE:0.5:1:600 RRA:AVERAGE:0.5:24:775 RRA:AVERAGE:0.5:288:797 RRA:MAX:0.5:1:600 RRA:MAX:0.5:6:700 RRA:MAX:0.5:24:775 RRA:MAX:0.5:288:797", rrd_conf.rrdtool_path, rrd_conf.output_dir, rrd_conf.servername);
}
else {
sprintf(str, "%s update %s/%s.rrd N:%d:%d:%d:%d:%d:%d", rrd_conf.rrdtool_path, rrd_conf.output_dir, rrd_conf.servername, curr_opers.used, dict_size(clients), dict_size(channels), invis_clients, (dict_size(clients) - invis_clients), dict_size(servers));
}
system(str);
for (it = dict_first(servers); it; it = iter_next(it))
{
struct server *server = iter_data(it);
if(rrd_ignore_server(server->name)) continue;
if(!rrd_exists(server->name)) {
// create
char str2[5000];
sprintf(str2, "%s create %s/%s.rrd DS:localusers:GAUGE:600:U:U DS:totalusers:GAUGE:600:U:U RRA:AVERAGE:0.5:1:600 RRA:AVERAGE:0.5:6:700 RRA:AVERAGE:0.5:24:775 RRA:AVERAGE:0.5:288:797 RRA:MAX:0.5:1:600 RRA:MAX:0.5:6:700 RRA:MAX:0.5:24:775 RRA:MAX:0.5:288:797 >> /dev/null", rrd_conf.rrdtool_path, rrd_conf.output_dir, server->name);
system(str2);
}
else {
// update
sprintf(str, "%s update %s/%s.rrd N:%d:%d >> /dev/null", rrd_conf.rrdtool_path, rrd_conf.output_dir, server->name, server->clients, dict_size(clients));
system(str);
}
}
timeq_add(now + 10, make_graphs, NULL);
}
static void
get_data(UNUSED_ARG(void *data))
{
collect_graphs();
if(rrd_conf.active && rrd_conf.update_duration) {
timeq_add(now + rrd_conf.update_duration, get_data, NULL);
}
}
void
html_header(FILE *fp, int defaulth, char *title)
{
time_t _time = now;
frput(fp, "<HTML>\n");
frput(fp, "<head>\n");
if(defaulth || !title) {
frput(fp, " <title>Stats for %s on %s</title>\n", rrd_conf.servername, ctime(&_time));
}
else {
frput(fp, " <title>%s</title>\n", title);
}
frput(fp, "<meta http-equiv=\"Refresh\" content=\"%ld\">\n", rrd_conf.update_duration);
frput(fp, "<meta name=\"Generator\" content=\"%s\">\n", MSG_VERSIONNB);
frput(fp, "<style type=\"text/css\" title=\"Defs\">\n");
frput(fp, "H2 {color:black; font-family:\"Helvetica\"; font-style:normal; font-weight:bold; font-size:16pt}\n");
frput(fp, ".normal {color:black; font-family:\"Helvetica\"; font-style:normal}\n");
frput(fp, "</style>\n");
frput(fp, "</head>\n");
frput(fp, "<body bgcolor=\"white\" link=\"blue\">\n");
frput(fp, "<center>\n");
}
void
html_footer(FILE *fp)
{
frput(fp, " <br><br><hr>\n");
frput(fp, " <font class=\"normal\">\n");
frput(fp, " This page was built using <a href=\"http://wstats.sourceforge.net\">%s</a> by <a href=\"mailto:wa...@wh...\">Martijn Smit</a><br>\n", MSG_VERSIONNB);
frput(fp, " PNG images created with <a href=\"http://www.rrdtool.org\">RRDTool</a> by Tobi Oetiker\n");
frput(fp, " </font><br>\n");
frput(fp, "</CENTER>\n");
frput(fp, "</BODY>\n");
frput(fp, "</HTML>\n");
}
void
format_html_index()
{
time_t _time = now;
dict_iterator_t it;
char file[125];
FILE *fp;
sprintf(file, "%s/index.html", rrd_conf.output_dir);
if(!(fp = fopen(file, "w"))) {
log_module(RRD_LOG, LOG_ERROR, "Couldn't open %s!", file);
return;
}
html_header(fp, 1, NULL);
frput(fp, "<h2><p align=\"center\">Stats for <b>%s</b></h2>\n", rrd_conf.servername);
frput(fp, "<font class=\"normal\">Page build at %s</font><br><hr>\n", ctime(&_time));
for (it = dict_first(servers); it; it = iter_next(it))
{
struct server *server = iter_data(it);
if(rrd_ignore_server(server->name)) continue;
if(rrd_exists(server->name)) {
frput(fp, " <a href=\"%s.html\"><img src=\"%s-day.png\" border=\"0\"></a><br><br>\n", server->name, server->name);
}
}
frput(fp, " <a href=\"network.html\"><img src=\"network-day.png\" border=\"0\"></a><br><br>\n");
frput(fp, " <a href=\"servers.html\"><img src=\"servers-day.png\" border=\"0\"></a><br><br>\n");
html_footer(fp);
fclose(fp);
}
void
format_html_network()
{
time_t _time = now;
char file[125];
FILE *fp;
sprintf(file, "%s/network.html", rrd_conf.output_dir);
if(!(fp = fopen(file, "w"))) {
log_module(RRD_LOG, LOG_ERROR, "Couldn't open %s!", file);
return;
}
html_header(fp, 1, NULL);
frput(fp, "<h2><p align=\"center\">Stats for <b>%s</b></h2>\n", rrd_conf.servername);
frput(fp, "<font class=\"normal\">Page build at %s</font><br><hr>\n", ctime(&_time));
frput(fp, " <img src=\"network-day.png\"><br><br>\n");
frput(fp, " <img src=\"network-week.png\"><br><br>\n");
frput(fp, " <img src=\"network-month.png\"><br><br>\n");
frput(fp, " <img src=\"network-year.png\">\n");
html_footer(fp);
fclose(fp);
}
void
format_html_servers()
{
time_t _time = now;
char file[125];
FILE *fp;
sprintf(file, "%s/servers.html", rrd_conf.output_dir);
if(!(fp = fopen(file, "w"))) {
log_module(RRD_LOG, LOG_ERROR, "Couldn't open %s!", file);
return;
}
html_header(fp, 1, NULL);
frput(fp, "<h2><p align=\"center\">Servers and Ircops on <b>%s</b></h2>\n", rrd_conf.servername);
frput(fp, "<font class=\"normal\">Page build at %s</font><br><hr>\n", ctime(&_time));
frput(fp, " <img src=\"servers-day.png\"><br><br>\n");
frput(fp, " <img src=\"servers-week.png\"><br><br>\n");
frput(fp, " <img src=\"servers-month.png\"><br><br>\n");
frput(fp, " <img src=\"servers-year.png\">\n");
html_footer(fp);
fclose(fp);
}
void
format_html_local_servers()
{
char file[512], str[512];
time_t _time = now;
dict_iterator_t it;
FILE *fp;
for (it = dict_first(servers); it; it = iter_next(it))
{
struct server *server = iter_data(it);
if(rrd_ignore_server(server->name)) continue;
if(rrd_exists(server->name)) {
sprintf(file, "%s/%s.html", rrd_conf.output_dir, server->name);
if(!(fp = fopen(file, "w"))) {
log_module(RRD_LOG, LOG_ERROR, "Couldn't open %s!", file);
return;
}
sprintf(str, "Users connected to %s", server->name);
html_header(fp, 0, str);
frput(fp, "<h2><p align=\"center\">Stats for <b>%s</b></h2>\n", server->name);
frput(fp, "<font class=\"normal\">Page build at %s</font><br><hr>\n", ctime(&_time));
frput(fp, " <img src=\"%s-day.png\"><br><br>\n", server->name);
frput(fp, " <img src=\"%s-week.png\"><br><br>\n", server->name);
frput(fp, " <img src=\"%s-month.png\"><br><br>\n", server->name);
frput(fp, " <img src=\"%s-year.png\">\n", server->name);
html_footer(fp);
fclose(fp);
}
}
}
void
format_graph_servers()
{
char str[5000];
sprintf(str, "%s graph %s/servers-day.png %s -a PNG -s -1day -v \"servers/ircops\" -t \"Servers and ircops online (1 day)\" DEF:totalservers=%s/%s.rrd:servers:AVERAGE DEF:maxservers=%s/%s.rrd:servers:MAX DEF:totalircops=%s/%s.rrd:ircops:AVERAGE DEF:maxircops=%s/%s.rrd:ircops:MAX DEF:users=%s/%s.rrd:users:AVERAGE \"CDEF:copsperserver=totalircops,totalservers,/\" \"CDEF:percircops=totalircops,100,*,users,/\" AREA:totalservers#FF0000:\"Servers online\" LINE2:totalircops#000000:\"IRCops online\\l\" GPRINT:totalservers:AVERAGE:'Servers -> Average\\: %%.lf' GPRINT:maxservers:MAX:'Max\\: %%.lf' GPRINT:totalservers:LAST:'Current\\: %%.lf\\l' GPRINT:totalircops:AVERAGE:'IRCops -> Average\\: %%.lf' GPRINT:maxircops:MAX:'Max\\: %%.lf' GPRINT:totalircops:LAST:'Current\\: %%.lf\\l' GPRINT:copsperserver:LAST:'IRCops per server\\: %%.2lf\\l' GPRINT:percircops:LAST:'Ircops\\: %%.2lf%%%% of total users\\l' >> /dev/null", rrd_conf.rrdtool_path, rrd_conf.output_dir, DEF_COLORS, rrd_conf.out!
put_dir, rrd_conf.servername, rrd_conf.output_dir, rrd_conf.servername, rrd_conf.output_dir, rrd_conf.servername, rrd_conf.output_dir, rrd_conf.servername, rrd_conf.output_dir, rrd_conf.servername);
system(str);
sprintf(str, "%s graph %s/servers-week.png %s -a PNG -s -1week -v \"servers/ircops\" -t \"Servers and ircops on line (1 week)\" DEF:totalservers=%s/%s.rrd:servers:AVERAGE DEF:maxservers=%s/%s.rrd:servers:MAX DEF:totalircops=%s/%s.rrd:ircops:AVERAGE DEF:maxircops=%s/%s.rrd:ircops:MAX DEF:users=%s/%s.rrd:users:AVERAGE AREA:totalservers#FF0000:\"Servers on line\" LINE2:totalircops#FF6600:\"IRCops on line\\l\" GPRINT:totalservers:AVERAGE:'Servers -> Average\\: %%.lf' GPRINT:maxservers:MAX:'Max\\: %%.lf' GPRINT:totalservers:LAST:'Current\\: %%.lf\\l' GPRINT:totalircops:AVERAGE:'IRCops -> Average\\: %%.lf' GPRINT:maxircops:MAX:'Max\\: %%.lf' GPRINT:totalircops:LAST:'Current\\: %%.lf\\l' >> /dev/null", rrd_conf.rrdtool_path, rrd_conf.output_dir, DEF_COLORS, rrd_conf.output_dir, rrd_conf.servername, rrd_conf.output_dir, rrd_conf.servername, rrd_conf.output_dir, rrd_conf.servername, rrd_conf.output_dir, rrd_conf.servername, rrd_conf.output_dir, rrd_conf.servername);
system(str);
sprintf(str, "%s graph %s/servers-month.png %s -a PNG -s -1month -v \"servers/ircops\" -t \"Servers and ircops on line (1 month)\" DEF:totalservers=%s/%s.rrd:servers:AVERAGE DEF:maxservers=%s/%s.rrd:servers:MAX DEF:totalircops=%s/%s.rrd:ircops:AVERAGE DEF:maxircops=%s/%s.rrd:ircops:MAX DEF:users=%s/%s.rrd:users:AVERAGE AREA:totalservers#FF0000:\"Servers on line\" LINE2:totalircops#FF6600:\"IRCops on line\\l\" GPRINT:totalservers:AVERAGE:'Servers -> Average\\: %%.lf' GPRINT:maxservers:MAX:'Max\\: %%.lf' GPRINT:totalservers:LAST:'Current\\: %%.lf\\l' GPRINT:totalircops:AVERAGE:'IRCops -> Average\\: %%.lf' GPRINT:maxircops:MAX:'Max\\: %%.lf' GPRINT:totalircops:LAST:'Current\\: %%.lf\\l' >> /dev/null", rrd_conf.rrdtool_path, rrd_conf.output_dir, DEF_COLORS, rrd_conf.output_dir, rrd_conf.servername, rrd_conf.output_dir, rrd_conf.servername, rrd_conf.output_dir, rrd_conf.servername, rrd_conf.output_dir, rrd_conf.servername, rrd_conf.output_dir, rrd_conf.servername);
system(str);
sprintf(str, "%s graph %s/servers-year.png %s -a PNG -s -1year -v \"servers/ircops\" -t \"Servers and ircops on line (1 year)\" DEF:totalservers=%s/%s.rrd:servers:AVERAGE DEF:maxservers=%s/%s.rrd:servers:MAX DEF:totalircops=%s/%s.rrd:ircops:AVERAGE DEF:maxircops=%s/%s.rrd:ircops:MAX DEF:users=%s/%s.rrd:users:AVERAGE AREA:totalservers#FF0000:\"Servers on line\" LINE2:totalircops#FF6600:\"IRCops on line\\l\" GPRINT:totalservers:AVERAGE:'Servers -> Average\\: %%.lf' GPRINT:maxservers:MAX:'Max\\: %%.lf' GPRINT:totalservers:LAST:'Current\\: %%.lf\\l' GPRINT:totalircops:AVERAGE:'IRCops -> Average\\: %%.lf' GPRINT:maxircops:MAX:'Max\\: %%.lf' GPRINT:totalircops:LAST:'Current\\: %%.lf\\l' >> /dev/null", rrd_conf.rrdtool_path, rrd_conf.output_dir, DEF_COLORS, rrd_conf.output_dir, rrd_conf.servername, rrd_conf.output_dir, rrd_conf.servername, rrd_conf.output_dir, rrd_conf.servername, rrd_conf.output_dir, rrd_conf.servername, rrd_conf.output_dir, rrd_conf.servername);
system(str);
}
void
format_graph_network()
{
char str[5000];
sprintf(str, "%s graph %s/network-day.png %s -a PNG -h 200 -s -1day -v \"users/channels\" -t \"Users and channels in the network (1 day)\" DEF:users=%s/%s.rrd:users:AVERAGE DEF:channels=%s/%s.rrd:channels:AVERAGE \"CDEF:usersperchannel=users,channels,/\" DEF:invisible=%s/%s.rrd:invisible:AVERAGE DEF:normal=%s/%s.rrd:normal:AVERAGE \"CDEF:percinvisible=invisible,100,*,users,/\" \"CDEF:percnormal=normal,100,*,users,/\" AREA:users#FF0000:\"Users connected\" LINE2:channels#0000FF:\"Channels created\" LINE2:invisible#00FF00:\"Users +i\" LINE2:normal#000000:\"Users -i\" DEF:maxusers=%s/%s.rrd:users:MAX DEF:maxchannels=%s/%s.rrd:channels:MAX GPRINT:maxusers:MAX:'Users -> Max\\: %%.lf' GPRINT:users:AVERAGE:'Average\\: %%.lf' GPRINT:users:LAST:'Current\\: %%.lf\\l' GPRINT:maxchannels:MAX:'Channels -> Max\\: %%.lf' GPRINT:channels:AVERAGE:'Average\\: %%.lf' GPRINT:channels:LAST:'Current\\: %%.lf\\l' GPRINT:usersperchannel:LAST:'Users per channel\\: %%.2lf\\l' GPRINT:percinvisible:L!
AST:'Invisible (+i)\\: %%.2lf%%%% of total users\\l' GPRINT:percnormal:LAST:'Visible (-i)\\: %%.2lf%%%% of total users\\l' >> /dev/null", rrd_conf.rrdtool_path, rrd_conf.output_dir, DEF_COLORS, rrd_conf.output_dir, rrd_conf.servername, rrd_conf.output_dir, rrd_conf.servername, rrd_conf.output_dir, rrd_conf.servername, rrd_conf.output_dir, rrd_conf.servername, rrd_conf.output_dir, rrd_conf.servername, rrd_conf.output_dir, rrd_conf.servername);
system(str);
sprintf(str, "%s graph %s/network-week.png %s -a PNG -h 200 -s -1week -v \"users/channels\" -t \"Users and channels in the network (1 week)\" DEF:users=%s/%s.rrd:users:AVERAGE DEF:channels=%s/%s.rrd:channels:AVERAGE DEF:invisible=%s/%s.rrd:invisible:AVERAGE DEF:normal=%s/%s.rrd:normal:AVERAGE AREA:users#FF0000:\"Users connected\" LINE2:channels#0000FF:\"Channels created\" LINE2:invisible#00FF00:\"Users +i\" LINE2:normal#000000:\"Users -i\" DEF:maxusers=%s/%s.rrd:users:MAX DEF:maxchannels=%s/%s.rrd:channels:MAX GPRINT:maxusers:MAX:'Users -> Max\\: %%.lf' GPRINT:users:AVERAGE:'Average\\: %%.lf' GPRINT:users:LAST:'Current\\: %%.lf\\l' GPRINT:maxchannels:MAX:'Channels -> Max\\: %%.lf' GPRINT:channels:AVERAGE:'Average\\: %%.lf' GPRINT:channels:LAST:'Current\\: %%.lf\\l' >> /dev/null", rrd_conf.rrdtool_path, rrd_conf.output_dir, DEF_COLORS, rrd_conf.output_dir, rrd_conf.servername, rrd_conf.output_dir, rrd_conf.servername, rrd_conf.output_dir, rrd_conf.servername, rrd_conf.outp!
ut_dir, rrd_conf.servername, rrd_conf.output_dir, rrd_conf.servername, rrd_conf.output_dir, rrd_conf.servername);
system(str);
sprintf(str, "%s graph %s/network-month.png %s -a PNG -h 200 -s -1month -v \"users/channels\" -t \"Users and channels in the network (1 month)\" DEF:users=%s/%s.rrd:users:AVERAGE DEF:channels=%s/%s.rrd:channels:AVERAGE DEF:invisible=%s/%s.rrd:invisible:AVERAGE DEF:normal=%s/%s.rrd:normal:AVERAGE AREA:users#FF0000:\"Users connected\" LINE2:channels#0000FF:\"Channels created\" LINE2:invisible#00FF00:\"Users +i\" LINE2:normal#000000:\"Users -i\" DEF:maxusers=%s/%s.rrd:users:MAX DEF:maxchannels=%s/%s.rrd:channels:MAX GPRINT:maxusers:MAX:'Users -> Max\\: %%.lf' GPRINT:users:AVERAGE:'Average\\: %%.lf' GPRINT:users:LAST:'Current\\: %%.lf\\l' GPRINT:maxchannels:MAX:'Channels -> Max\\: %%.lf' GPRINT:channels:AVERAGE:'Average\\: %%.lf' GPRINT:channels:LAST:'Current\\: %%.lf\\l' >> /dev/null", rrd_conf.rrdtool_path, rrd_conf.output_dir, DEF_COLORS, rrd_conf.output_dir, rrd_conf.servername, rrd_conf.output_dir, rrd_conf.servername, rrd_conf.output_dir, rrd_conf.servername, rrd_conf.o!
utput_dir, rrd_conf.servername, rrd_conf.output_dir, rrd_conf.servername, rrd_conf.output_dir, rrd_conf.servername);
system(str);
sprintf(str, "%s graph %s/network-year.png %s -a PNG -h 200 -s -1year -v \"users/channels\" -t \"Users and channels in the network (1 year)\" DEF:users=%s/%s.rrd:users:AVERAGE DEF:channels=%s/%s.rrd:channels:AVERAGE DEF:invisible=%s/%s.rrd:invisible:AVERAGE DEF:normal=%s/%s.rrd:normal:AVERAGE AREA:users#FF0000:\"Users connected\" LINE2:channels#0000FF:\"Channels created\" LINE2:invisible#00FF00:\"Users +i\" LINE2:normal#000000:\"Users -i\" DEF:maxusers=%s/%s.rrd:users:MAX DEF:maxchannels=%s/%s.rrd:channels:MAX GPRINT:maxusers:MAX:'Users -> Max\\: %%.lf' GPRINT:users:AVERAGE:'Average\\: %%.lf' GPRINT:users:LAST:'Current\\: %%.lf\\l' GPRINT:maxchannels:MAX:'Channels -> Max\\: %%.lf' GPRINT:channels:AVERAGE:'Average\\: %%.lf' GPRINT:channels:LAST:'Current\\: %%.lf\\l' >> /dev/null", rrd_conf.rrdtool_path, rrd_conf.output_dir, DEF_COLORS, rrd_conf.output_dir, rrd_conf.servername, rrd_conf.output_dir, rrd_conf.servername, rrd_conf.output_dir, rrd_conf.servername, rrd_conf.outp!
ut_dir, rrd_conf.servername, rrd_conf.output_dir, rrd_conf.servername, rrd_conf.output_dir, rrd_conf.servername);
system(str);
}
void
format_graph_local_servers()
{
dict_iterator_t it;
char str[3000];
for (it = dict_first(servers); it; it = iter_next(it))
{
struct server *server = iter_data(it);
if(rrd_ignore_server(server->name)) continue;
if(rrd_exists(server->name)) {
sprintf(str, "%s graph %s/%s-day.png %s -a PNG -v \"local users\" -t \"Users connected to %s (1 day)\" DEF:lastglobal=%s/%s.rrd:totalusers:AVERAGE DEF:localusers=%s/%s.rrd:localusers:AVERAGE \"CDEF:perclocal=localusers,100,*,lastglobal,/\" AREA:localusers#FF0000:\"Users connected to %s\\l\" DEF:maxlocal=%s/%s.rrd:localusers:MAX GPRINT:maxlocal:MAX:'Users -> Max\\: %%.lf' GPRINT:localusers:AVERAGE:'Average\\: %%.lf' GPRINT:localusers:LAST:'Current\\: %%.lf\\l' GPRINT:perclocal:LAST:'Percentage\\: %s has %%.2lf%%%% of global users\\l' >> /dev/null", rrd_conf.rrdtool_path, rrd_conf.output_dir, server->name, DEF_COLORS, server->name, rrd_conf.output_dir, server->name, rrd_conf.output_dir, server->name, server->name, rrd_conf.output_dir, server->name, server->name);
system(str);
sprintf(str, "%s graph %s/%s-week.png %s -a PNG -s -1week -v \"local users\" -t \"Users connected to %s (1 week)\" DEF:localusers=%s/%s.rrd:localusers:AVERAGE AREA:localusers#FF0000:\"Users connected to %s\\l\" DEF:maxlocals=%s/%s.rrd:localusers:MAX GPRINT:maxlocals:MAX:'Users -> Max\\: %%.lf' GPRINT:localusers:AVERAGE:'Average\\: %%.lf' GPRINT:localusers:LAST:'Current\\: %%.lf users\\l' >> /dev/null", rrd_conf.rrdtool_path, rrd_conf.output_dir, server->name, DEF_COLORS, server->name, rrd_conf.output_dir, server->name, server->name, rrd_conf.output_dir, server->name);
system(str);
sprintf(str, "%s graph %s/%s-month.png %s -a PNG -s -1month -v \"local users\" -t \"Users connected to %s (1 month)\" DEF:localusers=%s/%s.rrd:localusers:AVERAGE AREA:localusers#FF0000:\"Users connected to %s\\l\" DEF:maxlocals=%s/%s.rrd:localusers:MAX GPRINT:maxlocals:MAX:'Users -> Max\\: %%.lf' GPRINT:localusers:AVERAGE:'Average\\: %%.lf' GPRINT:localusers:LAST:'Current\\: %%.lf users\\l' >> /dev/null", rrd_conf.rrdtool_path, rrd_conf.output_dir, server->name, DEF_COLORS, server->name, rrd_conf.output_dir, server->name, server->name, rrd_conf.output_dir, server->name);
system(str);
sprintf(str, "%s graph %s/%s-year.png %s -a PNG -s -1year -v \"local users\" -t \"Users connected to %s (1 year)\" DEF:localusers=%s/%s.rrd:localusers:AVERAGE AREA:localusers#FF0000:\"Users connected to %s\\l\" DEF:maxlocals=%s/%s.rrd:localusers:MAX GPRINT:maxlocals:MAX:'Users -> Max\\: %%.lf' GPRINT:localusers:AVERAGE:'Average\\: %%.lf' GPRINT:localusers:LAST:'Current\\: %%.lf users\\l' >> /dev/null", rrd_conf.rrdtool_path, rrd_conf.output_dir, server->name, DEF_COLORS, server->name, rrd_conf.output_dir, server->name, server->name, rrd_conf.output_dir, server->name);
system(str);
}
}
}
static void
make_graphs(UNUSED_ARG(void *data))
{
format_html_index();
format_html_network();
format_html_servers();
format_html_local_servers();
format_graph_servers();
format_graph_network();
format_graph_local_servers();
}
static void
rrd_conf_read(void)
{
struct record_data *rd;
dict_t conf_node;
const char *str;
rd = conf_get_node(RRD_CONF_NAME);
if (!rd || rd->type != RECDB_OBJECT) {
log_module(RRD_LOG, LOG_ERROR, "config node `%s' is missing or has wrong type", RRD_CONF_NAME);
return;
}
conf_node = rd->d.object;
str = database_get_data(conf_node, KEY_ACTIVE, RECDB_QSTRING);
rrd_conf.active = enabled_string(str) ? 1 : 0;
str = database_get_data(conf_node, KEY_GRAPH_UPDATE, RECDB_QSTRING);
rrd_conf.update_duration = str ? ParseInterval(str) : 900;
str = database_get_data(conf_node, KEY_SERVERNAME, RECDB_QSTRING);
rrd_conf.servername = str ? strdup(str) : "bad.config";
str = database_get_data(conf_node, KEY_OUTPUTDIR, RECDB_QSTRING);
if(str) {
rrd_conf.output_dir = strdup(str);
}
else {
log_module(RRD_LOG, LOG_ERROR, "No output directory defined! Deactivating rrdgraphs module");
rrd_conf.active = 0;
}
free_string_list(rrd_conf.ignore_servers);
rrd_conf.ignore_servers = database_get_data(conf_node, KEY_IGNORE_SERVERS, RECDB_STRING_LIST);
if(rrd_conf.ignore_servers) {
rrd_conf.ignore_servers = string_list_copy(rrd_conf.ignore_servers);
}
str = database_get_data(conf_node, KEY_RRD_PATH, RECDB_QSTRING);
if(str) {
rrd_conf.rrdtool_path = strdup(str);
if(!check_rrdtool(rrd_conf.rrdtool_path)) {
rrd_conf.active = 0;
}
}
else {
log_module(RRD_LOG, LOG_ERROR, "RRDTool path not defined! Deactivating rrdgraphs module");
rrd_conf.active = 0;
}
}
void
rrd_module_init(void)
{
RRD_LOG = log_register_type("RRD", "file:rrd.log");
rrd_module = module_register("RRD", RRD_LOG, NULL, NULL);
conf_register_reload(rrd_conf_read);
if(rrd_conf.active && rrd_conf.update_duration) {
timeq_add(now + rrd_conf.update_duration, get_data, NULL);
}
}
Index: rrdgraph.h
====================================================================
/* rrdgraph.h - RRDTool graphs
* Copyright 2004 Martijn Smit, WhatNET Coder-Com
*
* 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. Important limitations are
* listed in the COPYING file that accompanies this software.
*
* 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
*
* $Id: rrdgraph.h,v 1.1 2004/06/12 11:32:50 wasted Exp $
*/
void rrd_module_init(void);
void collect_graphs(void);
Index: Makefile.am
===================================================================
RCS file: /home/cvs/wstats/wStats-pgsql/src/Makefile.am,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -r1.1 -r1.2
--- Makefile.am 10 Apr 2004 16:57:01 -0000 1.1
+++ Makefile.am 12 Jun 2004 11:32:49 -0000 1.2
@@ -25,6 +25,7 @@
statserv.c statserv.h \
proto-p10.c proto.h \
recdb.c recdb.h \
+ rrdgraph.c rrdgraph.h \
timeq.c timeq.h \
tools.c
Index: Makefile.in
===================================================================
RCS file: /home/cvs/wstats/wStats-pgsql/src/Makefile.in,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -r1.1 -r1.2
--- Makefile.in 10 Apr 2004 16:57:01 -0000 1.1
+++ Makefile.in 12 Jun 2004 11:32:49 -0000 1.2
@@ -108,6 +108,7 @@
statserv.c statserv.h \
proto-p10.c proto.h \
recdb.c recdb.h \
+ rrdgraph.c rrdgraph.h \
timeq.c timeq.h \
tools.c
@@ -123,7 +124,8 @@
hash.$(OBJEXT) heap.$(OBJEXT) helpfile.$(OBJEXT) \
ioset.$(OBJEXT) log.$(OBJEXT) main.$(OBJEXT) modcmd.$(OBJEXT) \
pgsql.$(OBJEXT) statserv.$(OBJEXT) proto-p10.$(OBJEXT) \
- recdb.$(OBJEXT) timeq.$(OBJEXT) tools.$(OBJEXT)
+ recdb.$(OBJEXT) rrdgraph.$(OBJEXT) timeq.$(OBJEXT) \
+ tools.$(OBJEXT)
wstats_OBJECTS = $(am_wstats_OBJECTS)
wstats_LDFLAGS =
@@ -141,8 +143,8 @@
@AMDEP_TRUE@ ./$(DEPDIR)/log.Po ./$(DEPDIR)/main.Po \
@AMDEP_TRUE@ ./$(DEPDIR)/modcmd.Po ./$(DEPDIR)/pgsql.Po \
@AMDEP_TRUE@ ./$(DEPDIR)/proto-p10.Po ./$(DEPDIR)/recdb.Po \
-@AMDEP_TRUE@ ./$(DEPDIR)/statserv.Po ./$(DEPDIR)/timeq.Po \
-@AMDEP_TRUE@ ./$(DEPDIR)/tools.Po
+@AMDEP_TRUE@ ./$(DEPDIR)/rrdgraph.Po ./$(DEPDIR)/statserv.Po \
+@AMDEP_TRUE@ ./$(DEPDIR)/timeq.Po ./$(DEPDIR)/tools.Po
COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
$(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
CCLD = $(CC)
@@ -210,6 +212,7 @@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pgsql.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/proto-p10.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/recdb.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/rrdgraph.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/statserv.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/timeq.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tools.Po@am__quote@
Index: main.c
===================================================================
RCS file: /home/cvs/wstats/wStats-pgsql/src/main.c,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -r1.1 -r1.2
--- main.c 10 Apr 2004 16:57:06 -0000 1.1
+++ main.c 12 Jun 2004 11:32:49 -0000 1.2
@@ -18,7 +18,7 @@
* wStats is derrived from srvx (http://srvx.net), everything in here that's
* original srvx code, Copyrighted 2000-2003 srvx Development Team.
*
- * $Id: main.c,v 1.1 2004/04/10 16:57:06 wasted Exp $
+ * $Id: main.c,v 1.2 2004/06/12 11:32:49 wasted Exp $
*/
#define PID_FILE "wstats.pid"
@@ -28,6 +28,7 @@
#include "ioset.h"
#include "modcmd.h"
#include "pgsql.h"
+#include "rrdgraph.h"
#include "timeq.h"
#include "statserv.h"
@@ -449,6 +450,7 @@
if (info) init_statserv(info);
pgsql_module_init();
+ rrd_module_init();
}
#ifdef HAVE_SYS_RESOURCE_H
Index: messages.h
===================================================================
RCS file: /home/cvs/wstats/wStats-pgsql/src/messages.h,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -r1.1 -r1.2
--- messages.h 10 Apr 2004 16:57:08 -0000 1.1
+++ messages.h 12 Jun 2004 11:32:49 -0000 1.2
@@ -18,13 +18,15 @@
* wStats is derrived from srvx (http://srvx.net), everything in here that's
* original srvx code, Copyrighted 2000-2003 srvx Development Team.
*
- * $Id: messages.h,v 1.1 2004/04/10 16:57:08 wasted Exp $
+ * $Id: messages.h,v 1.2 2004/06/12 11:32:49 wasted Exp $
*/
#ifndef _MESSAGES_H_
#define _MESSAGES_H_
#define MSG_VERSION "$b"PACKAGE_STRING"$b, Built: " __DATE__ ", " __TIME__"."
+// No Bold version.
+#define MSG_VERSIONNB PACKAGE_STRING", Built: " __DATE__ ", " __TIME__"."
#define MSG_SERVICE_PRIVILEGED "$b%s$b is a privileged service."
#define MSG_NOT_A_SERVICE "$b%s$b is not a service bot."
#define MSG_COMMAND_UNKNOWN "$b%s$b is an unknown command."
Index: statserv.c
===================================================================
RCS file: /home/cvs/wstats/wStats-pgsql/src/statserv.c,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -r1.1 -r1.2
--- statserv.c 10 Apr 2004 16:57:07 -0000 1.1
+++ statserv.c 12 Jun 2004 11:32:50 -0000 1.2
@@ -16,7 +16,7 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
- * $Id: statserv.c,v 1.1 2004/04/10 16:57:07 wasted Exp $
+ * $Id: statserv.c,v 1.2 2004/06/12 11:32:50 wasted Exp $
*/
#include "conf.h"
@@ -24,6 +24,7 @@
#include "modcmd.h"
#include "pgsql.h"
#include "statserv.h"
+#include "rrdgraph.h"
#include "timeq.h"
#ifdef HAVE_SYS_TIMES_H
@@ -79,6 +80,7 @@
#define MSG_RAW_PARSE_ERROR "Error parsing raw line (not dumping to uplink)."
#define MSG_UPLINK_START "Uplink $b%s$b:"
#define MSG_NO_SUCH_STATS "No such stats type $b%s$b."
+#define MSG_RRDUPDATED "RRD graphs are being updated."
#define MAX_CHANNELS_WHOIS 50
@@ -95,7 +97,7 @@
unsigned char trigger_char;
} statserv_conf;
-const char *SSMSG_VERSION_ID = "$Id: statserv.c,v 1.1 2004/04/10 16:57:07 wasted Exp $";
+const char *SSMSG_VERSION_ID = "$Id: statserv.c,v 1.2 2004/06/12 11:32:50 wasted Exp $";
#define statserv_notice(target, format...) send_message(target, statserv, ## format)
#define statserv_debug(format...) do { if (statserv_conf.debug_channel) send_channel_notice(statserv_conf.debug_channel, statserv, ## format); } while (0)
@@ -600,6 +602,13 @@
statserv_notice(user, MSG_NO_SUCH_STATS, argv[1]);
return 0;
}
+
+static STATSERV_FUNC(cmd_rrdupdate)
+{
+ collect_graphs();
+ statserv_notice(user, MSG_RRDUPDATED);
+ return 1;
+}
static STATSERV_FUNC(cmd_dump)
{
@@ -742,6 +751,7 @@
modcmd_register(statserv_module, "REHASH", cmd_rehash, 1);
modcmd_register(statserv_module, "RESTART", cmd_restart, 1);
modcmd_register(statserv_module, "STATS", cmd_stats, 2);
+ modcmd_register(statserv_module, "RRDUPDATE", cmd_rrdupdate, 1);
modcmd_register(statserv_module, "UPTIME", cmd_uptime, 1);
modcmd_register(statserv_module, "VERSION", cmd_version, 1);
modcmd_register(statserv_module, "WHOIS", cmd_whois, 2);
|