Merge branch 'ff/snmp'
authorFlorian Forster <octo@leeloo.lan.home.verplant.org>
Sun, 3 Jun 2007 20:43:43 +0000 (22:43 +0200)
committerFlorian Forster <octo@leeloo.lan.home.verplant.org>
Sun, 3 Jun 2007 20:43:43 +0000 (22:43 +0200)
12 files changed:
ChangeLog
README
configure.in
contrib/PerlLib/Collectd.pm [new file with mode: 0644]
src/collectd-exec.pod
src/collectd-perl.pod
src/collectd-unixsock.pod
src/common.c
src/common.h
src/exec.c
src/perl.c
src/unixsock.c

index afcb453..ac1d9c7 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,4 +1,4 @@
-2007-04-02, Version 4.0.0
+2007-06-03, Version 4.0.0
        * collectd: The plugin-infrastructure has been changed to allow for
          more types of plugins, namely `write' and `log' plugins.
        * collectd: The read-function has been changed to read many plugins in
@@ -42,6 +42,7 @@
          connections) field was added by Florent Monbillard.
        * collectd-nagios: The new `collectd-nagios' binary queries values
          from collectd, parses them and exits according to Nagios-standards.
+       * manpages: The manpages have been improved a lot.
 
 2007-05-29, Version 3.11.5
        * configure: Added `AC_SYS_LARGEFILE' for LFS.
diff --git a/README b/README
index 555af86..794511c 100644 (file)
--- a/README
+++ b/README
@@ -112,6 +112,9 @@ Features
       write your own plugins in Perl and return arbitary values using this
       API. See collectd-perl(5).
 
+      This plugin is still considered to be experimental and subject to change
+      between minor releases.
+
     - ping
       Network latency: Time to reach the default gateway or another given
       host.
index f259bf6..443dbde 100644 (file)
@@ -1,5 +1,5 @@
 dnl Process this file with autoconf to produce a configure script.
-AC_INIT(collectd, 4.0.0-rc10)
+AC_INIT(collectd, 4.0.0)
 AC_CONFIG_SRCDIR(src/collectd.c)
 AC_CONFIG_HEADERS(src/config.h)
 AM_INIT_AUTOMAKE(dist-bzip2)
diff --git a/contrib/PerlLib/Collectd.pm b/contrib/PerlLib/Collectd.pm
new file mode 100644 (file)
index 0000000..9f50f18
--- /dev/null
@@ -0,0 +1,52 @@
+# collectd - Collectd.pm
+# Copyright (C) 2007  Sebastian Harl
+#
+# 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
+#
+# Author:
+#   Sebastian Harl <sh at tokkee.org>
+
+package Collectd;
+
+use strict;
+use warnings;
+
+require Exporter;
+
+our @ISA = qw( Exporter );
+
+our %EXPORT_TAGS = (
+       'funcs'    => [ qw( plugin_register plugin_unregister
+                           plugin_dispatch_values plugin_log ) ],
+       'types'    => [ qw( TYPE_INIT TYPE_READ TYPE_WRITE TYPE_SHUTDOWN TYPE_LOG
+                           TYPE_DATASET ) ],
+       'ds_types' => [ qw( DS_TYPE_COUNTER DS_TYPE_GAUGE ) ],
+       'log'      => [ qw( LOG_ERR LOG_WARNING LOG_NOTICE LOG_INFO LOG_DEBUG ) ],
+);
+
+{
+       my %seen;
+
+       push @{$EXPORT_TAGS{'all'}}, grep {! $seen{$_}++ } @{$EXPORT_TAGS{$_}}
+               foreach keys %EXPORT_TAGS;
+}
+
+Exporter::export_ok_tags('all');
+
+bootstrap Collectd "4.0.0";
+
+1;
+
+# vim: set sw=4 ts=4 tw=78 noexpandtab :
+
index cb6069c..0baf2eb 100644 (file)
@@ -15,7 +15,7 @@ collectd-exec - Documentation of collectd's C<exec plugin>
 =head1 DESCRIPTION
 
 The C<exec plugin> forks of an executable and reads back values that it writes
-to C<STDOUT>. The executable is forked in a fassion similar to L<init>: It is
+to C<STDOUT>. The executable is forked in a fashion similar to L<init>: It is
 forked once and not again until it exits. If it exited, it will be forked again
 after at most I<Interval> seconds. It is perfectly legal for the executable to
 run for a long time and continuously write values to C<STDOUT>.
@@ -36,16 +36,27 @@ Each line beginning with a C<#> (hash mark) is ignored.
 
 =item
 
-Any other line must be of the form C<I<type>,I<type-instance>,I<value>>, where
-I<type> is either B<counter> or B<gauge>, I<type-instance> may not contain
-C<,> (comma), C</> (slash) and C<\0> (null byte) and I<value> is either an
-integer (if I<type> is B<counter>) or a floating-point number (if I<type> is
-B<gauge>).
+Other lines must consist of an I<Identifier> and a I<Value-List>, separated by
+a space. A description of these two parts follows:
 
-=back
+An I<Identifier> is of the form
+C<I<host>B</>I<plugin>B<->I<instance>B</>I<type>B<->I<instance>> with both
+I<instance>-parts being optional. If they're omitted the hyphen must be
+omitted, too.
+
+A I<Value-List> is a colon-separated list of values, prepended by the time
+stamp in epoch, i.E<nbsp>e. the same format RRDTool uses, see L<rrdupdate(1)>.
+As with the argument passed to RRDTool you can use B<N> as the current time and
+B<U> for undefined values. However, undefined values can only passed for
+B<GAUGE> values. When setting B<U> for a B<COUNTER> data source the behavior is
+undefined.
+
+Since examples usually let one understand a lot better, here are some:
 
-The values are always considered to be "fresh", i.E<nbsp>e. the time is set to
-"now".
+  leeloo/cpu-0/cpu-idle N:2299366
+  alice/interface/if_octets-eth0 1180647081:421465:479194
+
+=back
 
 When collectd exits it sends a B<SIGTERM> to all still running
 child-processes upon which they have to quit.
@@ -72,6 +83,7 @@ must have an UID that is non-zero.
 L<collectd(1)>,
 L<collectd.conf(5)>,
 L<collectd-perl(5)>,
+L<collectd-unixsock(5)>,
 L<fork(2)>, L<exec(3)>
 
 =head1 AUTHOR
index 90a35da..7b74eee 100644 (file)
@@ -21,6 +21,9 @@ plugins for collectd in Perl. This is a lot more performant than executing a
 Perl-script every time you want to read a value with the C<exec plugin> (see
 L<collectd-exec(5)>) and provides a lot more functionality, too.
 
+Please note that this is still considered to be experimental and subject to
+change between minor releases.
+
 =head1 DATA TYPES
 
 There are two more complex types you need to know about:
index 55e46b8..7c0e316 100644 (file)
@@ -54,10 +54,11 @@ Example:
 
 Submits a value (identified by I<Identifier>, see below) to the daemon which
 will dispatch it to all it's write-plugins. The I<Valuelist> is a
-colon-seperated list of values, either an integer if the data-source is a
-counter, of a double if the data-source if of type "gauge". You can submit an
-undefined gauge-value by using B<U>. When submitting B<U> to a counter the
-behavior is undefined.
+colon-seperated list of the time and the values, each either an integer if the
+data-source is a counter, of a double if the data-source if of type "gauge".
+You can submit an undefined gauge-value by using B<U>. When submitting B<U> to
+a counter the behavior is undefined. The time is given as epoch (i.E<nbsp>e.
+standard UNIX time).
 
 Example:
   -> | PUTVAL testhost/interface/if_octets-test0 1179574444:123:456
index 9a28cdb..1addb32 100644 (file)
@@ -555,3 +555,91 @@ int format_name (char *ret, int ret_len,
                return (-1);
        return (0);
 } /* int format_name */
+
+int parse_identifier (char *str, char **ret_host,
+               char **ret_plugin, char **ret_plugin_instance,
+               char **ret_type, char **ret_type_instance)
+{
+       char *hostname = NULL;
+       char *plugin = NULL;
+       char *plugin_instance = NULL;
+       char *type = NULL;
+       char *type_instance = NULL;
+
+       hostname = str;
+       if (hostname == NULL)
+               return (-1);
+
+       plugin = strchr (hostname, '/');
+       if (plugin == NULL)
+               return (-1);
+       *plugin = '\0'; plugin++;
+
+       type = strchr (plugin, '/');
+       if (type == NULL)
+               return (-1);
+       *type = '\0'; type++;
+
+       plugin_instance = strchr (plugin, '-');
+       if (plugin_instance != NULL)
+       {
+               *plugin_instance = '\0';
+               plugin_instance++;
+       }
+
+       type_instance = strchr (type, '-');
+       if (type_instance != NULL)
+       {
+               *type_instance = '\0';
+               type_instance++;
+       }
+
+       *ret_host = hostname;
+       *ret_plugin = plugin;
+       *ret_plugin_instance = plugin_instance;
+       *ret_type = type;
+       *ret_type_instance = type_instance;
+       return (0);
+} /* int parse_identifier */
+
+int parse_values (char *buffer, value_list_t *vl, const data_set_t *ds)
+{
+       int i;
+       char *dummy;
+       char *ptr;
+       char *saveptr;
+
+       i = -1;
+       dummy = buffer;
+       saveptr = NULL;
+       while ((ptr = strtok_r (dummy, ":", &saveptr)) != NULL)
+       {
+               dummy = NULL;
+
+               if (i >= vl->values_len)
+                       break;
+
+               if (i == -1)
+               {
+                       if (strcmp ("N", ptr) == 0)
+                               vl->time = time (NULL);
+                       else
+                               vl->time = (time_t) atoi (ptr);
+               }
+               else
+               {
+                       if (strcmp ("U", ptr) == 0)
+                               vl->values[i].gauge = NAN;
+                       else if (ds->ds[i].type == DS_TYPE_COUNTER)
+                               vl->values[i].counter = atoll (ptr);
+                       else if (ds->ds[i].type == DS_TYPE_GAUGE)
+                               vl->values[i].gauge = atof (ptr);
+               }
+
+               i++;
+       } /* while (strtok_r) */
+
+       if ((ptr != NULL) || (i != vl->values_len))
+               return (-1);
+       return (0);
+} /* int parse_values */
index 7808ac9..b07db9d 100644 (file)
@@ -24,6 +24,7 @@
 #define COMMON_H
 
 #include "collectd.h"
+#include "plugin.h"
 
 #define sfree(ptr) \
        if((ptr) != NULL) { \
@@ -166,4 +167,9 @@ int format_name (char *ret, int ret_len,
        format_name (ret, ret_len, (vl)->host, (vl)->plugin, (vl)->plugin_instance, \
                        (ds)->type, (vl)->type_instance)
 
+int parse_identifier (char *str, char **ret_host,
+               char **ret_plugin, char **ret_plugin_instance,
+               char **ret_type, char **ret_type_instance);
+int parse_values (char *buffer, value_list_t *vl, const data_set_t *ds);
+
 #endif /* COMMON_H */
index bd96e07..d726f70 100644 (file)
@@ -104,46 +104,6 @@ static int exec_config (const char *key, const char *value)
   return (0);
 } /* int exec_config */
 
-static void submit_counter (const char *type_instance, counter_t value)
-{
-  value_t values[1];
-  value_list_t vl = VALUE_LIST_INIT;
-
-  DEBUG ("type_instance = %s; value = %llu;", type_instance, value);
-
-  values[0].counter = value;
-
-  vl.values = values;
-  vl.values_len = 1;
-  vl.time = time (NULL);
-  strcpy (vl.host, hostname_g);
-  strcpy (vl.plugin, "exec");
-  strcpy (vl.plugin_instance, "");
-  strncpy (vl.type_instance, type_instance, sizeof (vl.type_instance));
-
-  plugin_dispatch_values ("counter", &vl);
-} /* void submit_counter */
-
-static void submit_gauge (const char *type_instance, gauge_t value)
-{
-  value_t values[1];
-  value_list_t vl = VALUE_LIST_INIT;
-
-  DEBUG ("type_instance = %s; value = %lf;", type_instance, value);
-
-  values[0].gauge = value;
-
-  vl.values = values;
-  vl.values_len = 1;
-  vl.time = time (NULL);
-  strcpy (vl.host, hostname_g);
-  strcpy (vl.plugin, "exec");
-  strcpy (vl.plugin_instance, "");
-  strncpy (vl.type_instance, type_instance, sizeof (vl.type_instance));
-
-  plugin_dispatch_values ("gauge", &vl);
-} /* void submit_counter */
-
 static void exec_child (program_list_t *pl)
 {
   int status;
@@ -242,6 +202,84 @@ static int fork_child (program_list_t *pl)
   return (fd_pipe[0]);
 } /* int fork_child */
 
+static int parse_line (char *buffer)
+{
+  char *fields[4];
+  int fields_num;
+
+  char *hostname;
+  char *plugin;
+  char *plugin_instance;
+  char *type;
+  char *type_instance;
+
+  const data_set_t *ds;
+  value_list_t vl = VALUE_LIST_INIT;
+
+  int status;
+
+  fields_num = strsplit (buffer, fields, 4);
+  if (fields_num != 2)
+  {
+    WARNING ("exec plugin: Number of fields is not 2.");
+    return (-1);
+  }
+
+  status = parse_identifier (fields[0], &hostname,
+      &plugin, &plugin_instance,
+      &type, &type_instance);
+  if (status != 0)
+  {
+    WARNING ("exec plugin: Cannot parse `%s'", fields[0]);
+    return (-1);
+  }
+
+  if ((strlen (hostname) >= sizeof (vl.host))
+      || (strlen (plugin) >= sizeof (vl.plugin))
+      || ((plugin_instance != NULL)
+       && (strlen (plugin_instance) >= sizeof (vl.plugin_instance)))
+      || ((type_instance != NULL)
+       && (strlen (type_instance) >= sizeof (vl.type_instance))))
+  {
+    WARNING ("exec plugin: An identifier is too long.");
+    return (-1);
+  }
+
+  strcpy (vl.host, hostname);
+  strcpy (vl.plugin, plugin);
+  if (plugin_instance != NULL)
+    strcpy (vl.plugin_instance, plugin_instance);
+  if (type_instance != NULL)
+    strcpy (vl.type_instance, type_instance);
+
+  ds = plugin_get_ds (type);
+  if (ds == NULL)
+  {
+    WARNING ("exec plugin: No such type: `%s'", type);
+    return (-1);
+  }
+
+  vl.values_len = ds->ds_num;
+  vl.values = (value_t *) malloc (sizeof (value_t) * vl.values_len);
+  if (vl.values == NULL)
+    return (-1);
+
+  /* Sets vl.values and vl.time */
+  status = parse_values (fields[1], &vl, ds);
+  if (status != 0)
+  {
+    WARNING ("exec plugin: Cannot parse `%s'", fields[1]);
+    sfree (vl.values);
+    return (-1);
+  }
+
+  plugin_dispatch_values (type, &vl);
+
+  sfree (vl.values);
+  
+  return (0);
+} /* int parse_line */
+
 static void *exec_read_one (void *arg)
 {
   program_list_t *pl = (program_list_t *) arg;
@@ -269,9 +307,6 @@ static void *exec_read_one (void *arg)
   while (fgets (buffer, sizeof (buffer), fh) != NULL)
   {
     int len;
-    char *type;
-    char *type_instance;
-    char *value;
 
     len = strlen (buffer);
 
@@ -282,43 +317,7 @@ static void *exec_read_one (void *arg)
 
     DEBUG ("exec plugin: exec_read_one: buffer = %s", buffer);
 
-    if (len < 5)
-      continue;
-
-    if (buffer[0] == '#')
-      continue;
-
-    type = buffer;
-
-    type_instance = strchr (type, ',');
-    if (type_instance == NULL)
-      continue;
-    *type_instance = '\0';
-    type_instance++;
-
-    if ((strcasecmp ("counter", type) != 0)
-       && (strcasecmp ("gauge", type) != 0))
-    {
-      WARNING ("exec plugin: Received invalid type: %s", type);
-      continue;
-    }
-
-    value = strchr (type_instance, ',');
-    if (value == NULL)
-    {
-      WARNING ("exec plugin: type-instance is missing.");
-      continue;
-    }
-    *value = '\0';
-    value++;
-
-    DEBUG ("exec plugin: exec_read_one: type = %s; type_instance = %s; "
-       "value = %s;", type, type_instance, value);
-
-    if (strcasecmp ("counter", type) == 0)
-      submit_counter (type_instance, atoll (value));
-    else
-      submit_gauge (type_instance, atof (value));
+    parse_line (buffer);
   } /* while (fgets) */
 
   fclose (fh);
index bcf7bb1..1ad7248 100644 (file)
@@ -25,7 +25,6 @@
  */
 
 #include "collectd.h"
-#include "common.h"
 
 #include "configfile.h"
 
@@ -41,6 +40,7 @@
 
 /* ... while we want the definition found in plugin.h. */
 #include "plugin.h"
+#include "common.h"
 
 #define PLUGIN_INIT     0
 #define PLUGIN_READ     1
index 9793659..215abdd 100644 (file)
@@ -84,52 +84,6 @@ static unsigned int     cache_oldest = UINT_MAX;
 /*
  * Functions
  */
-static int parse_identifier (char *str, char **ret_host,
-               char **ret_plugin, char **ret_plugin_instance,
-               char **ret_type, char **ret_type_instance)
-{
-       char *hostname = NULL;
-       char *plugin = NULL;
-       char *plugin_instance = NULL;
-       char *type = NULL;
-       char *type_instance = NULL;
-
-       hostname = str;
-       if (hostname == NULL)
-               return (-1);
-
-       plugin = strchr (hostname, '/');
-       if (plugin == NULL)
-               return (-1);
-       *plugin = '\0'; plugin++;
-
-       type = strchr (plugin, '/');
-       if (type == NULL)
-               return (-1);
-       *type = '\0'; type++;
-
-       plugin_instance = strchr (plugin, '-');
-       if (plugin_instance != NULL)
-       {
-               *plugin_instance = '\0';
-               plugin_instance++;
-       }
-
-       type_instance = strchr (type, '-');
-       if (type_instance != NULL)
-       {
-               *type_instance = '\0';
-               type_instance++;
-       }
-
-       *ret_host = hostname;
-       *ret_plugin = plugin;
-       *ret_plugin_instance = plugin_instance;
-       *ret_type = type;
-       *ret_type_instance = type_instance;
-       return (0);
-} /* int parse_identifier */
-
 static value_cache_t *cache_search (const char *name)
 {
        value_cache_t *vc;
@@ -568,12 +522,12 @@ static int us_handle_putval (FILE *fh, char **fields, int fields_num)
                return (-1);
        }
 
-       if ((strlen (hostname) > sizeof (vl.host))
-                       || (strlen (plugin) > sizeof (vl.plugin))
+       if ((strlen (hostname) >= sizeof (vl.host))
+                       || (strlen (plugin) >= sizeof (vl.plugin))
                        || ((plugin_instance != NULL)
-                               && (strlen (plugin_instance) > sizeof (vl.plugin_instance)))
+                               && (strlen (plugin_instance) >= sizeof (vl.plugin_instance)))
                        || ((type_instance != NULL)
-                               && (strlen (type_instance) > sizeof (vl.type_instance))))
+                               && (strlen (type_instance) >= sizeof (vl.type_instance))))
        {
                fprintf (fh, "-1 Identifier too long.");
                return (-1);