From b75cf8a9fa8259c68cf2877ade4a7ae4bf1b497e Mon Sep 17 00:00:00 2001 From: Timo Kokkonen Date: Sun, 6 Jan 2013 15:49:14 +0200 Subject: [PATCH] Add support for data logging Add new configuration parameters "logfile" and "logfile_timestamp_fmt". Both of them are fed through strftime. The first one is used for creating log file name, the second one is the time stamp format in the beginning of each line. Neither of the options are mandatory. If no file name is given, no logging will be done. If no time stamp format is given, default of "%Y.%m.%d %H:%M " is used. Each line in the log file contains all the data elements given to rrdtool during updating the database. The format is altered slightly. The beginning of the line has got the time stamp, the beginning "N:" part is removed and all ':' characters are replaced with white space. Each entry is padded up to 12 characters with white space in order to make the log file entries nicely human readable. Signed-off-by: Timo Kokkonen --- config.c | 11 +++++++++++ rrdtool.c | 59 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ rrdtool.h | 3 +++ 3 files changed, 73 insertions(+) diff --git a/config.c b/config.c index 939a8c6..68939bd 100644 --- a/config.c +++ b/config.c @@ -232,6 +232,7 @@ static int parse_database(config_setting_t *rrd, struct rrd_database *db) config_setting_t *list, *str_list; const char *name, *parser = NULL, *filename, **parser_data; const char **pre_draw_cmd; + const char *logfile = NULL, *logfile_timestamp_fmt = NULL; if (!config_setting_lookup_string(rrd, "name", &name)) { pr_err("Database entry does not contain name\n"); @@ -273,6 +274,16 @@ static int parse_database(config_setting_t *rrd, struct rrd_database *db) db->pre_draw_cmd = (char *const *)pre_draw_cmd; } + config_setting_lookup_string(rrd, "logfile", &logfile); + if (logfile) + db->logfile = strdup(logfile); + + config_setting_lookup_string(rrd, "logfile_timestamp_fmt", + &logfile_timestamp_fmt); + if (logfile_timestamp_fmt) + db->logfile_timestamp_fmt = strdup(logfile_timestamp_fmt); + + return 0; } diff --git a/rrdtool.c b/rrdtool.c index 53db261..9539c68 100644 --- a/rrdtool.c +++ b/rrdtool.c @@ -2,6 +2,7 @@ #include #include +#include #include #include @@ -199,6 +200,62 @@ static int sanitize_rrd_update_data(char *data) return entries; } +static int write_to_logfile(struct rrd_database *rrd, const char *data) +{ + time_t t = time(NULL); + int fd, ret; + int spacing, i; + char filename[1024]; + char logstr[RRD_DATA_MAX_LEN * 2] = { 0 }; + const char *time_stamp_fmt = "%Y.%m.%d %H:%M "; + char *str_ptr; + + if (!rrd->logfile) + return 0; + + if (rrd->logfile_timestamp_fmt) + time_stamp_fmt = rrd->logfile_timestamp_fmt; + + strftime(filename, sizeof(filename), rrd->logfile, localtime(&t)); + + fd = open(filename, O_RDWR | O_APPEND | O_CREAT | O_CLOEXEC, 0644); + if (fd < 0) { + pr_err("Failed to open file %s for logging: %m\n", filename); + return -1; + } + + strftime(logstr, sizeof(logstr), time_stamp_fmt, localtime(&t)); + + str_ptr = logstr + strlen(logstr); + + data += 2; /* Skip the "N: part */ + spacing = 12; + + while (*data && str_ptr - logstr < sizeof(logstr) - 1) { + if (*data == ':') { + *str_ptr++ = ' '; + for (i = 0; i < spacing; i++) + *str_ptr++ = ' '; + spacing = 12; + data++; + continue; + } + + *str_ptr++ = *data++; + spacing--; + } + *str_ptr++ = '\n'; + *str_ptr++ = 0; + + ret = write(fd, logstr, strlen(logstr)); + if (ret < 0) + pr_err("Failed to write to logfile %s: %m\n", filename); + + close(fd); + + return ret < 0 ? ret : 0; +} + int rrdtool_update_data(struct rrd_database *rrd) { int pid; @@ -227,6 +284,8 @@ int rrdtool_update_data(struct rrd_database *rrd) pr_info("Data: %s\n", data); sanitize_rrd_update_data(data + l); + write_to_logfile(rrd, data); + pid = run(cmd, cmdline); harvest_zombies(pid); } diff --git a/rrdtool.h b/rrdtool.h index ae0c507..91fab9c 100644 --- a/rrdtool.h +++ b/rrdtool.h @@ -47,6 +47,9 @@ struct rrd_database { struct rrd_data_source *sources; /* These are currently only used */ struct rrd_archive *archives; /* generating new rrd database */ + const char *logfile; /* Name of a file where data can be logged */ + const char *logfile_timestamp_fmt; + int last_update; /* When was the data last updated */ const char *name; /* Name of the database */ }; -- 2.44.0