]> git.itanic.dy.fi Git - rrdd/commitdiff
Add support for data logging
authorTimo Kokkonen <timo.t.kokkonen@iki.fi>
Sun, 6 Jan 2013 13:49:14 +0000 (15:49 +0200)
committerTimo Kokkonen <timo.t.kokkonen@iki.fi>
Sun, 6 Jan 2013 13:49:14 +0000 (15:49 +0200)
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 <timo.t.kokkonen@iki.fi>
config.c
rrdtool.c
rrdtool.h

index 939a8c6c0aac6a8c638fa776d95b1621ae30d509..68939bdc499edded4a32346ecfd1356f70f6c513 100644 (file)
--- 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;
        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");
 
        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;
        }
 
                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;
 }
 
        return 0;
 }
 
index 53db261354f4102f41f3bdccf4a77b2ee6ba542a..9539c6813289ba531b14474ce7a367b0e60b54e3 100644 (file)
--- a/rrdtool.c
+++ b/rrdtool.c
@@ -2,6 +2,7 @@
 
 #include <sys/types.h>
 #include <sys/stat.h>
 
 #include <sys/types.h>
 #include <sys/stat.h>
+#include <fcntl.h>
 #include <unistd.h>
 #include <string.h>
 
 #include <unistd.h>
 #include <string.h>
 
@@ -199,6 +200,62 @@ static int sanitize_rrd_update_data(char *data)
        return entries;
 }
 
        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;
 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);
                pr_info("Data: %s\n", data);
 
                sanitize_rrd_update_data(data + l);
+               write_to_logfile(rrd, data);
+
                pid = run(cmd, cmdline);
                harvest_zombies(pid);
        }
                pid = run(cmd, cmdline);
                harvest_zombies(pid);
        }
index ae0c507154911fe4293e3b90aa5f24554181d821..91fab9cfada4246e7f155a1aa7af12b949ff5add 100644 (file)
--- 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 */
 
        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 */
 };
        int     last_update;    /* When was the data last updated */
        const char *name;               /* Name of the database */
 };