author | Florian Forster <octo@leeloo.lan.home.verplant.org> | |
Fri, 5 Oct 2007 14:09:11 +0000 (16:09 +0200) | ||
committer | Florian Forster <octo@leeloo.lan.home.verplant.org> | |
Fri, 5 Oct 2007 14:09:11 +0000 (16:09 +0200) |
configure.in | patch | blob | history | |
src/Makefile.am | patch | blob | history | |
src/collectd-snmp.pod | patch | blob | history | |
src/collectd.conf.pod | patch | blob | history | |
src/rrdtool.c | patch | blob | history | |
src/snmp.c | patch | blob | history |
diff --git a/configure.in b/configure.in
index f67186edd8bf04937a43fc8110a1b4b7ff27300c..d904920d5c5501ebbe2c41aaa079e34bcbc40e89 100644 (file)
--- a/configure.in
+++ b/configure.in
collectd additional packages:])
# AC_ARG_WITH (package, help-string, [action-if-given], [action-if-not-given])
+librrd_cflags=""
+librrd_ldflags=""
+librrd_threadsafe="yes"
AC_ARG_WITH(rrdtool, [AS_HELP_STRING([--with-rrdtool@<:@=PREFIX@:>@], [Path to rrdtool.])],
[ if test "x$withval" != "xno" && test "x$withval" != "xyes"
then
- LDFLAGS="$LDFLAGS -L$withval/lib"
- CPPFLAGS="$CPPFLAGS -I$withval/include"
+ librrd_cflags="-I$withval/include"
+ librrd_ldflags="-L$withval/lib"
with_rrdtool="yes"
fi
], [with_rrdtool="yes"])
if test "x$with_rrdtool" = "xyes"
then
- AC_CHECK_LIB(rrd, rrd_update,
- [
- AC_DEFINE(HAVE_LIBRRD, 1, [Define to 1 if you have the rrd library (-lrrd).])
- ],
- [with_rrdtool="no (librrd not found)"], [-lm])
+ SAVE_CFLAGS="$CFLAGS"
+ SAVE_LDFLAGS="$LDFLAGS"
+
+ CFLAGS="$CFLAGS $librrd_cflags"
+ LDFLAGS="$LDFLAGS $librrd_ldflags"
+
+ AC_CHECK_HEADERS(rrd.h,, [with_rrdtool="no (rrd.h not found)"])
+
+ CFLAGS="$SAVE_CFLAGS"
+ LDFLAGS="$SAVE_LDFLAGS"
fi
if test "x$with_rrdtool" = "xyes"
then
- AC_CHECK_HEADERS(rrd.h,, [with_rrdtool="no (rrd.h not found)"])
+ AC_CHECK_LIB(rrd_th, rrd_update_r,
+ [with_rrdtool="yes"
+ librrd_ldflags="$librrd_ldflags -lrrd_th -lm"
+ ],
+ [librrd_threadsafe="no"
+ AC_CHECK_LIB(rrd, rrd_update,
+ [with_rrdtool="yes"
+ librrd_ldflags="$librrd_ldflags -lrrd -lm"
+ ],
+ [with_rrdtool="no (symbol 'rrd_update' not found)"],
+ [-lm])
+ ]
+ [-lm])
fi
if test "x$with_rrdtool" = "xyes"
then
- collect_rrdtool=1
-else
- collect_rrdtool=0
+ BUILD_WITH_LIBRRD_CFLAGS="$librrd_cflags"
+ BUILD_WITH_LIBRRD_LDFLAGS="$librrd_ldflags"
+ AC_SUBST(BUILD_WITH_LIBRRD_CFLAGS)
+ AC_SUBST(BUILD_WITH_LIBRRD_LDFLAGS)
+fi
+if test "x$librrd_threadsafe" = "xyes"
+then
+ AC_DEFINE(HAVE_THREADSAFE_LIBRRD, 1, [Define to 1 if you have the threadsafe rrd library (-lrrd_th).])
fi
-AC_DEFINE_UNQUOTED(COLLECT_RRDTOOL, [$collect_rrdtool],
- [Wether or not to use rrdtool library])
-AM_CONDITIONAL(BUILD_WITH_RRDTOOL, test "x$with_rrdtool" = "xyes")
AC_ARG_WITH(libpthread, [AS_HELP_STRING([--with-libpthread=@<:@=PREFIX@:>@], [Path to libpthread.])],
[ if test "x$withval" != "xno" -a "x$withval" != "xyes"
diff --git a/src/Makefile.am b/src/Makefile.am
index f988a0f0f30649ba154db4878c1bc3ce06905a0e..9818580462860123c3640a65ce81789858f3e683 100644 (file)
--- a/src/Makefile.am
+++ b/src/Makefile.am
if BUILD_PLUGIN_RRDTOOL
pkglib_LTLIBRARIES += rrdtool.la
rrdtool_la_SOURCES = rrdtool.c
-rrdtool_la_LDFLAGS = -module -avoid-version -lrrd
+rrdtool_la_LDFLAGS = -module -avoid-version
+rrdtool_la_CFLAGS = $(BUILD_WITH_LIBRRD_CFLAGS)
+rrdtool_la_LIBADD = $(BUILD_WITH_LIBRRD_LDFLAGS)
collectd_LDADD += "-dlopen" rrdtool.la
collectd_DEPENDENCIES += rrdtool.la
endif
diff --git a/src/collectd-snmp.pod b/src/collectd-snmp.pod
index 44ca4d1f907b1bd13f56e664b8c8fb2429f7cb6f..a08b69ed3e7e6527bdebb9ecca86b1d9c3f66308 100644 (file)
--- a/src/collectd-snmp.pod
+++ b/src/collectd-snmp.pod
Since the aim of the C<snmp plugin> is to provide a generic interface to SNMP,
it's configuration is not trivial and may take some time.
+Since the C<Net-SNMP> library is used you cann use all the environment
+variables that are interpreted by that package. See L<snmpcmd(1)> for more
+details.
+
There are two types of blocks that can be contained in the
C<E<lt>PluginE<nbsp>snmpE<gt>> block: B<Data> and B<Host>:
diff --git a/src/collectd.conf.pod b/src/collectd.conf.pod
index 27c506564356c0fbd5e3431c90977cfb43facec2..4dcbcd1bb9bf4049e5066c9470dade81c94c9766 100644 (file)
--- a/src/collectd.conf.pod
+++ b/src/collectd.conf.pod
=item B<StepSize> I<Seconds>
-Sets the stepsize of newly created RRD-files. Ideally (and per default) this
-setting is identical to the global B<Interval>-option and should not be
-smaller. If unsure, don't set this option.
+B<Force> the stepsize of newly created RRD-files. Ideally (and per default)
+this setting is unset and the stepsize is set to the interval in which the data
+is collected. Do not use this option unless you absolutely have to for some
+reason. Setting this option may cause problems with the C<snmp plugin>, the
+C<exec plugin> or when the daemon is set up to receive data from other hosts.
=item B<HeartBeat> I<Seconds>
-Sets the heartbeat of newly created RRD-files. Ideally this setting is bigger
-than the B<Interval>-setting, by default it's twice the B<Interval>-setting. If
-unsure, don't set this option.
+B<Force> the heartbeat of newly created RRD-files. This setting should be unset
+in which case the heartbeat is set to twice the B<StepSize> which should equal
+the interval in which data is collected. Do not set this option unless you have
+a very good reason to do so.
=item B<RRARows> I<NumRows>
diff --git a/src/rrdtool.c b/src/rrdtool.c
index 56ef581e3596a522656380da219f408bec0dce43..06d9763968292de2a4ab85ffa3628bd4e72fa3e4 100644 (file)
--- a/src/rrdtool.c
+++ b/src/rrdtool.c
static pthread_mutex_t queue_lock = PTHREAD_MUTEX_INITIALIZER;
static pthread_cond_t queue_cond = PTHREAD_COND_INITIALIZER;
+#if !HAVE_THREADSAFE_LIBRRD
+static pthread_mutex_t librrd_lock = PTHREAD_MUTEX_INITIALIZER;
+#endif
+
static int do_shutdown = 0;
/* * * * * * * * * *
return (ds_num);
}
+#if HAVE_THREADSAFE_LIBRRD
+static int srrd_create (char *filename, unsigned long pdp_step, time_t last_up,
+ int argc, char **argv)
+{
+ int status;
+
+ optind = 0; /* bug in librrd? */
+ rrd_clear_error ();
+
+ status = rrd_create_r (filename, pdp_step, last_up, argc, argv);
+
+ if (status != 0)
+ {
+ WARNING ("rrdtool plugin: rrd_create_r (%s) failed: %s",
+ filename, rrd_get_error ());
+ }
+
+ return (status);
+} /* int srrd_create */
+
+static int srrd_update (char *filename, char *template, int argc, char **argv)
+{
+ int status;
+
+ optind = 0; /* bug in librrd? */
+ rrd_clear_error ();
+
+ status = rrd_update_r (filename, template, argc, argv);
+
+ if (status != 0)
+ {
+ WARNING ("rrdtool plugin: rrd_update_r (%s) failed: %s",
+ filename, rrd_get_error ());
+ }
+
+ return (status);
+} /* int srrd_update */
+/* #endif HAVE_THREADSAFE_LIBRRD */
+
+#else /* !HAVE_THREADSAFE_LIBRRD */
+static int srrd_create (char *filename, unsigned long pdp_step, time_t last_up,
+ int argc, char **argv)
+{
+ int status;
+
+ int new_argc;
+ char **new_argv;
+
+ char pdp_step_str[16];
+ char last_up_str[16];
+
+ new_argc = 6 + argc;
+ new_argv = (char **) malloc ((new_argc + 1) * sizeof (char *));
+ if (new_argv == NULL)
+ {
+ ERROR ("rrdtool plugin: malloc failed.");
+ return (-1);
+ }
+
+ if (last_up == 0)
+ last_up = time (NULL) - 10;
+
+ snprintf (pdp_step_str, sizeof (pdp_step_str), "%lu", pdp_step);
+ pdp_step_str[sizeof (pdp_step_str) - 1] = '\0';
+ snprintf (last_up_str, sizeof (last_up_str), "%u", (unsigned int) last_up);
+ last_up_str[sizeof (last_up_str) - 1] = '\0';
+
+ new_argv[0] = "create";
+ new_argv[1] = filename;
+ new_argv[2] = "-s";
+ new_argv[3] = pdp_step_str;
+ new_argv[4] = "-b";
+ new_argv[5] = last_up_str;
+
+ memcpy (new_argv + 6, argv, argc * sizeof (char *));
+ new_argv[new_argc] = NULL;
+
+ pthread_mutex_lock (&librrd_lock);
+ optind = 0; /* bug in librrd? */
+ rrd_clear_error ();
+
+ status = rrd_create (new_argc, new_argv);
+ pthread_mutex_unlock (&librrd_lock);
+
+ if (status != 0)
+ {
+ WARNING ("rrdtool plugin: rrd_create (%s) failed: %s",
+ filename, rrd_get_error ());
+ }
+
+ sfree (new_argv);
+
+ return (status);
+} /* int srrd_create */
+
+static int srrd_update (char *filename, char *template, int argc, char **argv)
+{
+ int status;
+
+ int new_argc;
+ char **new_argv;
+
+ assert (template == NULL);
+
+ new_argc = 2 + argc;
+ new_argv = (char **) malloc ((new_argc + 1) * sizeof (char *));
+ if (new_argv == NULL)
+ {
+ ERROR ("rrdtool plugin: malloc failed.");
+ return (-1);
+ }
+
+ new_argv[0] = "update";
+ new_argv[1] = filename;
+
+ memcpy (new_argv + 2, argv, argc * sizeof (char *));
+ new_argv[new_argc] = NULL;
+
+ pthread_mutex_lock (&librrd_lock);
+ optind = 0; /* bug in librrd? */
+ rrd_clear_error ();
+
+ status = rrd_update (new_argc, new_argv);
+ pthread_mutex_unlock (&librrd_lock);
+
+ if (status != 0)
+ {
+ WARNING ("rrdtool plugin: rrd_update_r failed: %s: %s",
+ argv[1], rrd_get_error ());
+ }
+
+ sfree (new_argv);
+
+ return (status);
+} /* int srrd_update */
+#endif /* !HAVE_THREADSAFE_LIBRRD */
+
static int rrd_create_file (char *filename, const data_set_t *ds, const value_list_t *vl)
{
char **argv;
@@ -335,9 +476,6 @@ static int rrd_create_file (char *filename, const data_set_t *ds, const value_li
int rra_num;
char **ds_def;
int ds_num;
- int i, j;
- char stepsize_str[16];
- char begin_str[16];
int status = 0;
if (check_create_dir (filename))
@@ -355,7 +493,7 @@ static int rrd_create_file (char *filename, const data_set_t *ds, const value_li
return (-1);
}
- argc = ds_num + rra_num + 6;
+ argc = ds_num + rra_num;
if ((argv = (char **) malloc (sizeof (char *) * (argc + 1))) == NULL)
{
@@ -365,47 +503,15 @@ static int rrd_create_file (char *filename, const data_set_t *ds, const value_li
return (-1);
}
- status = snprintf (stepsize_str, sizeof (stepsize_str),
- "%i", (stepsize > 0) ? stepsize : vl->interval);
- if ((status < 1) || (status >= sizeof (stepsize_str)))
- {
- ERROR ("rrdtool plugin: snprintf failed.");
- free (argv);
- ds_free (ds_num, ds_def);
- rra_free (rra_num, rra_def);
- return (-1);
- }
+ memcpy (argv, ds_def, ds_num * sizeof (char *));
+ memcpy (argv + ds_num, rra_def, rra_num * sizeof (char *));
+ argv[ds_num + rra_num] = NULL;
assert (vl->time > 10);
- status = snprintf (begin_str, sizeof (begin_str),
- "%llu", (unsigned long long) (vl->time - 10));
- if ((status < 1) || (status >= sizeof (begin_str)))
- {
- ERROR ("rrdtool plugin: snprintf failed.");
- return (-1);
- }
-
- argv[0] = "create";
- argv[1] = filename;
- argv[2] = "-b";
- argv[3] = begin_str;
- argv[4] = "-s";
- argv[5] = stepsize_str;
-
- j = 6;
- for (i = 0; i < ds_num; i++)
- argv[j++] = ds_def[i];
- for (i = 0; i < rra_num; i++)
- argv[j++] = rra_def[i];
- argv[j] = NULL;
-
- optind = 0; /* bug in librrd? */
- rrd_clear_error ();
- if (rrd_create (argc, argv) == -1)
- {
- ERROR ("rrd_create failed: %s: %s", filename, rrd_get_error ());
- status = -1;
- }
+ status = srrd_create (filename,
+ (stepsize > 0) ? stepsize : vl->interval,
+ vl->time - 10,
+ argc, argv);
free (argv);
ds_free (ds_num, ds_def);
return (0);
} /* int value_list_to_filename */
-static int rrd_write_to_file (char *filename, char **values, int values_num)
-{
- char **argv;
- int argc;
- int status;
-
- if (values_num < 1)
- return (0);
-
- argc = values_num + 2;
- argv = (char **) malloc ((argc + 1) * sizeof (char *));
- if (argv == NULL)
- return (-1);
-
- argv[0] = "update";
- argv[1] = filename;
- memcpy (argv + 2, values, values_num * sizeof (char *));
- argv[argc] = NULL;
-
- DEBUG ("rrd_update (argc = %i, argv = %p)", argc, (void *) argv);
-
- optind = 0; /* bug in librrd? */
- rrd_clear_error ();
- status = rrd_update (argc, argv);
- if (status != 0)
- {
- WARNING ("rrd_update failed: %s: %s",
- filename, rrd_get_error ());
- status = -1;
- }
-
- sfree (argv);
-
- return (status);
-} /* int rrd_write_cache_entry */
-
static void *rrd_queue_thread (void *data)
{
while (42)
pthread_mutex_unlock (&cache_lock);
/* Write the values to the RRD-file */
- rrd_write_to_file (queue_entry->filename, values, values_num);
+ srrd_update (queue_entry->filename, NULL, values_num, values);
for (i = 0; i < values_num; i++)
{
diff --git a/src/snmp.c b/src/snmp.c
index a10509dae1f22097fc0bef24138e21ce423490f7..8673df199e9ffe135993986a24f5cc1e1607b50e 100644 (file)
--- a/src/snmp.c
+++ b/src/snmp.c
char *community;
int version;
void *sess_handle;
- int16_t skip_num;
- int16_t skip_left;
+ uint32_t interval;
+ time_t next_update;
data_definition_t **data_list;
int data_list_len;
- enum /****************************************************/
- { /* This host.. */
- STATE_IDLE, /* - just sits there until `skip_left < interval_g' */
- STATE_WAIT, /* - waits to be queried. */
- STATE_BUSY /* - is currently being queried. */
- } state; /****************************************************/
+ enum /******************************************************/
+ { /* This host.. */
+ STATE_IDLE, /* - just sits there until `next_update < interval_g' */
+ STATE_WAIT, /* - waits to be queried. */
+ STATE_BUSY /* - is currently being queried. */
+ } state; /******************************************************/
struct host_definition_s *next;
};
typedef struct host_definition_s host_definition_t;
static int csnmp_config_add_host_interval (host_definition_t *hd, oconfig_item_t *ci)
{
- int interval;
-
if ((ci->values_num != 1)
|| (ci->values[0].type != OCONFIG_TYPE_NUMBER))
{
@@ -528,10 +526,9 @@ static int csnmp_config_add_host_interval (host_definition_t *hd, oconfig_item_t
return (-1);
}
- interval = (int) ci->values[0].value.number;
- hd->skip_num = interval;
- if (hd->skip_num < 0)
- hd->skip_num = 0;
+ hd->interval = (int) ci->values[0].value.number;
+ if (hd->interval < 0)
+ hd->interval = 0;
return (0);
} /* int csnmp_config_add_host_interval */
}
hd->sess_handle = NULL;
- hd->skip_num = 0;
- hd->skip_left = 0;
+ hd->interval = 0;
+ hd->next_update = 0;
hd->state = STATE_IDLE;
for (i = 0; i < ci->children_num; i++)
@@ -928,7 +925,7 @@ static int csnmp_dispatch_table (host_definition_t *host, data_definition_t *dat
vl.host[sizeof (vl.host) - 1] = '\0';
strcpy (vl.plugin, "snmp");
- vl.interval = host->skip_num;
+ vl.interval = host->interval;
vl.time = time (NULL);
subid = 0;
@@ -1305,7 +1302,7 @@ static int csnmp_read_value (host_definition_t *host, data_definition_t *data)
strncpy (vl.type_instance, data->instance.string, sizeof (vl.type_instance));
vl.type_instance[sizeof (vl.type_instance) - 1] = '\0';
- vl.interval = host->skip_num;
+ vl.interval = host->interval;
req = snmp_pdu_create (SNMP_MSG_GET);
if (req == NULL)
@@ -1336,10 +1333,12 @@ static int csnmp_read_value (host_definition_t *host, data_definition_t *data)
for (vb = res->variables; vb != NULL; vb = vb->next_variable)
{
+#if COLLECT_DEBUG
char buffer[1024];
snprint_variable (buffer, sizeof (buffer),
vb->name, vb->name_length, vb);
DEBUG ("snmp plugin: Got this variable: %s", buffer);
+#endif /* COLLECT_DEBUG */
for (i = 0; i < data->values_len; i++)
if (snmp_oid_compare (data->values[i].oid, data->values[i].oid_len,
@@ -1360,8 +1359,12 @@ static int csnmp_read_value (host_definition_t *host, data_definition_t *data)
static int csnmp_read_host (host_definition_t *host)
{
int i;
+ time_t time_start;
+ time_t time_end;
- DEBUG ("snmp plugin: csnmp_read_host (%s);", host->name);
+ time_start = time (NULL);
+ DEBUG ("snmp plugin: csnmp_read_host (%s) started at %u;", host->name,
+ (unsigned int) time_start);
if (host->sess_handle == NULL)
csnmp_host_open_session (host);
csnmp_read_value (host, data);
}
+ time_end = time (NULL);
+ DEBUG ("snmp plugin: csnmp_read_host (%s) finished at %u;", host->name,
+ (unsigned int) time_end);
+ if ((time_end - time_start) > host->interval)
+ {
+ WARNING ("snmp plugin: Host `%s' should be queried every %i seconds, "
+ "but reading all values takes %i seconds.",
+ host->name, host->interval, time_end - time_start);
+ }
+
return (0);
} /* int csnmp_read_host */
for (host = host_head; host != NULL; host = host->next)
{
threads_num++;
- /* We need to initialize `skip_num' here, because `interval_g' isn't
+ /* We need to initialize `interval' here, because `interval_g' isn't
* initialized during `configure'. */
- host->skip_left = interval_g;
- if (host->skip_num == 0)
+ host->next_update = time (NULL);
+ if (host->interval == 0)
{
- host->skip_num = interval_g;
+ host->interval = interval_g;
}
- else if (host->skip_num < interval_g)
+ else if (host->interval < interval_g)
{
- host->skip_num = interval_g;
+ host->interval = interval_g;
WARNING ("snmp plugin: Data for host `%s' will be collected every %i seconds.",
- host->name, host->skip_num);
+ host->name, host->interval);
}
csnmp_host_open_session (host);
if (host->state != STATE_IDLE)
continue;
- host->skip_left -= interval_g;
- if (host->skip_left >= interval_g)
+ /* Skip this host if the next or a later iteration will be sufficient. */
+ if (host->next_update >= (now + interval_g))
continue;
host->state = STATE_WAIT;
-
- host->skip_left = host->skip_num;
+ host->next_update = now + host->interval;
} /* for (host) */
pthread_cond_broadcast (&host_cond);