2 * collectd - src/rrdtool.c
3 * Copyright (C) 2006 Florian octo Forster
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License as published by the
7 * Free Software Foundation; only version 2 of the License is applicable.
9 * This program is distributed in the hope that it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * General Public License for more details.
14 * You should have received a copy of the GNU General Public License along
15 * with this program; if not, write to the Free Software Foundation, Inc.,
16 * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
19 * Florian octo Forster <octo at verplant.org>
25 #include "utils_debug.h"
28 * This weird macro cascade forces the glibc to define `NAN'. I don't know
29 * another way to solve this, so more intelligent solutions are welcome. -octo
32 # define DISABLE__USE_ISOC99 1
33 # define __USE_ISOC99 1
36 #ifdef DISABLE__USE_ISOC99
37 # undef DISABLE__USE_ISOC99
41 static int rra_timespans[] =
50 static int rra_timespans_num = 5;
52 static char *rra_types[] =
59 static int rra_types_num = 3;
64 static int rra_get (char ***ret)
66 static char **rra_def = NULL;
67 static int rra_num = 0;
69 int rra_max = rra_timespans_num * rra_types_num;
81 if ((rra_num != 0) && (rra_def != NULL))
87 if ((rra_def = (char **) malloc ((rra_max + 1) * sizeof (char *))) == NULL)
89 memset (rra_def, '\0', (rra_max + 1) * sizeof (char *));
91 step = atoi (COLLECTD_STEP);
92 rows = atoi (COLLECTD_ROWS);
94 if ((step <= 0) || (rows <= 0))
101 for (i = 0; i < rra_timespans_num; i++)
103 span = rra_timespans[i];
105 if ((span / step) < rows)
111 cdp_len = (int) floor (((double) span) / ((double) (rows * step)));
113 cdp_num = (int) ceil (((double) span) / ((double) (cdp_len * step)));
115 for (j = 0; j < rra_types_num; j++)
117 if (rra_num >= rra_max)
120 if (snprintf (buffer, sizeof(buffer), "RRA:%s:%3.1f:%u:%u",
121 rra_types[j], COLLECTD_XFF,
122 cdp_len, cdp_num) >= sizeof (buffer))
124 syslog (LOG_ERR, "rra_get: Buffer would have been truncated.");
128 rra_def[rra_num++] = sstrdup (buffer);
133 DBG ("rra_num = %i", rra_num);
134 for (i = 0; i < rra_num; i++)
135 DBG (" %s", rra_def[i]);
142 static void ds_free (int ds_num, char **ds_def)
146 for (i = 0; i < ds_num; i++)
147 if (ds_def[i] != NULL)
152 static int ds_get (char ***ret, const data_set_t *ds)
161 DBG ("ds->ds_num = %i", ds->ds_num);
163 ds_def = (char **) malloc (ds->ds_num * sizeof (char *));
166 syslog (LOG_ERR, "rrdtool plugin: malloc failed: %s",
170 memset (ds_def, '\0', ds->ds_num * sizeof (char *));
172 for (ds_num = 0; ds_num < ds->ds_num; ds_num++)
174 data_source_t *d = ds->ds + ds_num;
178 ds_def[ds_num] = NULL;
180 if (d->type == DS_TYPE_COUNTER)
182 else if (d->type == DS_TYPE_GAUGE)
186 syslog (LOG_ERR, "rrdtool plugin: Unknown DS type: %i",
197 snprintf (min, sizeof (min), "%lf", d->min);
198 min[sizeof (min) - 1] = '\0';
207 snprintf (max, sizeof (max), "%lf", d->max);
208 max[sizeof (max) - 1] = '\0';
211 status = snprintf (buffer, sizeof (buffer),
213 d->name, type, COLLECTD_HEARTBEAT,
215 if ((status < 1) || (status >= sizeof (buffer)))
218 ds_def[ds_num] = sstrdup (buffer);
219 } /* for ds_num = 0 .. ds->ds_num */
224 DBG ("ds_num = %i", ds_num);
225 for (i = 0; i < ds_num; i++)
226 DBG (" %s", ds_def[i]);
230 if (ds_num != ds->ds_num)
232 ds_free (ds_num, ds_def);
240 static int rrd_create_file (char *filename, const data_set_t *ds)
251 if (check_create_dir (filename))
254 if ((rra_num = rra_get (&rra_def)) < 1)
256 syslog (LOG_ERR, "rrd_create_file failed: Could not calculate RRAs");
260 if ((ds_num = ds_get (&ds_def, ds)) < 1)
262 syslog (LOG_ERR, "rrd_create_file failed: Could not calculate DSes");
266 argc = ds_num + rra_num + 4;
268 if ((argv = (char **) malloc (sizeof (char *) * (argc + 1))) == NULL)
270 syslog (LOG_ERR, "rrd_create failed: %s", strerror (errno));
277 argv[3] = COLLECTD_STEP;
280 for (i = 0; i < ds_num; i++)
281 argv[j++] = ds_def[i];
282 for (i = 0; i < rra_num; i++)
283 argv[j++] = rra_def[i];
286 optind = 0; /* bug in librrd? */
288 if (rrd_create (argc, argv) == -1)
290 syslog (LOG_ERR, "rrd_create failed: %s: %s", filename, rrd_get_error ());
295 ds_free (ds_num, ds_def);
300 static int value_list_to_string (char *buffer, int buffer_len,
301 const data_set_t *ds, const value_list_t *vl)
307 memset (buffer, '\0', sizeof (buffer_len));
309 status = snprintf (buffer, buffer_len, "%u", (unsigned int) vl->time);
310 if ((status < 1) || (status >= buffer_len))
314 for (i = 0; i < ds->ds_num; i++)
316 if ((ds->ds[i].type != DS_TYPE_COUNTER)
317 && (ds->ds[i].type != DS_TYPE_GAUGE))
320 if (ds->ds[i].type == DS_TYPE_COUNTER)
321 status = snprintf (buffer + offset, buffer_len - offset,
322 ":%llu", vl->values[i].counter);
324 status = snprintf (buffer + offset, buffer_len - offset,
325 ":%lf", vl->values[i].gauge);
327 if ((status < 1) || (status >= (buffer_len - offset)))
331 } /* for ds->ds_num */
334 } /* int value_list_to_string */
336 static int value_list_to_filename (char *buffer, int buffer_len,
337 const data_set_t *ds, const value_list_t *vl)
342 status = snprintf (buffer + offset, buffer_len - offset,
344 if ((status < 1) || (status >= buffer_len - offset))
348 if (strlen (vl->plugin_instance) > 0)
349 status = snprintf (buffer + offset, buffer_len - offset,
350 "%s-%s/", vl->plugin, vl->plugin_instance);
352 status = snprintf (buffer + offset, buffer_len - offset,
354 if ((status < 1) || (status >= buffer_len - offset))
358 if (strlen (vl->type_instance) > 0)
359 status = snprintf (buffer + offset, buffer_len - offset,
360 "%s-%s.rrd", ds->type, vl->type_instance);
362 status = snprintf (buffer + offset, buffer_len - offset,
364 if ((status < 1) || (status >= buffer_len - offset))
369 } /* int value_list_to_filename */
371 static int rrd_write (const data_set_t *ds, const value_list_t *vl)
376 char *argv[4] = { "update", filename, values, NULL };
378 if (value_list_to_filename (filename, sizeof (filename), ds, vl) != 0)
381 if (value_list_to_string (values, sizeof (values), ds, vl) != 0)
384 if (stat (filename, &statbuf) == -1)
388 if (rrd_create_file (filename, ds))
393 syslog (LOG_ERR, "stat(%s) failed: %s",
394 filename, strerror (errno));
398 else if (!S_ISREG (statbuf.st_mode))
400 syslog (LOG_ERR, "stat(%s): Not a regular file!",
405 DBG ("rrd_update (%s, %s, %s)", argv[0], argv[1], argv[2]);
407 optind = 0; /* bug in librrd? */
409 if (rrd_update (3, argv) == -1)
411 syslog (LOG_WARNING, "rrd_update failed: %s: %s",
412 filename, rrd_get_error ());
416 } /* int rrd_update_file */
418 void module_register (void)
420 plugin_register_write ("rrdtool", rrd_write);