From: Florian Forster Date: Tue, 16 Jan 2007 08:42:35 +0000 (+0100) Subject: csv plugin: Added this plugin which writes to CSV files. X-Git-Tag: collectd-4.0.0~226 X-Git-Url: https://git.verplant.org/?a=commitdiff_plain;h=f5b4f424b9a0eb11c4cc98513971e1a3ddf40b3b;p=collectd.git csv plugin: Added this plugin which writes to CSV files. This is basically the old `logfile' functionality. --- diff --git a/configure.in b/configure.in index 6a0838bb..ac6e5c99 100644 --- a/configure.in +++ b/configure.in @@ -984,10 +984,10 @@ AC_COLLECTD([battery], [disable], [module], [battery statistics]) AC_COLLECTD([cpu], [disable], [module], [cpu usage statistics]) AC_COLLECTD([cpufreq], [disable], [module], [system cpu frequency statistics]) AC_COLLECTD([disk], [disable], [module], [disk/partition statistics]) +AC_COLLECTD([csv], [disable], [module], [csv output plugin]) AC_COLLECTD([df], [disable], [module], [df statistics]) AC_COLLECTD([dns], [disable], [module], [dns statistics]) AC_COLLECTD([email], [disable], [module], [email statistics]) -AC_COLLECTD([quota], [enable], [module], [quota statistics (experimental)]) AC_COLLECTD([hddtemp], [disable], [module], [hdd temperature statistics]) AC_COLLECTD([load], [disable], [module], [system load statistics]) AC_COLLECTD([mbmon], [disable], [module], [motherboard monitor statistics]) @@ -1038,6 +1038,7 @@ Configuration: battery . . . . . . $enable_battery cpu . . . . . . . . $enable_cpu cpufreq . . . . . . $enable_cpufreq + csv . . . . . . . . $enable_csv df . . . . . . . . $enable_df disk . . . . . . . $enable_disk dns . . . . . . . . $enable_dns diff --git a/src/Makefile.am b/src/Makefile.am index 4ea3be0e..55584191 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -128,6 +128,14 @@ collectd_LDADD += "-dlopen" cpufreq.la collectd_DEPENDENCIES += cpufreq.la endif +if BUILD_MODULE_CSV +pkglib_LTLIBRARIES += csv.la +csv_la_SOURCES = csv.c +csv_la_LDFLAGS = -module -avoid-version +collectd_LDADD += "-dlopen" csv.la +collectd_DEPENDENCIES += csv.la +endif + if BUILD_MODULE_DF pkglib_LTLIBRARIES += df.la df_la_SOURCES = df.c diff --git a/src/collectd.conf.in b/src/collectd.conf.in index 39d7f70c..c6ae3b36 100644 --- a/src/collectd.conf.in +++ b/src/collectd.conf.in @@ -26,6 +26,7 @@ @BUILD_MODULE_BATTERY_TRUE@LoadPlugin battery @BUILD_MODULE_CPU_TRUE@LoadPlugin cpu @BUILD_MODULE_CPUFREQ_TRUE@LoadPlugin cpufreq +@BUILD_MODULE_CSV_TRUE@LoadPlugin csv @BUILD_MODULE_DF_TRUE@LoadPlugin df @BUILD_MODULE_DISK_TRUE@LoadPlugin disk @BUILD_MODULE_DNS_TRUE@LoadPlugin dns diff --git a/src/csv.c b/src/csv.c new file mode 100644 index 00000000..b22f176f --- /dev/null +++ b/src/csv.c @@ -0,0 +1,207 @@ +/** + * collectd - src/csv.c + * Copyright (C) 2007 Florian octo Forster + * + * 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; only version 2 of the License is applicable. + * + * 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., + * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + * Authors: + * Florian octo Forster + **/ + +#include "collectd.h" +#include "plugin.h" +#include "common.h" +#include "utils_debug.h" + +static int value_list_to_string (char *buffer, int buffer_len, + const data_set_t *ds, const value_list_t *vl) +{ + int offset; + int status; + int i; + + memset (buffer, '\0', sizeof (buffer_len)); + + status = snprintf (buffer, buffer_len, "%u", (unsigned int) vl->time); + if ((status < 1) || (status >= buffer_len)) + return (-1); + offset = status; + + for (i = 0; i < ds->ds_num; i++) + { + if ((ds->ds[i].type != DS_TYPE_COUNTER) + && (ds->ds[i].type != DS_TYPE_GAUGE)) + return (-1); + + if (ds->ds[i].type == DS_TYPE_COUNTER) + status = snprintf (buffer + offset, buffer_len - offset, + ",%llu", vl->values[i].counter); + else + status = snprintf (buffer + offset, buffer_len - offset, + ",%lf", vl->values[i].gauge); + + if ((status < 1) || (status >= (buffer_len - offset))) + return (-1); + + offset += status; + } /* for ds->ds_num */ + + return (0); +} /* int value_list_to_string */ + +static int value_list_to_filename (char *buffer, int buffer_len, + const data_set_t *ds, const value_list_t *vl) +{ + int offset = 0; + int status; + + status = snprintf (buffer + offset, buffer_len - offset, + "%s/", vl->host); + if ((status < 1) || (status >= buffer_len - offset)) + return (-1); + offset += status; + + if (strlen (vl->plugin_instance) > 0) + status = snprintf (buffer + offset, buffer_len - offset, + "%s-%s/", vl->plugin, vl->plugin_instance); + else + status = snprintf (buffer + offset, buffer_len - offset, + "%s/", vl->plugin); + if ((status < 1) || (status >= buffer_len - offset)) + return (-1); + offset += status; + + if (strlen (vl->type_instance) > 0) + status = snprintf (buffer + offset, buffer_len - offset, + "%s-%s", ds->type, vl->type_instance); + else + status = snprintf (buffer + offset, buffer_len - offset, + "%s", ds->type); + if ((status < 1) || (status >= buffer_len - offset)) + return (-1); + offset += status; + + { + time_t now; + struct tm *tm; + + /* TODO: Find a way to minimize the calls to `localtime', since + * they are pretty expensive.. */ + now = time (NULL); + tm = localtime (&now); + + strftime (buffer + offset, buffer_len - offset, + "-%Y-%m-%d", tm); + + /* `localtime(3)' returns a pointer to static data, + * therefore the pointer may not be free'd. */ + } + + return (0); +} /* int value_list_to_filename */ + +static int csv_create_file (const char *filename, const data_set_t *ds) +{ + FILE *csv; + int i; + + if (check_create_dir (filename)) + return (-1); + + csv = fopen (filename, "w"); + if (csv == NULL) + { + syslog (LOG_ERR, "csv plugin: fopen (%s) failed: %s", + filename, strerror(errno)); + return (-1); + } + + fprintf (csv, "epoch"); + for (i = 0; i < ds->ds_num; i++) + fprintf (csv, ",%s", ds->ds[i].name); + + fprintf (csv, "\n"); + fclose (csv); + + return 0; +} /* int csv_create_file */ + +static int csv_write (const data_set_t *ds, const value_list_t *vl) +{ + struct stat statbuf; + char filename[512]; + char values[512]; + FILE *csv; + int csv_fd; + struct flock fl = { F_WRLCK, SEEK_SET, 0, 0, getpid () }; + int status; + + if (value_list_to_filename (filename, sizeof (filename), ds, vl) != 0) + return (-1); + + if (value_list_to_string (values, sizeof (values), ds, vl) != 0) + return (-1); + + if (stat (filename, &statbuf) == -1) + { + if (errno == ENOENT) + { + if (csv_create_file (filename, ds)) + return (-1); + } + else + { + syslog (LOG_ERR, "stat(%s) failed: %s", + filename, strerror (errno)); + return (-1); + } + } + else if (!S_ISREG (statbuf.st_mode)) + { + syslog (LOG_ERR, "stat(%s): Not a regular file!", + filename); + return (-1); + } + + csv = fopen (filename, "a"); + if (csv == NULL) + { + syslog (LOG_ERR, "csv plugin: fopen (%s) failed: %s", + filename, strerror (errno)); + return (-1); + } + csv_fd = fileno (csv); + + status = fcntl (csv_fd, F_SETLK, &fl); + if (status != 0) + { + syslog (LOG_ERR, "csv plugin: flock (%s) failed: %s", + filename, strerror (errno)); + fclose (csv); + return (-1); + } + + fprintf (csv, "%s\n", values); + + /* The lock is implicitely released. I we don't release it explicitely + * because the `FILE *' may need to flush a cache first */ + fclose (csv); + + return (0); +} /* int csv_write */ + +void module_register (void) +{ + plugin_register_write ("csv", csv_write); +}