diff --git a/src/damon.c b/src/damon.c index ba64157..8a85729 100644 --- a/src/damon.c +++ b/src/damon.c @@ -74,7 +74,7 @@ static void _damon_destroy(DaMon * damon); static int _damon_perror(char const * message, int error); -static int _damon_update(DaMon * damon, char const * filename, +static int _damon_update(DaMon * damon, RRDType type, char const * filename, int args_cnt, ...); @@ -198,7 +198,7 @@ static int _refresh_uptime(AppClient * ac, Host * host, char * rrd) if(appclient_call(ac, (void **)&ret, "uptime") != 0) return error_print(PROGNAME); sprintf(rrd, "%s%c%s", host->hostname, DAMON_SEP, "uptime.rrd"); - _damon_update(host->damon, rrd, 1, ret); + _damon_update(host->damon, RRDTYPE_UNKNOWN, rrd, 1, ret); return 0; } @@ -213,7 +213,8 @@ static int _refresh_load(AppClient * ac, Host * host, char * rrd) if(res != 0) return 0; sprintf(rrd, "%s%c%s", host->hostname, DAMON_SEP, "load.rrd"); - _damon_update(host->damon, rrd, 3, load[0], load[1], load[2]); + _damon_update(host->damon, RRDTYPE_LOAD, rrd, 3, + load[0], load[1], load[2]); return 0; } @@ -224,7 +225,7 @@ static int _refresh_procs(AppClient * ac, Host * host, char * rrd) if(appclient_call(ac, (void **)&res, "procs") != 0) return 1; sprintf(rrd, "%s%c%s", host->hostname, DAMON_SEP, "procs.rrd"); - _damon_update(host->damon, rrd, 1, res); + _damon_update(host->damon, RRDTYPE_UNKNOWN, rrd, 1, res); return 0; } @@ -237,7 +238,8 @@ static int _refresh_ram(AppClient * ac, Host * host, char * rrd) &ram[3]) != 0) return 1; sprintf(rrd, "%s%c%s", host->hostname, DAMON_SEP, "ram.rrd"); - _damon_update(host->damon, rrd, 4, ram[0], ram[1], ram[2], ram[3]); + _damon_update(host->damon, RRDTYPE_UNKNOWN, rrd, 4, + ram[0], ram[1], ram[2], ram[3]); return 0; } @@ -249,7 +251,7 @@ static int _refresh_swap(AppClient * ac, Host * host, char * rrd) if(appclient_call(ac, (void **)&res, "swap", &swap[0], &swap[1]) != 0) return 1; sprintf(rrd, "%s%c%s", host->hostname, DAMON_SEP, "swap.rrd"); - _damon_update(host->damon, rrd, 2, swap[0], swap[1]); + _damon_update(host->damon, RRDTYPE_UNKNOWN, rrd, 2, swap[0], swap[1]); return 0; } @@ -260,7 +262,7 @@ static int _refresh_users(AppClient * ac, Host * host, char * rrd) if(appclient_call(ac, (void **)&res, "users") != 0) return 1; sprintf(rrd, "%s%c%s", host->hostname, DAMON_SEP, "users.rrd"); - _damon_update(host->damon, rrd, 1, res); + _damon_update(host->damon, RRDTYPE_UNKNOWN, rrd, 1, res); return 0; } @@ -288,7 +290,7 @@ static int _ifaces_if(AppClient * ac, Host * host, char * rrd, iface) != 0) return 1; sprintf(rrd, "%s%c%s%s", host->hostname, DAMON_SEP, iface, ".rrd"); - _damon_update(host->damon, rrd, 2, res[0], res[1]); + _damon_update(host->damon, RRDTYPE_UNKNOWN, rrd, 2, res[0], res[1]); return 0; } @@ -314,7 +316,7 @@ static int _vols_vol(AppClient * ac, Host * host, char * rrd, char * vol) != 0) return 1; sprintf(rrd, "%s%s%s", host->hostname, vol, ".rrd"); /* FIXME */ - _damon_update(host->damon, rrd, 2, res[0], res[1]); + _damon_update(host->damon, RRDTYPE_UNKNOWN, rrd, 2, res[0], res[1]); return 0; } @@ -512,7 +514,7 @@ static int _damon_perror(char const * message, int ret) /* damon_update */ -static int _damon_update(DaMon * damon, char const * filename, +static int _damon_update(DaMon * damon, RRDType type, char const * filename, int args_cnt, ...) { int ret; @@ -523,7 +525,7 @@ static int _damon_update(DaMon * damon, char const * filename, == NULL) return -1; va_start(args, args_cnt); - ret = rrd_updatev(RRDTYPE_UNKNOWN, path, args_cnt, args); + ret = rrd_updatev(type, path, args_cnt, args); va_end(args); string_delete(path); return ret; diff --git a/src/rrd.c b/src/rrd.c index c72a1aa..b58f196 100644 --- a/src/rrd.c +++ b/src/rrd.c @@ -15,6 +15,7 @@ +#include #include #include #include @@ -28,6 +29,18 @@ #ifndef RRDTOOL # define RRDTOOL "rrdtool" #endif +#ifndef RRD_XFF +# define RRD_XFF "0.5" +#endif +#ifndef RRD_AVERAGE_DAY +# define RRD_AVERAGE_DAY "RRA:AVERAGE:" RRD_XFF ":1:288" +#endif +#ifndef RRD_AVERAGE_WEEK +# define RRD_AVERAGE_WEEK "RRA:AVERAGE:" RRD_XFF ":2:1008" +#endif +#ifndef RRD_AVERAGE_4WEEK +# define RRD_AVERAGE_4WEEK "RRA:AVERAGE:" RRD_XFF ":8:1008" +#endif /* RRD */ @@ -35,10 +48,47 @@ /* prototypes */ static int _rrd_exec(char * argv[]); static int _rrd_perror(char const * message, int ret); +static char * _rrd_timestamp(void); /* public */ /* functions */ +/* rrd_create */ +int rrd_create(RRDType type, char const * filename) +{ + int ret; + char * argv[16] = { RRDTOOL, "create", NULL, "--start", NULL, NULL }; + + switch(type) + { + case RRDTYPE_LOAD: + argv[5] = "--step"; + argv[6] = "300"; + argv[7] = "DS:load1:GAUGE:600:0:U"; + argv[8] = "DS:load5:GAUGE:600:0:U"; + argv[9] = "DS:load15:GAUGE:600:0:U"; + argv[10] = RRD_AVERAGE_DAY; + argv[11] = RRD_AVERAGE_WEEK; + argv[12] = RRD_AVERAGE_4WEEK; + argv[13] = NULL; + break; + default: + /* FIXME implement */ + return -1; + } + argv[2] = string_new(filename); + argv[4] = _rrd_timestamp(); + /* create the database */ + if(argv[2] != NULL && argv[4] != NULL) + ret = _rrd_exec(argv); + else + ret = -1; + string_delete(argv[4]); + string_delete(argv[2]); + return ret; +} + + /* rrd_update */ int rrd_update(RRDType type, char const * filename, int args_cnt, ...) { @@ -55,6 +105,7 @@ int rrd_update(RRDType type, char const * filename, int args_cnt, ...) /* rrd_updatev */ int rrd_updatev(RRDType type, char const * filename, int args_cnt, va_list args) { + struct stat st; char * argv[] = { RRDTOOL, "update", NULL, NULL, NULL }; struct timeval tv; size_t s; @@ -65,6 +116,14 @@ int rrd_updatev(RRDType type, char const * filename, int args_cnt, va_list args) #ifdef DEBUG fprintf(stderr, "DEBUG: %s(%u, \"%s\")\n", __func__, type, filename); #endif + /* create the database if not available */ + if(stat(filename, &st) != 0) + { + if(errno != ENOENT) + return _rrd_perror(filename, -errno); + if(rrd_create(type, filename) != 0) + return -1; + } /* prepare the parameters */ if(gettimeofday(&tv, NULL) != 0) return _rrd_perror("gettimeofday", -errno); @@ -126,3 +185,17 @@ static int _rrd_perror(char const * message, int ret) return error_set_code(ret, "%s%s%s", (message != NULL) ? message : "", (message != NULL) ? ": " : "", strerror(errno)); } + + +/* rrd_timestamp */ +static char * _rrd_timestamp(void) +{ + struct timeval tv; + + if(gettimeofday(&tv, NULL) != 0) + { + _rrd_perror("gettimeofday", -errno); + return NULL; + } + return string_new_format("%ld", tv.tv_sec); +} diff --git a/src/rrd.h b/src/rrd.h index 9f3b21a..864f86b 100644 --- a/src/rrd.h +++ b/src/rrd.h @@ -25,11 +25,14 @@ /* types */ typedef enum _RRDType { - RRDTYPE_UNKNOWN = 0 + RRDTYPE_UNKNOWN = 0, + RRDTYPE_LOAD } RRDType; /* functions */ +int rrd_create(RRDType type, char const * filename); + int rrd_update(RRDType type, char const * filename, int args_cnt, ...); int rrd_updatev(RRDType type, char const * filename, int args_cnt, va_list args);