X-Git-Url: https://git.octo.it/?a=blobdiff_plain;ds=inline;f=src%2Fcsv.c;h=78037a940ca3981a150a3fa84055c490b83c955b;hb=c35203c82560eba66bb901aa22c5170fb8c389fb;hp=dd33ca5e4876ea42d33f1db618a72c4d1d70b58f;hpb=cb7fed8bf0af2646dfcb32844933398c28e39be5;p=collectd.git diff --git a/src/csv.c b/src/csv.c index dd33ca5e..78037a94 100644 --- a/src/csv.c +++ b/src/csv.c @@ -1,6 +1,7 @@ /** * collectd - src/csv.c - * Copyright (C) 2007 Florian octo Forster + * Copyright (C) 2007-2009 Florian octo Forster + * Copyright (C) 2009 Doug MacEachern * * 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 @@ -17,12 +18,28 @@ * * Authors: * Florian octo Forster + * Doug MacEachern **/ #include "collectd.h" #include "plugin.h" #include "common.h" -#include "utils_debug.h" +#include "utils_cache.h" +#include "utils_parse_option.h" + +/* + * Private variables + */ +static const char *config_keys[] = +{ + "DataDir", + "StoreRates" +}; +static int config_keys_num = STATIC_ARRAY_SIZE (config_keys); + +static char *datadir = NULL; +static int store_rates = 0; +static int use_stdio = 0; static int value_list_to_string (char *buffer, int buffer_len, const data_set_t *ds, const value_list_t *vl) @@ -30,10 +47,13 @@ static int value_list_to_string (char *buffer, int buffer_len, int offset; int status; int i; + gauge_t *rates = NULL; + + assert (0 == strcmp (ds->type, vl->type)); - memset (buffer, '\0', sizeof (buffer_len)); + memset (buffer, '\0', buffer_len); - status = snprintf (buffer, buffer_len, "%u", (unsigned int) vl->time); + status = ssnprintf (buffer, buffer_len, "%u", (unsigned int) vl->time); if ((status < 1) || (status >= buffer_len)) return (-1); offset = status; @@ -41,22 +61,62 @@ static int value_list_to_string (char *buffer, int buffer_len, for (i = 0; i < ds->ds_num; i++) { if ((ds->ds[i].type != DS_TYPE_COUNTER) - && (ds->ds[i].type != DS_TYPE_GAUGE)) + && (ds->ds[i].type != DS_TYPE_GAUGE) + && (ds->ds[i].type != DS_TYPE_DERIVE) + && (ds->ds[i].type != DS_TYPE_ABSOLUTE)) 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, + if (ds->ds[i].type == DS_TYPE_GAUGE) + { + status = ssnprintf (buffer + offset, buffer_len - offset, ",%lf", vl->values[i].gauge); + } + else if (store_rates != 0) + { + if (rates == NULL) + rates = uc_get_rate (ds, vl); + if (rates == NULL) + { + WARNING ("csv plugin: " + "uc_get_rate failed."); + return (-1); + } + status = ssnprintf (buffer + offset, + buffer_len - offset, + ",%lf", rates[i]); + } + else if (ds->ds[i].type == DS_TYPE_COUNTER) + { + status = ssnprintf (buffer + offset, + buffer_len - offset, + ",%llu", + vl->values[i].counter); + } + else if (ds->ds[i].type == DS_TYPE_DERIVE) + { + status = ssnprintf (buffer + offset, + buffer_len - offset, + ",%"PRIi64, + vl->values[i].derive); + } + else if (ds->ds[i].type == DS_TYPE_ABSOLUTE) + { + status = ssnprintf (buffer + offset, + buffer_len - offset, + ",%"PRIu64, + vl->values[i].absolute); + } if ((status < 1) || (status >= (buffer_len - offset))) + { + sfree (rates); return (-1); + } offset += status; } /* for ds->ds_num */ + sfree (rates); return (0); } /* int value_list_to_string */ @@ -66,46 +126,59 @@ static int value_list_to_filename (char *buffer, int buffer_len, int offset = 0; int status; - status = snprintf (buffer + offset, buffer_len - offset, + assert (0 == strcmp (ds->type, vl->type)); + + if (datadir != NULL) + { + status = ssnprintf (buffer + offset, buffer_len - offset, + "%s/", datadir); + if ((status < 1) || (status >= buffer_len - offset)) + return (-1); + offset += status; + } + + status = ssnprintf (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, + status = ssnprintf (buffer + offset, buffer_len - offset, "%s-%s/", vl->plugin, vl->plugin_instance); else - status = snprintf (buffer + offset, buffer_len - offset, + status = ssnprintf (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); + status = ssnprintf (buffer + offset, buffer_len - offset, + "%s-%s", vl->type, vl->type_instance); else - status = snprintf (buffer + offset, buffer_len - offset, - "%s", ds->type); + status = ssnprintf (buffer + offset, buffer_len - offset, + "%s", vl->type); if ((status < 1) || (status >= buffer_len - offset)) return (-1); offset += status; + if (!use_stdio) { time_t now; - struct tm *tm; + struct tm stm; - /* TODO: Find a way to minimize the calls to `localtime', since - * they are pretty expensive.. */ + /* TODO: Find a way to minimize the calls to `localtime_r', + * since they are pretty expensive.. */ now = time (NULL); - tm = localtime (&now); + if (localtime_r (&now, &stm) == NULL) + { + ERROR ("csv plugin: localtime_r failed"); + return (1); + } 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. */ + "-%Y-%m-%d", &stm); } return (0); @@ -122,8 +195,10 @@ static int csv_create_file (const char *filename, const data_set_t *ds) csv = fopen (filename, "w"); if (csv == NULL) { - syslog (LOG_ERR, "csv plugin: fopen (%s) failed: %s", - filename, strerror(errno)); + char errbuf[1024]; + ERROR ("csv plugin: fopen (%s) failed: %s", + filename, + sstrerror (errno, errbuf, sizeof (errbuf))); return (-1); } @@ -137,7 +212,60 @@ static int csv_create_file (const char *filename, const data_set_t *ds) return 0; } /* int csv_create_file */ -static int csv_write (const data_set_t *ds, const value_list_t *vl) +static int csv_config (const char *key, const char *value) +{ + if (strcasecmp ("DataDir", key) == 0) + { + if (datadir != NULL) + free (datadir); + if (strcasecmp ("stdout", value) == 0) + { + use_stdio = 1; + return (0); + } + else if (strcasecmp ("stderr", value) == 0) + { + use_stdio = 2; + return (0); + } + datadir = strdup (value); + if (datadir != NULL) + { + int len = strlen (datadir); + while ((len > 0) && (datadir[len - 1] == '/')) + { + len--; + datadir[len] = '\0'; + } + if (len <= 0) + { + free (datadir); + datadir = NULL; + } + } + } + else if (strcasecmp ("StoreRates", key) == 0) + { + if ((strcasecmp ("True", value) == 0) + || (strcasecmp ("Yes", value) == 0) + || (strcasecmp ("On", value) == 0)) + { + store_rates = 1; + } + else + { + store_rates = 0; + } + } + else + { + return (-1); + } + return (0); +} /* int csv_config */ + +static int csv_write (const data_set_t *ds, const value_list_t *vl, + user_data_t __attribute__((unused)) *user_data) { struct stat statbuf; char filename[512]; @@ -147,12 +275,40 @@ static int csv_write (const data_set_t *ds, const value_list_t *vl) struct flock fl; int status; + if (0 != strcmp (ds->type, vl->type)) { + ERROR ("csv plugin: DS type does not match value list type"); + return -1; + } + if (value_list_to_filename (filename, sizeof (filename), ds, vl) != 0) return (-1); + DEBUG ("csv plugin: csv_write: filename = %s;", filename); + if (value_list_to_string (values, sizeof (values), ds, vl) != 0) return (-1); + if (use_stdio) + { + size_t i; + + escape_string (filename, sizeof (filename)); + + /* Replace commas by colons for PUTVAL compatible output. */ + for (i = 0; i < sizeof (values); i++) + { + if (values[i] == 0) + break; + else if (values[i] == ',') + values[i] = ':'; + } + + fprintf (use_stdio == 1 ? stdout : stderr, + "PUTVAL %s interval=%i %s\n", + filename, interval_g, values); + return (0); + } + if (stat (filename, &statbuf) == -1) { if (errno == ENOENT) @@ -162,14 +318,16 @@ static int csv_write (const data_set_t *ds, const value_list_t *vl) } else { - syslog (LOG_ERR, "stat(%s) failed: %s", - filename, strerror (errno)); + char errbuf[1024]; + ERROR ("stat(%s) failed: %s", filename, + sstrerror (errno, errbuf, + sizeof (errbuf))); return (-1); } } else if (!S_ISREG (statbuf.st_mode)) { - syslog (LOG_ERR, "stat(%s): Not a regular file!", + ERROR ("stat(%s): Not a regular file!", filename); return (-1); } @@ -177,8 +335,9 @@ static int csv_write (const data_set_t *ds, const value_list_t *vl) csv = fopen (filename, "a"); if (csv == NULL) { - syslog (LOG_ERR, "csv plugin: fopen (%s) failed: %s", - filename, strerror (errno)); + char errbuf[1024]; + ERROR ("csv plugin: fopen (%s) failed: %s", filename, + sstrerror (errno, errbuf, sizeof (errbuf))); return (-1); } csv_fd = fileno (csv); @@ -193,8 +352,9 @@ static int csv_write (const data_set_t *ds, const value_list_t *vl) status = fcntl (csv_fd, F_SETLK, &fl); if (status != 0) { - syslog (LOG_ERR, "csv plugin: flock (%s) failed: %s", - filename, strerror (errno)); + char errbuf[1024]; + ERROR ("csv plugin: flock (%s) failed: %s", filename, + sstrerror (errno, errbuf, sizeof (errbuf))); fclose (csv); return (-1); } @@ -210,5 +370,7 @@ static int csv_write (const data_set_t *ds, const value_list_t *vl) void module_register (void) { - plugin_register_write ("csv", csv_write); -} + plugin_register_config ("csv", csv_config, + config_keys, config_keys_num); + plugin_register_write ("csv", csv_write, /* user_data = */ NULL); +} /* void module_register */