AC_CHECK_HEADERS(sys/types.h)
AC_CHECK_HEADERS(sys/socket.h)
AC_CHECK_HEADERS(sys/select.h)
-AC_CHECK_HEADERS(sys/poll.h)
+AC_CHECK_HEADERS(poll.h)
AC_CHECK_HEADERS(netdb.h)
AC_CHECK_HEADERS(arpa/inet.h)
AC_CHECK_HEADERS(sys/resource.h)
# include <netinet/ip6.h>
#endif
])
+AC_CHECK_HEADERS(netinet/tcp.h, [], [],
+[#if HAVE_STDINT_H
+# include <stdint.h>
+#endif
+#if HAVE_SYS_TYPES_H
+# include <sys/types.h>
+#endif
+#if HAVE_NETINET_IN_SYSTM_H
+# include <netinet/in_systm.h>
+#endif
+#if HAVE_NETINET_IN_H
+# include <netinet/in.h>
+#endif
+#if HAVE_NETINET_IP_H
+# include <netinet/ip.h>
+#endif
+])
AC_CHECK_HEADERS(netinet/udp.h, [], [],
[#if HAVE_STDINT_H
# include <stdint.h>
AC_CHECK_HEADERS(net/if_ppp.h)
AC_CHECK_HEADERS(netinet/if_ether.h)
+# For the multimeter plugin
+AC_CHECK_HEADERS(termios.h)
+AC_CHECK_HEADERS(sys/ioctl.h)
+
dnl Checking for libraries
AC_CHECK_LIB(m, ext)
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([entropy], [disable], [module], [entropy statistics])
AC_COLLECTD([hddtemp], [disable], [module], [hdd temperature statistics])
AC_COLLECTD([load], [disable], [module], [system load statistics])
AC_COLLECTD([mbmon], [disable], [module], [motherboard monitor statistics])
AC_COLLECTD([memory], [disable], [module], [memory statistics])
AC_COLLECTD([multimeter],[disable], [module], [multimeter statistics])
AC_COLLECTD([mysql], [disable], [module], [mysql statistics])
+AC_COLLECTD([network], [disable], [module], [network functionality])
AC_COLLECTD([nfs], [disable], [module], [nfs statistics])
AC_COLLECTD([ntpd], [disable], [module], [nfs statistics])
AC_COLLECTD([ping], [disable], [module], [ping statistics])
AC_COLLECTD([swap], [disable], [module], [swap statistics])
AC_COLLECTD([tape], [disable], [module], [tape statistics])
AC_COLLECTD([traffic], [disable], [module], [system traffic statistics])
+AC_COLLECTD([unixsock], [disable], [module], [UNIX socket plugin])
AC_COLLECTD([users], [disable], [module], [user count statistics])
AC_COLLECTD([vserver], [disable], [module], [vserver statistics])
AC_COLLECTD([wireless], [disable], [module], [wireless link statistics])
battery . . . . . . $enable_battery
cpu . . . . . . . . $enable_cpu
cpufreq . . . . . . $enable_cpufreq
+ csv . . . . . . . . $enable_csv
df . . . . . . . . $enable_df
disk . . . . . . . $enable_disk
dns . . . . . . . . $enable_dns
email . . . . . . . $enable_email
+ entropy . . . . . . $enable_entropy
hddtemp . . . . . . $enable_hddtemp
load . . . . . . . $enable_load
mbmon . . . . . . . $enable_mbmon
memory . . . . . . $enable_memory
multimeter . . . . $enable_multimeter
mysql . . . . . . . $enable_mysql
+ network . . . . . . $enable_network
nfs . . . . . . . . $enable_nfs
ntpd . . . . . . . $enable_ntpd
ping . . . . . . . $enable_ping
swap . . . . . . . $enable_swap
tape . . . . . . . $enable_tape
traffic . . . . . . $enable_traffic
+ unixsock . . . . . $enable_unixsock
users . . . . . . . $enable_users
vserver . . . . . . $enable_vserver
wireless . . . . . $enable_wireless
endif
sbin_PROGRAMS = collectd
+bin_PROGRAMS = collectd-nagios
collectd_SOURCES = collectd.c collectd.h \
utils_debug.c utils_debug.h \
utils_mount.c utils_mount.h \
+ utils_llist.c utils_llist.h \
utils_ignorelist.c utils_ignorelist.h \
common.c common.h \
- network.c network.h \
plugin.c plugin.h \
configfile.c configfile.h
collectd_CPPFLAGS = $(LTDLINCL)
+collectd_CPPFLAGS += -DPREFIX='"${prefix}"'
collectd_CPPFLAGS += -DCONFIGFILE='"${sysconfdir}/${PACKAGE_NAME}.conf"'
collectd_CPPFLAGS += -DPKGLOCALSTATEDIR='"${localstatedir}/lib/${PACKAGE_NAME}"'
if BUILD_FEATURE_DAEMON
# Link to these libraries..
collectd_LDFLAGS = -export-dynamic
-if BUILD_WITH_RRDTOOL
-collectd_LDFLAGS += -lm -lrrd
-endif
if BUILD_WITH_LIBRT
collectd_LDFLAGS += -lrt
endif
collectd_LDADD = $(LIBLTDL) libconfig/libconfig.la "-dlopen" self
collectd_DEPENDENCIES = $(LIBLTDL) libconfig/libconfig.la
+collectd_nagios_SOURCES = collectd-nagios.c
+
pkglib_LTLIBRARIES =
if BUILD_MODULE_APACHE
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
collectd_DEPENDENCIES += email.la
endif
+if BUILD_MODULE_ENTROPY
+pkglib_LTLIBRARIES += entropy.la
+entropy_la_SOURCES = entropy.c
+entropy_la_LDFLAGS = -module -avoid-version
+collectd_LDADD += "-dlopen" entropy.la
+collectd_DEPENDENCIES += entropy.la
+endif
+
#if BUILD_MODULE_QUOTA
#pkglib_LTLIBRARIES += quota.la
#quota_la_SOURCES = quota_plugin.c quota_plugin.h
collectd_DEPENDENCIES += mysql.la
endif
+if BUILD_MODULE_NETWORK
+pkglib_LTLIBRARIES += network.la
+network_la_SOURCES = network.c
+network_la_LDFLAGS = -module -avoid-version
+if BUILD_WITH_LIBSOCKET
+network_la_LDFLAGS += -lsocket
+endif
+if BUILD_WITH_LIBPTHREAD
+network_la_LDFLAGS += -lpthread
+endif
+collectd_LDADD += "-dlopen" network.la
+collectd_DEPENDENCIES += network.la
+endif
+
if BUILD_MODULE_NFS
pkglib_LTLIBRARIES += nfs.la
nfs_la_SOURCES = nfs.c
collectd_DEPENDENCIES += processes.la
endif
+if BUILD_WITH_RRDTOOL
+pkglib_LTLIBRARIES += rrdtool.la
+rrdtool_la_SOURCES = rrdtool.c
+rrdtool_la_LDFLAGS = -module -avoid-version -lrrd
+collectd_LDADD += "-dlopen" rrdtool.la
+collectd_DEPENDENCIES += rrdtool.la
+endif
+
if BUILD_MODULE_SENSORS
pkglib_LTLIBRARIES += sensors.la
sensors_la_SOURCES = sensors.c
endif
endif
+if BUILD_MODULE_UNIXSOCK
+pkglib_LTLIBRARIES += unixsock.la
+unixsock_la_SOURCES = unixsock.c
+unixsock_la_LDFLAGS = -module -avoid-version
+if BUILD_WITH_LIBPTHREAD
+unixsock_la_LDFLAGS += -lpthread
+endif
+collectd_LDADD += "-dlopen" unixsock.la
+collectd_DEPENDENCIES += unixsock.la
+endif
+
if BUILD_MODULE_USERS
pkglib_LTLIBRARIES += users.la
users_la_SOURCES = users.c
*
* 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; either version 2 of the License, or (at your
- * option) any later version.
+ * 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
#include "common.h"
#include "plugin.h"
#include "configfile.h"
-
-#define MODULE_NAME "apache"
+#include "utils_debug.h"
#if HAVE_LIBCURL && HAVE_CURL_CURL_H
# define APACHE_HAVE_READ 1
# define APACHE_HAVE_READ 0
#endif
-static char *url = NULL;
-static char *user = NULL;
-static char *pass = NULL;
-static char *cacert = NULL;
-
-#if HAVE_LIBCURL
-static CURL *curl = NULL;
-
-#define ABUFFER_SIZE 16384
-static char apache_buffer[ABUFFER_SIZE];
-static int apache_buffer_len = 0;
-static char apache_curl_error[CURL_ERROR_SIZE];
-#endif /* HAVE_LIBCURL */
-
/* Limit to 2^27 bytes/s. That's what a gigabit-ethernet link can handle, in
* theory. */
-static char *bytes_file = "apache/apache_bytes.rrd";
-static char *bytes_ds_def[] =
+static data_source_t apache_bytes_dsrc[1] =
{
- "DS:count:COUNTER:"COLLECTD_HEARTBEAT":0:134217728",
- NULL
+ {"count", DS_TYPE_COUNTER, 0, 134217728.0},
+};
+
+static data_set_t apache_bytes_ds =
+{
+ "apache_bytes", 1, apache_bytes_dsrc
};
-static int bytes_ds_num = 1;
/* Limit to 2^20 requests/s */
-static char *requests_file = "apache/apache_requests.rrd";
-static char *requests_ds_def[] =
+static data_source_t apache_requests_dsrc[1] =
{
- "DS:count:COUNTER:"COLLECTD_HEARTBEAT":0:1048576",
- NULL
+ {"count", DS_TYPE_COUNTER, 0, 134217728.0},
};
-static int requests_ds_num = 1;
-static char *scoreboard_file = "apache/apache_scoreboard-%s.rrd";
-static char *scoreboard_ds_def[] =
+static data_set_t apache_requests_ds =
{
- "DS:count:GAUGE:"COLLECTD_HEARTBEAT":0:U",
- NULL
+ "apache_requests", 1, apache_requests_dsrc
+};
+
+static data_source_t apache_scoreboard_dsrc[1] =
+{
+ {"count", DS_TYPE_GAUGE, 0, 65535.0},
+};
+
+static data_set_t apache_scoreboard_ds =
+{
+ "apache_scoreboard", 1, apache_scoreboard_dsrc
};
-static int scoreboard_ds_num = 1;
-static char *config_keys[] =
+#if APACHE_HAVE_READ
+static char *url = NULL;
+static char *user = NULL;
+static char *pass = NULL;
+static char *cacert = NULL;
+
+static CURL *curl = NULL;
+
+#define ABUFFER_SIZE 16384
+static char apache_buffer[ABUFFER_SIZE];
+static int apache_buffer_len = 0;
+static char apache_curl_error[CURL_ERROR_SIZE];
+
+static const char *config_keys[] =
{
"URL",
"User",
};
static int config_keys_num = 4;
-#if HAVE_LIBCURL
static size_t apache_curl_callback (void *buf, size_t size, size_t nmemb, void *stream)
{
size_t len = size * nmemb;
return (len);
}
-#endif /* HAVE_LIBCURL */
-static int config_set (char **var, char *value)
+static int config_set (char **var, const char *value)
{
if (*var != NULL)
{
return (0);
}
-static int config (char *key, char *value)
+static int config (const char *key, const char *value)
{
if (strcasecmp (key, "url") == 0)
return (config_set (&url, value));
return (-1);
}
-static void init (void)
+static int init (void)
{
-#if HAVE_LIBCURL
static char credentials[1024];
if (curl != NULL)
if ((curl = curl_easy_init ()) == NULL)
{
syslog (LOG_ERR, "apache: `curl_easy_init' failed.");
- return;
+ return (-1);
}
curl_easy_setopt (curl, CURLOPT_WRITEFUNCTION, apache_curl_callback);
if (snprintf (credentials, 1024, "%s:%s", user, pass == NULL ? "" : pass) >= 1024)
{
syslog (LOG_ERR, "apache: Credentials would have been truncated.");
- return;
+ return (-1);
}
curl_easy_setopt (curl, CURLOPT_USERPWD, credentials);
{
curl_easy_setopt (curl, CURLOPT_CAINFO, cacert);
}
-#endif /* HAVE_LIBCURL */
-}
-static void bytes_write (char *host, char *inst, char *val)
-{
- rrd_update_file (host, bytes_file, val, bytes_ds_def, bytes_ds_num);
-}
+ return (0);
+} /* int init */
-static void requests_write (char *host, char *inst, char *val)
+static void submit_counter (const char *type, const char *type_instance,
+ unsigned long long value)
{
- rrd_update_file (host, requests_file, val, requests_ds_def, requests_ds_num);
-}
+ value_t values[1];
+ value_list_t vl = VALUE_LIST_INIT;
-static void scoreboard_write (char *host, char *inst, char *val)
-{
- char buf[1024];
+ DBG ("type = %s; type_instance = %s; value = %llu;",
+ type, type_instance, value);
- if (snprintf (buf, 1024, scoreboard_file, inst) >= 1024)
- return;
+ values[0].counter = value;
- rrd_update_file (host, buf, val, scoreboard_ds_def, scoreboard_ds_num);
-}
+ vl.values = values;
+ vl.values_len = 1;
+ vl.time = time (NULL);
+ strcpy (vl.host, hostname);
+ strcpy (vl.plugin, "apache");
+ strcpy (vl.plugin_instance, "");
+ strncpy (vl.type_instance, type_instance, sizeof (vl.type_instance));
-#if APACHE_HAVE_READ
-static void submit (char *type, char *inst, long long value)
+ plugin_dispatch_values (type, &vl);
+} /* void submit_counter */
+
+static void submit_gauge (const char *type, const char *type_instance,
+ double value)
{
- char buf[1024];
- int status;
+ value_t values[1];
+ value_list_t vl = VALUE_LIST_INIT;
- status = snprintf (buf, 1024, "%u:%lli", (unsigned int) curtime, value);
- if (status < 0)
- {
- syslog (LOG_ERR, "apache: bytes_submit: snprintf failed");
- return;
- }
- else if (status >= 1024)
- {
- syslog (LOG_WARNING, "apache: bytes_submit: snprintf was truncated");
- return;
- }
+ DBG ("type = %s; type_instance = %s; value = %lf;",
+ type, type_instance, value);
- plugin_submit (type, inst, buf);
-}
+ values[0].gauge = value;
+
+ vl.values = values;
+ vl.values_len = 1;
+ vl.time = time (NULL);
+ strcpy (vl.host, hostname);
+ strcpy (vl.plugin, "apache");
+ strcpy (vl.plugin_instance, "");
+ strncpy (vl.type_instance, type_instance, sizeof (vl.type_instance));
+
+ plugin_dispatch_values (type, &vl);
+} /* void submit_counter */
static void submit_scoreboard (char *buf)
{
else if (buf[i] == 'I') idle_cleanup++;
}
- submit ("apache_scoreboard", "open" , open);
- submit ("apache_scoreboard", "waiting" , waiting);
- submit ("apache_scoreboard", "starting" , starting);
- submit ("apache_scoreboard", "reading" , reading);
- submit ("apache_scoreboard", "sending" , sending);
- submit ("apache_scoreboard", "keepalive", keepalive);
- submit ("apache_scoreboard", "dnslookup", dnslookup);
- submit ("apache_scoreboard", "closing" , closing);
- submit ("apache_scoreboard", "logging" , logging);
- submit ("apache_scoreboard", "finishing", finishing);
- submit ("apache_scoreboard", "idle_cleanup", idle_cleanup);
+ submit_gauge ("apache_scoreboard", "open" , open);
+ submit_gauge ("apache_scoreboard", "waiting" , waiting);
+ submit_gauge ("apache_scoreboard", "starting" , starting);
+ submit_gauge ("apache_scoreboard", "reading" , reading);
+ submit_gauge ("apache_scoreboard", "sending" , sending);
+ submit_gauge ("apache_scoreboard", "keepalive", keepalive);
+ submit_gauge ("apache_scoreboard", "dnslookup", dnslookup);
+ submit_gauge ("apache_scoreboard", "closing" , closing);
+ submit_gauge ("apache_scoreboard", "logging" , logging);
+ submit_gauge ("apache_scoreboard", "finishing", finishing);
+ submit_gauge ("apache_scoreboard", "idle_cleanup", idle_cleanup);
}
-static void apache_read (void)
+static int apache_read (void)
{
int i;
int fields_num;
if (curl == NULL)
- return;
+ return (-1);
if (url == NULL)
- return;
+ return (-1);
apache_buffer_len = 0;
if (curl_easy_perform (curl) != 0)
{
- syslog (LOG_WARNING, "apache: curl_easy_perform failed: %s", apache_curl_error);
- return;
+ syslog (LOG_ERR, "apache: curl_easy_perform failed: %s",
+ apache_curl_error);
+ return (-1);
}
ptr = apache_buffer;
{
if ((strcmp (fields[0], "Total") == 0)
&& (strcmp (fields[1], "Accesses:") == 0))
- submit ("apache_requests", NULL, atoll (fields[2]));
+ submit_counter ("apache_requests", "",
+ atoll (fields[2]));
else if ((strcmp (fields[0], "Total") == 0)
&& (strcmp (fields[1], "kBytes:") == 0))
- submit ("apache_bytes", NULL, 1024LL * atoll (fields[2]));
+ submit_counter ("apache_bytes", "",
+ 1024LL * atoll (fields[2]));
}
else if (fields_num == 2)
{
}
apache_buffer_len = 0;
-}
-#else
-# define apache_read NULL
+
+ return (0);
+} /* int apache_read */
#endif /* APACHE_HAVE_READ */
void module_register (void)
{
- plugin_register (MODULE_NAME, init, apache_read, NULL);
- plugin_register ("apache_requests", NULL, NULL, requests_write);
- plugin_register ("apache_bytes", NULL, NULL, bytes_write);
- plugin_register ("apache_scoreboard", NULL, NULL, scoreboard_write);
- cf_register (MODULE_NAME, config, config_keys, config_keys_num);
-}
+ plugin_register_data_set (&apache_bytes_ds);
+ plugin_register_data_set (&apache_requests_ds);
+ plugin_register_data_set (&apache_scoreboard_ds);
-#undef MODULE_NAME
+#if APACHE_HAVE_READ
+ plugin_register_config ("apache", config,
+ config_keys, config_keys_num);
+ plugin_register_init ("apache", init);
+ plugin_register_read ("apache", apache_read);
+#endif
+}
# include <netinet/in.h>
#endif
-#ifndef APCMAIN
-# define APCMAIN 0
-#endif
-
#define NISPORT 3551
#define MAXSTRING 256
#define MODULE_NAME "apcups"
#define APCUPS_DEFAULT_HOST "localhost"
+/*
+ * Private data types
+ */
+struct apc_detail_s
+{
+ double linev;
+ double loadpct;
+ double bcharge;
+ double timeleft;
+ double outputv;
+ double itemp;
+ double battv;
+ double linefreq;
+};
+
+/*
+ * Private variables
+ */
/* Default values for contacting daemon */
-static char *global_host = NULL;
-static int global_port = NISPORT;
+static char *conf_host = NULL;
+static int conf_port = NISPORT;
+
+static int global_sockfd = -1;
/*
* The following are only if not compiled to test the module with its own main.
*/
-#if !APCMAIN
-static char *bvolt_file_template = "apcups/voltage-%s.rrd";
-static char *bvolt_ds_def[] =
+static data_source_t data_source_voltage[1] =
{
- "DS:voltage:GAUGE:"COLLECTD_HEARTBEAT":0:U",
+ {"value", DS_TYPE_GAUGE, NAN, NAN}
};
-static int bvolt_ds_num = 1;
-static char *load_file_template = "apcups/load_percent.rrd";
-static char *load_ds_def[] =
+static data_set_t ds_voltage =
{
- "DS:percent:GAUGE:"COLLECTD_HEARTBEAT":0:110",
+ "voltage", 1, data_source_voltage
};
-static int load_ds_num = 1;
-static char *charge_file_template = "apcups/charge_percent.rrd";
-static char *charge_ds_def[] =
+static data_source_t data_source_percent[1] =
{
- "DS:percent:GAUGE:"COLLECTD_HEARTBEAT":0:110",
+ {"percent", DS_TYPE_GAUGE, 0, 100.1}
};
-static int charge_ds_num = 1;
-static char *time_file_template = "apcups/timeleft.rrd";
-static char *time_ds_def[] =
+static data_set_t ds_percent =
{
- "DS:timeleft:GAUGE:"COLLECTD_HEARTBEAT":0:100",
+ "percent", 1, data_source_percent
};
-static int time_ds_num = 1;
-static char *temp_file_template = "apcups/temperature.rrd";
-static char *temp_ds_def[] =
+static data_source_t data_source_timeleft[1] =
{
- /* -273.15 is absolute zero */
- "DS:value:GAUGE:"COLLECTD_HEARTBEAT":-274:U",
+ {"timeleft", DS_TYPE_GAUGE, 0, 100.0}
};
-static int temp_ds_num = 1;
-static char *freq_file_template = "apcups/frequency-%s.rrd";
-static char *freq_ds_def[] =
+static data_set_t ds_timeleft =
{
- "DS:frequency:GAUGE:"COLLECTD_HEARTBEAT":0:U",
+ "timeleft", 1, data_source_timeleft
};
-static int freq_ds_num = 1;
-static char *config_keys[] =
+static data_source_t data_source_temperature[1] =
{
- "Host",
- "Port",
- NULL
+ {"value", DS_TYPE_GAUGE, -273.15, NAN}
};
-static int config_keys_num = 2;
-#endif /* if APCMAIN */
+static data_set_t ds_temperature =
+{
+ "temperature", 1, data_source_temperature
+};
-struct apc_detail_s
+static data_source_t data_source_frequency[1] =
{
- double linev;
- double loadpct;
- double bcharge;
- double timeleft;
- double outputv;
- double itemp;
- double battv;
- double linefreq;
+ {"frequency", DS_TYPE_GAUGE, 0, NAN}
+};
+
+static data_set_t ds_frequency =
+{
+ "frequency", 1, data_source_frequency
};
-#define BIG_BUF 4096
+static const char *config_keys[] =
+{
+ "Host",
+ "Port",
+ NULL
+};
+static int config_keys_num = 2;
-#if APCMAIN
/* Close the network connection */
-static void net_close (int *fd)
+static int apcups_shutdown (void)
{
uint16_t packet_size = 0;
- assert (*fd >= 0);
+ if (global_sockfd < 0)
+ return (0);
- DBG ("Gracefully shutting down socket %i.", *fd);
+ DBG ("Gracefully shutting down socket %i.", global_sockfd);
/* send EOF sentinel */
- swrite (*fd, (void *) &packet_size, sizeof (packet_size));
+ swrite (global_sockfd, (void *) &packet_size, sizeof (packet_size));
- close (*fd);
- *fd = -1;
-}
-#endif /* APCMAIN */
+ close (global_sockfd);
+ global_sockfd = -1;
+
+ return (0);
+} /* int apcups_shutdown */
/*
* Open a TCP connection to the UPS network server
char *key;
double value;
- static int sockfd = -1;
static complain_t compl;
#if APCMAIN
# define PRINT_VALUE(name, val) /**/
#endif
- if (sockfd < 0)
+ if (global_sockfd < 0)
{
- if ((sockfd = net_open (host, NULL, port)) < 0)
+ if ((global_sockfd = net_open (host, NULL, port)) < 0)
{
plugin_complain (LOG_ERR, &compl, "apcups plugin: "
"Connecting to the apcupsd failed.");
}
}
- if (net_send (&sockfd, "status", 6) < 0)
+ if (net_send (&global_sockfd, "status", 6) < 0)
{
syslog (LOG_ERR, "apcups plugin: Writing to the socket failed.");
return (-1);
}
- while ((n = net_recv (&sockfd, recvline, sizeof (recvline) - 1)) > 0)
+ while ((n = net_recv (&global_sockfd, recvline, sizeof (recvline) - 1)) > 0)
{
assert (n < sizeof (recvline));
recvline[n] = '\0';
syslog (LOG_WARNING, "apcups plugin: Error reading from socket");
return (-1);
}
-#if APCMAIN
- else
- {
- /* close the opened socket */
- net_close (&sockfd);
- }
-#endif /* APCMAIN */
return (0);
}
-#if APCMAIN
-/*
- * This is used for testing apcups in a standalone mode.
- * Usefull for debugging.
- */
-int main (int argc, char **argv)
-{
- /* we are not really going to use this */
- struct apc_detail_s apcups_detail;
-
- openlog ("apcups", LOG_PID | LOG_NDELAY | LOG_LOCAL1, LOG_USER);
-
- if (global_host == NULL || strcmp (global_host, "0.0.0.0") == 0)
- global_host = "localhost";
-
- if(apc_query_server (global_host, global_port, &apcups_detail) < 0)
- {
- printf("apcups: Failed...\n");
- return(-1);
- }
-
- return 0;
-}
-#else
-static int apcups_config (char *key, char *value)
+static int apcups_config (const char *key, const char *value)
{
if (strcasecmp (key, "host") == 0)
{
- if (global_host != NULL)
+ if (conf_host != NULL)
{
- free (global_host);
- global_host = NULL;
+ free (conf_host);
+ conf_host = NULL;
}
- if ((global_host = strdup (value)) == NULL)
+ if ((conf_host = strdup (value)) == NULL)
return (1);
}
else if (strcasecmp (key, "Port") == 0)
syslog (LOG_WARNING, "apcups plugin: Invalid port: %i", port_tmp);
return (1);
}
- global_port = port_tmp;
+ conf_port = port_tmp;
}
else
{
return (0);
}
-static void apcups_init (void)
-{
- return;
-}
-
-static void apc_write_voltage (char *host, char *inst, char *val)
-{
- char file[512];
- int status;
-
- status = snprintf (file, 512, bvolt_file_template, inst);
- if ((status < 1) || (status >= 512))
- return;
-
- rrd_update_file (host, file, val, bvolt_ds_def, bvolt_ds_num);
-}
-
-static void apc_write_charge (char *host, char *inst, char *val)
-{
- rrd_update_file (host, charge_file_template, val, charge_ds_def, charge_ds_num);
-}
-
-static void apc_write_percent (char *host, char *inst, char *val)
-{
- rrd_update_file (host, load_file_template, val, load_ds_def, load_ds_num);
-}
-
-static void apc_write_timeleft (char *host, char *inst, char *val)
-{
- rrd_update_file (host, time_file_template, val, time_ds_def, time_ds_num);
-}
-
-static void apc_write_temperature (char *host, char *inst, char *val)
-{
- rrd_update_file (host, temp_file_template, val, temp_ds_def, temp_ds_num);
-}
-
-static void apc_write_frequency (char *host, char *inst, char *val)
+static void apc_submit_generic (char *type, char *type_inst, double value)
{
- char file[512];
- int status;
-
- status = snprintf (file, 512, freq_file_template, inst);
- if ((status < 1) || (status >= 512))
- return;
-
- rrd_update_file (host, file, val, freq_ds_def, freq_ds_num);
-}
+ value_t values[1];
+ value_list_t vl = VALUE_LIST_INIT;
-static void apc_submit_generic (char *type, char *inst,
- double value)
-{
- char buf[512];
- int status;
+ values[0].gauge = value;
- status = snprintf (buf, 512, "%u:%f",
- (unsigned int) curtime, value);
- if ((status < 1) || (status >= 512))
- return;
+ vl.values = values;
+ vl.values_len = 1;
+ vl.time = time (NULL);
+ strcpy (vl.host, hostname);
+ strcpy (vl.plugin, "apcups");
+ strcpy (vl.plugin_instance, "");
+ strncpy (vl.type_instance, type_inst, sizeof (vl.type_instance));
- DBG ("plugin_submit (%s, %s, %s);", type, inst, buf);
- plugin_submit (type, inst, buf);
+ plugin_dispatch_values (type, &vl);
}
static void apc_submit (struct apc_detail_s *apcups_detail)
apc_submit_generic ("apcups_voltage", "input", apcups_detail->linev);
apc_submit_generic ("apcups_voltage", "output", apcups_detail->outputv);
apc_submit_generic ("apcups_voltage", "battery", apcups_detail->battv);
- apc_submit_generic ("apcups_charge", "-", apcups_detail->bcharge);
- apc_submit_generic ("apcups_charge_pct", "-", apcups_detail->loadpct);
- apc_submit_generic ("apcups_timeleft", "-", apcups_detail->timeleft);
- apc_submit_generic ("apcups_temp", "-", apcups_detail->itemp);
+ apc_submit_generic ("apcups_charge", "", apcups_detail->bcharge);
+ apc_submit_generic ("apcups_charge_pct", "", apcups_detail->loadpct);
+ apc_submit_generic ("apcups_timeleft", "", apcups_detail->timeleft);
+ apc_submit_generic ("apcups_temp", "", apcups_detail->itemp);
apc_submit_generic ("apcups_frequency", "input", apcups_detail->linefreq);
}
-static void apcups_read (void)
+static int apcups_read (void)
{
struct apc_detail_s apcups_detail;
int status;
apcups_detail.itemp = -300.0;
apcups_detail.linefreq = -1.0;
- status = apc_query_server (global_host == NULL
+ status = apc_query_server (conf_host == NULL
? APCUPS_DEFAULT_HOST
- : global_host,
- global_port, &apcups_detail);
+ : conf_host,
+ conf_port, &apcups_detail);
/*
* if we did not connect then do not bother submitting
if (status != 0)
{
DBG ("apc_query_server (%s, %i) = %i",
- global_host == NULL
+ conf_host == NULL
? APCUPS_DEFAULT_HOST
- : global_host,
- global_port, status);
- return;
+ : conf_host,
+ conf_port, status);
+ return (-1);
}
apc_submit (&apcups_detail);
+
+ return (0);
} /* apcups_read */
void module_register (void)
{
- plugin_register (MODULE_NAME, apcups_init, apcups_read, NULL);
- plugin_register ("apcups_voltage", NULL, NULL, apc_write_voltage);
- plugin_register ("apcups_charge", NULL, NULL, apc_write_charge);
- plugin_register ("apcups_charge_pct", NULL, NULL, apc_write_percent);
- plugin_register ("apcups_timeleft", NULL, NULL, apc_write_timeleft);
- plugin_register ("apcups_temp", NULL, NULL, apc_write_temperature);
- plugin_register ("apcups_frequency", NULL, NULL, apc_write_frequency);
- cf_register (MODULE_NAME, apcups_config, config_keys, config_keys_num);
-}
+ plugin_register_data_set (&ds_voltage);
+ plugin_register_data_set (&ds_percent);
+ plugin_register_data_set (&ds_timeleft);
+ plugin_register_data_set (&ds_temperature);
+ plugin_register_data_set (&ds_frequency);
-#endif /* if APCMAIN */
-#undef MODULE_NAME
+ plugin_register_config ("apcups", apcups_config, config_keys, config_keys_num);
+
+ plugin_register_read ("apcups", apcups_read);
+ plugin_register_shutdown ("apcups", apcups_shutdown);
+}
/**
* collectd - src/apple_sensors.c
- * Copyright (C) 2006 Florian octo Forster
+ * Copyright (C) 2006,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; either version 2 of the License, or (at your
- * option) any later version.
+ * 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
#include "plugin.h"
#include "utils_debug.h"
-#define MODULE_NAME "apple_sensors"
-
#if HAVE_CTYPE_H
# include <ctype.h>
#endif
static mach_port_t io_master_port = MACH_PORT_NULL;
#endif
-static char *temperature_file = "apple_sensors/temperature-%s.rrd";
-static char *fanspeed_file = "apple_sensors/fanspeed-%s.rrd";
+static data_source_t data_source_fanspeed[1] =
+{
+ {"value", DS_TYPE_GAUGE, 0, NAN}
+};
-static char *ds_def[] =
+static data_set_t fanspeed_ds =
{
- "DS:value:GAUGE:"COLLECTD_HEARTBEAT":U:U",
- NULL
+ "fanspeed", 1, data_source_fanspeed
};
-static int ds_num = 1;
-static void as_init (void)
+static data_source_t data_source_temperature[1] =
{
+ {"value", DS_TYPE_GAUGE, -273.15, NAN}
+};
+
+static data_set_t temperature_ds =
+{
+ "temperature", 1, data_source_temperature
+};
+
#if IOKIT_HAVE_READ
+static int as_init (void)
+{
kern_return_t status;
if (io_master_port != MACH_PORT_NULL)
syslog (LOG_ERR, "IOMasterPort failed: %s",
mach_error_string (status));
io_master_port = MACH_PORT_NULL;
- return;
+ return (-1);
}
-#endif /* IOKIT_HAVE_READ */
- return;
+ return (0);
}
-static void as_write (char *host, char *inst, char *val, const char *template)
+static void as_submit (const char *type, const char *type_instance,
+ double val)
{
- char filename[256];
- int status;
+ value_t values[1];
+ value_list_t vl = VALUE_LIST_INIT;
- status = snprintf (filename, 256, template, inst);
- if ((status < 1) || (status >= 256))
- return;
+ DBG ("type = %s; type_instance = %s; val = %f;",
+ type, type_instance, val);
- rrd_update_file (host, filename, val, ds_def, ds_num);
-}
+ values[0].gauge = val;
-static void temperature_write (char *host, char *inst, char *val)
-{
- as_write (host, inst, val, temperature_file);
-}
+ vl.values = values;
+ vl.values_len = 1;
+ vl.time = time (NULL);
+ strcpy (vl.host, hostname);
+ strcpy (vl.plugin, "apple_sensors");
+ strcpy (vl.plugin_instance, "");
+ strcpy (vl.type_instance, type_instance);
-static void fanspeed_write (char *host, char *inst, char *val)
-{
- as_write (host, inst, val, fanspeed_file);
+ plugin_dispatch_values (type, &vl);
}
-#if IOKIT_HAVE_READ
-static void as_submit (char *type, char *inst, double value)
-{
- char buf[128];
-
- if (snprintf (buf, 1024, "%u:%f", (unsigned int) curtime,
- value) >= 128)
- return;
-
- plugin_submit (type, inst, buf);
-}
-
-static void as_read (void)
+static int as_read (void)
{
kern_return_t status;
io_iterator_t iterator;
int i;
if (!io_master_port || (io_master_port == MACH_PORT_NULL))
- return;
+ return (-1);
status = IOServiceGetMatchingServices (io_master_port,
IOServiceNameMatching("IOHWSensor"),
{
syslog (LOG_ERR, "IOServiceGetMatchingServices failed: %s",
mach_error_string (status));
- return;
+ return (-1);
}
while ((io_obj = IOIteratorNext (iterator)))
if (strcmp (type, "temperature") == 0)
{
value_double = ((double) value_int) / 65536.0;
- strncpy (type, "apple_temperature", 128);
+ strcpy (type, "temperature");
}
else if (strcmp (type, "temp") == 0)
{
value_double = ((double) value_int) / 10.0;
- strncpy (type, "apple_temperature", 128);
+ strcpy (type, "temperature");
}
else if (strcmp (type, "fanspeed") == 0)
{
value_double = ((double) value_int) / 65536.0;
- strncpy (type, "apple_fanspeed", 128);
+ strcpy (type, "fanspeed");
}
else if (strcmp (type, "voltage") == 0)
{
else if (strcmp (type, "adc") == 0)
{
value_double = ((double) value_int) / 10.0;
- strncpy (type, "apple_temperature", 128);
+ strcpy (type, "fanspeed");
}
else
{
} /* while (iterator) */
IOObjectRelease (iterator);
-}
-#else
-# define as_read NULL
+
+ return (0);
+} /* int as_read */
#endif /* IOKIT_HAVE_READ */
void module_register (void)
{
- plugin_register (MODULE_NAME, as_init, as_read, NULL);
- plugin_register ("apple_temperature", NULL, NULL, temperature_write);
- plugin_register ("apple_fanspeed", NULL, NULL, fanspeed_write);
-}
+ plugin_register_data_set (&fanspeed_ds);
+ plugin_register_data_set (&temperature_ds);
-#undef MODULE_NAME
+#if IOKIT_HAVE_READ
+ plugin_register_init ("apple_sensors", as_init);
+ plugin_register_read ("apple_sensors", as_read);
+#endif /* IOKIT_HAVE_READ */
+}
/**
* collectd - src/battery.c
- * Copyright (C) 2006 Florian octo Forster
+ * Copyright (C) 2006,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; either version 2 of the License, or (at your
- * option) any later version.
+ * 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
#include "plugin.h"
#include "utils_debug.h"
-#define MODULE_NAME "battery"
-#define BUFSIZE 512
-
#if HAVE_MACH_MACH_TYPES_H
# include <mach/mach_types.h>
#endif
#define INVALID_VALUE 47841.29
-static char *battery_current_file = "battery-%s/current.rrd";
-static char *battery_voltage_file = "battery-%s/voltage.rrd";
-static char *battery_charge_file = "battery-%s/charge.rrd";
+static data_source_t data_source_charge[1] =
+{
+ {"value", DS_TYPE_GAUGE, 0, NAN}
+};
+
+static data_set_t charge_ds =
+{
+ "charge", 1, data_source_charge
+};
+
+static data_source_t data_source_current[1] =
+{
+ {"value", DS_TYPE_GAUGE, NAN, NAN}
+};
-static char *ds_def_current[] =
+static data_set_t current_ds =
{
- "DS:current:GAUGE:"COLLECTD_HEARTBEAT":U:U",
- NULL
+ "current", 1, data_source_current
};
-static int ds_num_current = 1;
-static char *ds_def_voltage[] =
+static data_source_t data_source_voltage[1] =
{
- "DS:voltage:GAUGE:"COLLECTD_HEARTBEAT":U:U",
- NULL
+ {"value", DS_TYPE_GAUGE, NAN, NAN}
};
-static int ds_num_voltage = 1;
-static char *ds_def_charge[] =
+static data_set_t voltage_ds =
{
- "DS:charge:GAUGE:"COLLECTD_HEARTBEAT":0:U",
- NULL
+ "voltage", 1, data_source_voltage
};
-static int ds_num_charge = 1;
+#if BATTERY_HAVE_READ
#if HAVE_IOKIT_IOKITLIB_H || HAVE_IOKIT_PS_IOPOWERSOURCES_H
/* No global variables */
/* #endif HAVE_IOKIT_IOKITLIB_H || HAVE_IOKIT_PS_IOPOWERSOURCES_H */
static char *battery_pmu_file = "/proc/pmu/battery_%i";
#endif /* KERNEL_LINUX */
-static void battery_init (void)
+static int battery_init (void)
{
#if HAVE_IOKIT_IOKITLIB_H || HAVE_IOKIT_PS_IOPOWERSOURCES_H
/* No init neccessary */
#elif KERNEL_LINUX
int len;
- char filename[BUFSIZE];
+ char filename[128];
for (battery_pmu_num = 0; ; battery_pmu_num++)
{
- len = snprintf (filename, BUFSIZE, battery_pmu_file, battery_pmu_num);
+ len = snprintf (filename, sizeof (filename), battery_pmu_file, battery_pmu_num);
- if ((len >= BUFSIZE) || (len < 0))
+ if ((len >= sizeof (filename)) || (len < 0))
break;
if (access (filename, R_OK))
}
#endif /* KERNEL_LINUX */
- return;
-}
-
-static void battery_current_write (char *host, char *inst, char *val)
-{
- char filename[BUFSIZE];
- int len;
-
- len = snprintf (filename, BUFSIZE, battery_current_file, inst);
- if ((len >= BUFSIZE) || (len < 0))
- return;
-
- rrd_update_file (host, filename, val,
- ds_def_current, ds_num_current);
-}
-
-static void battery_voltage_write (char *host, char *inst, char *val)
-{
- char filename[BUFSIZE];
- int len;
-
- len = snprintf (filename, BUFSIZE, battery_voltage_file, inst);
- if ((len >= BUFSIZE) || (len < 0))
- return;
-
- rrd_update_file (host, filename, val,
- ds_def_voltage, ds_num_voltage);
+ return (0);
}
-static void battery_charge_write (char *host, char *inst, char *val)
+static void battery_submit (const char *plugin_instance, const char *type, double value)
{
- char filename[BUFSIZE];
- int len;
-
- len = snprintf (filename, BUFSIZE, battery_charge_file, inst);
- if ((len >= BUFSIZE) || (len < 0))
- return;
+ value_t values[1];
+ value_list_t vl = VALUE_LIST_INIT;
- rrd_update_file (host, filename, val,
- ds_def_charge, ds_num_charge);
-}
+ values[0].gauge = value;
-#if BATTERY_HAVE_READ
-static void battery_submit (char *inst, double current, double voltage, double charge)
-{
- int len;
- char buffer[BUFSIZE];
+ vl.values = values;
+ vl.values_len = 1;
+ vl.time = time (NULL);
+ strcpy (vl.host, hostname);
+ strcpy (vl.plugin, "battery");
+ strcpy (vl.plugin_instance, plugin_instance);
- if (current != INVALID_VALUE)
- {
- len = snprintf (buffer, BUFSIZE, "N:%.3f", current);
-
- if ((len > 0) && (len < BUFSIZE))
- plugin_submit ("battery_current", inst, buffer);
- }
- else
- {
- plugin_submit ("battery_current", inst, "N:U");
- }
-
- if (voltage != INVALID_VALUE)
- {
- len = snprintf (buffer, BUFSIZE, "N:%.3f", voltage);
-
- if ((len > 0) && (len < BUFSIZE))
- plugin_submit ("battery_voltage", inst, buffer);
- }
- else
- {
- plugin_submit ("battery_voltage", inst, "N:U");
- }
-
- if (charge != INVALID_VALUE)
- {
- len = snprintf (buffer, BUFSIZE, "N:%.3f", charge);
-
- if ((len > 0) && (len < BUFSIZE))
- plugin_submit ("battery_charge", inst, buffer);
- }
- else
- {
- plugin_submit ("battery_charge", inst, "N:U");
- }
-}
+ plugin_dispatch_values (type, &vl);
+} /* void battery_submit */
#if HAVE_IOKIT_PS_IOPOWERSOURCES_H || HAVE_IOKIT_IOKITLIB_H
double dict_get_double (CFDictionaryRef dict, char *key_string)
}
#endif /* HAVE_IOKIT_IOKITLIB_H */
-static void battery_read (void)
+static int battery_read (void)
{
#if HAVE_IOKIT_IOKITLIB_H || HAVE_IOKIT_PS_IOPOWERSOURCES_H
double charge = INVALID_VALUE; /* Current charge in Ah */
if ((charge_rel != INVALID_VALUE) && (charge_abs != INVALID_VALUE))
charge = charge_abs * charge_rel / 100.0;
- if ((charge != INVALID_VALUE)
- || (current != INVALID_VALUE)
- || (voltage != INVALID_VALUE))
- battery_submit ("0", current, voltage, charge);
+ if (charge != INVALID_VALUE)
+ battery_submit ("0", "charge", charge);
+ if (current != INVALID_VALUE)
+ battery_submit ("0", "current", current);
+ if (voltage != INVALID_VALUE)
+ battery_submit ("0", "voltage", voltage);
/* #endif HAVE_IOKIT_IOKITLIB_H || HAVE_IOKIT_PS_IOPOWERSOURCES_H */
#elif KERNEL_LINUX
FILE *fh;
- char buffer[BUFSIZE];
- char filename[BUFSIZE];
+ char buffer[1024];
+ char filename[256];
char *fields[8];
int numfields;
for (i = 0; i < battery_pmu_num; i++)
{
- char batnum_str[BUFSIZE];
+ char batnum_str[256];
double current = INVALID_VALUE;
double voltage = INVALID_VALUE;
double charge = INVALID_VALUE;
double *valptr = NULL;
- len = snprintf (filename, BUFSIZE, battery_pmu_file, i);
- if ((len >= BUFSIZE) || (len < 0))
+ len = snprintf (filename, sizeof (filename), battery_pmu_file, i);
+ if ((len >= sizeof (filename)) || (len < 0))
continue;
- len = snprintf (batnum_str, BUFSIZE, "%i", i);
- if ((len >= BUFSIZE) || (len < 0))
+ len = snprintf (batnum_str, sizeof (batnum_str), "%i", i);
+ if ((len >= sizeof (batnum_str)) || (len < 0))
continue;
if ((fh = fopen (filename, "r")) == NULL)
continue;
- while (fgets (buffer, BUFSIZE, fh) != NULL)
+ while (fgets (buffer, sizeof (buffer), fh) != NULL)
{
numfields = strsplit (buffer, fields, 8);
}
}
- if ((current != INVALID_VALUE)
- || (voltage != INVALID_VALUE)
- || (charge != INVALID_VALUE))
- battery_submit (batnum_str, current, voltage, charge);
-
fclose (fh);
fh = NULL;
+
+ if (charge != INVALID_VALUE)
+ battery_submit ("0", "charge", charge);
+ if (current != INVALID_VALUE)
+ battery_submit ("0", "current", current);
+ if (voltage != INVALID_VALUE)
+ battery_submit ("0", "voltage", voltage);
}
if (access ("/proc/acpi/battery", R_OK | X_OK) == 0)
if ((dh = opendir ("/proc/acpi/battery")) == NULL)
{
syslog (LOG_ERR, "Cannot open `/proc/acpi/battery': %s", strerror (errno));
- return;
+ return (-1);
}
while ((ent = readdir (dh)) != NULL)
if (ent->d_name[0] == '.')
continue;
- len = snprintf (filename, BUFSIZE, "/proc/acpi/battery/%s/state", ent->d_name);
- if ((len >= BUFSIZE) || (len < 0))
+ len = snprintf (filename, sizeof (filename),
+ "/proc/acpi/battery/%s/state",
+ ent->d_name);
+ if ((len >= sizeof (filename)) || (len < 0))
continue;
if ((fh = fopen (filename, "r")) == NULL)
* [11:00] <@tokkee> remaining capacity: 4136 mAh
* [11:00] <@tokkee> present voltage: 12428 mV
*/
- while (fgets (buffer, BUFSIZE, fh) != NULL)
+ while (fgets (buffer, sizeof (buffer), fh) != NULL)
{
numfields = strsplit (buffer, fields, 8);
if ((fields[2] == endptr) || (errno != 0))
*valptr = INVALID_VALUE;
}
- }
+ } /* while (fgets (buffer, sizeof (buffer), fh) != NULL) */
+
+ fclose (fh);
if ((current != INVALID_VALUE) && (charging == 0))
current *= -1;
- if ((current != INVALID_VALUE)
- || (voltage != INVALID_VALUE)
- || (charge != INVALID_VALUE))
- battery_submit (ent->d_name, current, voltage, charge);
-
- fclose (fh);
+ if (charge != INVALID_VALUE)
+ battery_submit ("0", "charge", charge);
+ if (current != INVALID_VALUE)
+ battery_submit ("0", "current", current);
+ if (voltage != INVALID_VALUE)
+ battery_submit ("0", "voltage", voltage);
}
closedir (dh);
}
#endif /* KERNEL_LINUX */
+
+ return (0);
}
-#else
-# define battery_read NULL
#endif /* BATTERY_HAVE_READ */
void module_register (void)
{
- plugin_register (MODULE_NAME, battery_init, battery_read, NULL);
- plugin_register ("battery_current", NULL, NULL, battery_current_write);
- plugin_register ("battery_voltage", NULL, NULL, battery_voltage_write);
- plugin_register ("battery_charge", NULL, NULL, battery_charge_write);
-}
+ plugin_register_data_set (&charge_ds);
+ plugin_register_data_set (¤t_ds);
+ plugin_register_data_set (&voltage_ds);
-#undef BUFSIZE
-#undef MODULE_NAME
+#if BATTERY_HAVE_READ
+ plugin_register_init ("battery", battery_init);
+ plugin_register_read ("battery", battery_read);
+#endif /* BATTERY_HAVE_READ */
+}
--- /dev/null
+#include <stdlib.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <errno.h>
+#include <string.h>
+#include <assert.h>
+
+#include <sys/socket.h>
+#include <sys/un.h>
+
+/*
+ * This weird macro cascade forces the glibc to define `NAN'. I don't know
+ * another way to solve this, so more intelligent solutions are welcome. -octo
+ */
+#ifndef __USE_ISOC99
+# define DISABLE__USE_ISOC99 1
+# define __USE_ISOC99 1
+#endif
+#include <math.h>
+#ifdef DISABLE__USE_ISOC99
+# undef DISABLE__USE_ISOC99
+# undef __USE_ISOC99
+#endif
+
+#define RET_OKAY 0
+#define RET_WARNING 1
+#define RET_CRITICAL 2
+#define RET_UNKNOWN 3
+
+#define CON_NONE 0
+#define CON_AVERAGE 1
+#define CON_SUM 2
+
+struct range_s
+{
+ double min;
+ double max;
+ int invert;
+};
+typedef struct range_s range_t;
+
+extern char *optarg;
+extern int optind, opterr, optopt;
+
+static char *socket_file_g = NULL;
+static char *value_string_g = NULL;
+static char *hostname_g = NULL;
+
+static range_t range_critical_g;
+static range_t range_warning_g;
+static int consolitation_g = CON_NONE;
+
+static char **match_ds_g = NULL;
+static int match_ds_num_g = 0;
+
+static int ignore_ds (const char *name)
+{
+ int i;
+
+ if (match_ds_g == NULL)
+ return (0);
+
+ for (i = 0; i < match_ds_num_g; i++)
+ if (strcasecmp (match_ds_g[i], name) == 0)
+ return (0);
+
+ return (1);
+} /* int ignore_ds */
+
+static void parse_range (char *string, range_t *range)
+{
+ char *min_ptr;
+ char *max_ptr;
+
+ if (*string == '@')
+ {
+ range->invert = 1;
+ string++;
+ }
+
+ max_ptr = strchr (string, ':');
+ if (max_ptr == NULL)
+ {
+ min_ptr = NULL;
+ max_ptr = string;
+ }
+ else
+ {
+ min_ptr = string;
+ *max_ptr = '\0';
+ max_ptr++;
+ }
+
+ assert (max_ptr != NULL);
+
+ /* `10' == `0:10' */
+ if (min_ptr == NULL)
+ range->min = 0.0;
+ /* :10 == ~:10 == -inf:10 */
+ else if ((*min_ptr == '\0') || (*min_ptr == '~'))
+ range->min = NAN;
+ else
+ range->min = atof (min_ptr);
+
+ if ((*max_ptr == '\0') || (*max_ptr == '~'))
+ range->max = NAN;
+ else
+ range->max = atof (max_ptr);
+} /* void parse_range */
+
+int match_range (range_t *range, double value)
+{
+ int ret = 0;
+
+ if ((range->min != NAN) && (range->min > value))
+ ret = 1;
+ if ((range->max != NAN) && (range->max < value))
+ ret = 1;
+
+ return (((ret - range->invert) == 0) ? 0 : 1);
+}
+
+static int get_values (int *ret_values_num, double **ret_values,
+ char ***ret_values_names)
+{
+ struct sockaddr_un sa;
+ int status;
+ int fd;
+ FILE *fh;
+ char buffer[4096];
+
+ int values_num;
+ double *values;
+ char **values_names;
+
+ int i;
+
+ fd = socket (PF_UNIX, SOCK_STREAM, 0);
+ if (fd < 0)
+ {
+ fprintf (stderr, "socket failed: %s\n",
+ strerror (errno));
+ return (-1);
+ }
+
+ memset (&sa, '\0', sizeof (sa));
+ sa.sun_family = AF_UNIX;
+ strncpy (sa.sun_path, socket_file_g,
+ sizeof (sa.sun_path) - 1);
+
+ status = connect (fd, (struct sockaddr *) &sa, sizeof (sa));
+ if (status != 0)
+ {
+ fprintf (stderr, "connect failed: %s\n",
+ strerror (errno));
+ return (-1);
+ }
+
+ fh = fdopen (fd, "r+");
+ if (fh == NULL)
+ {
+ fprintf (stderr, "fdopen failed: %s\n",
+ strerror (errno));
+ close (fd);
+ return (-1);
+ }
+
+ fprintf (fh, "GETVAL %s/%s\n", hostname_g, value_string_g);
+ fflush (fh);
+
+ if (fgets (buffer, sizeof (buffer), fh) == NULL)
+ {
+ fprintf (stderr, "fgets failed: %s\n",
+ strerror (errno));
+ close (fd);
+ return (-1);
+ }
+ close (fd); fd = -1;
+
+ values_num = atoi (buffer);
+ if (values_num < 1)
+ return (-1);
+
+ values = (double *) malloc (values_num * sizeof (double));
+ if (values == NULL)
+ {
+ fprintf (stderr, "malloc failed: %s\n",
+ strerror (errno));
+ return (-1);
+ }
+
+ values_names = (char **) malloc (values_num * sizeof (char *));
+ if (values_names == NULL)
+ {
+ fprintf (stderr, "malloc failed: %s\n",
+ strerror (errno));
+ free (values);
+ return (-1);
+ }
+
+ {
+ char *ptr = strchr (buffer, ' ') + 1;
+ char *key;
+ char *value;
+
+ i = 0;
+ while ((key = strtok (ptr, " \t")) != NULL)
+ {
+ ptr = NULL;
+ value = strchr (key, '=');
+ if (value == NULL)
+ continue;
+ *value = '\0'; value++;
+
+ if (ignore_ds (key) != 0)
+ continue;
+
+ values_names[i] = strdup (key);
+ values[i] = atof (value);
+
+ i++;
+ if (i >= values_num)
+ break;
+ }
+ values_num = i;
+ }
+
+ *ret_values_num = values_num;
+ *ret_values = values;
+ *ret_values_names = values_names;
+
+ return (0);
+} /* int get_values */
+
+static void usage (const char *name)
+{
+ fprintf (stderr, "Usage: %s <-s socket> <-n value_spec> <-H hostname> [options]\n"
+ "\n"
+ "Valid options are:\n"
+ " -s <socket> Path to collectd's UNIX-socket.\n"
+ " -n <v_spec> Value specification to get from collectd.\n"
+ " Format: `plugin-instance/type-instance'\n"
+ " -d <ds> Select the DS to examine. May be repeated to examine multiple\n"
+ " DSes. By default all DSes are used.\n"
+ " -g <consol> Method to use to consolidate several DSes.\n"
+ " Valid arguments are `none', `average' and `sum'\n"
+ " -H <host> Hostname to query the values for.\n"
+ " -c <range> Critical range\n"
+ " -w <range> Warning range\n"
+ "\n"
+ "Consolidation functions:\n"
+ " none: Apply the warning- and critical-ranges to each data-source\n"
+ " individually.\n"
+ " average: Calculate the average of all matching DSes and apply the\n"
+ " warning- and critical-ranges to the calculated average.\n"
+ " sum: Apply the ranges to the sum of all DSes.\n"
+ "\n", name);
+ exit (1);
+} /* void usage */
+
+int do_check_con_none (int values_num, double *values, char **values_names)
+{
+ int i;
+
+ int num_critical = 0;
+ int num_warning = 0;
+ int num_okay = 0;
+
+ for (i = 0; i < values_num; i++)
+ {
+ if (values[i] == NAN)
+ num_warning++;
+ else if (match_range (&range_critical_g, values[i]) != 0)
+ num_critical++;
+ else if (match_range (&range_warning_g, values[i]) != 0)
+ num_warning++;
+ else
+ num_okay++;
+ }
+
+ if ((num_critical != 0) || (values_num == 0))
+ {
+ printf ("CRITICAL: %i critical, %i warning, %i okay\n",
+ num_critical, num_warning, num_okay);
+ return (RET_CRITICAL);
+ }
+ else if (num_warning != 0)
+ {
+ printf ("WARNING: %i warning, %i okay\n",
+ num_warning, num_okay);
+ return (RET_WARNING);
+ }
+ else
+ {
+ printf ("OKAY: %i okay\n", num_okay);
+ return (RET_OKAY);
+ }
+
+ return (RET_UNKNOWN);
+} /* int do_check_con_none */
+
+int do_check_con_average (int values_num, double *values, char **values_names)
+{
+ int i;
+ double total;
+ int total_num;
+
+ total = 0.0;
+ total_num = 0;
+ for (i = 0; i < values_num; i++)
+ {
+ if (values[i] != NAN)
+ {
+ total += values[i];
+ total_num++;
+ }
+ }
+
+ if (total_num == 0)
+ {
+ printf ("WARNING: No defined values found\n");
+ return (RET_WARNING);
+ }
+
+ if (match_range (&range_critical_g, total / total_num) != 0)
+ {
+ printf ("CRITICAL: Average = %lf\n",
+ (double) (total / total_num));
+ return (RET_CRITICAL);
+ }
+ else if (match_range (&range_warning_g, total / total_num) != 0)
+ {
+ printf ("WARNING: Average = %lf\n",
+ (double) (total / total_num));
+ return (RET_WARNING);
+ }
+ else
+ {
+ printf ("OKAY: Average = %lf\n",
+ (double) (total / total_num));
+ return (RET_OKAY);
+ }
+
+ return (RET_UNKNOWN);
+} /* int do_check_con_average */
+
+int do_check_con_sum (int values_num, double *values, char **values_names)
+{
+ int i;
+ double total;
+ int total_num;
+
+ total = 0.0;
+ total_num = 0;
+ for (i = 0; i < values_num; i++)
+ {
+ if (values[i] != NAN)
+ {
+ total += values[i];
+ total_num++;
+ }
+ }
+
+ if (total_num == 0)
+ {
+ printf ("WARNING: No defined values found\n");
+ return (RET_WARNING);
+ }
+
+ if (match_range (&range_critical_g, total) != 0)
+ {
+ printf ("CRITICAL: Sum = %lf\n", total);
+ return (RET_CRITICAL);
+ }
+ else if (match_range (&range_warning_g, total) != 0)
+ {
+ printf ("WARNING: Sum = %lf\n", total);
+ return (RET_WARNING);
+ }
+ else
+ {
+ printf ("OKAY: Sum = %lf\n", total);
+ return (RET_OKAY);
+ }
+
+ return (RET_UNKNOWN);
+} /* int do_check_con_sum */
+
+int do_check (void)
+{
+ double *values;
+ char **values_names;
+ int values_num;
+
+ if (get_values (&values_num, &values, &values_names) != 0)
+ {
+ fputs ("ERROR: Cannot get values from daemon\n", stdout);
+ return (RET_CRITICAL);
+ }
+
+ if (consolitation_g == CON_NONE)
+ return (do_check_con_none (values_num, values, values_names));
+ else if (consolitation_g == CON_AVERAGE)
+ return (do_check_con_average (values_num, values, values_names));
+ else if (consolitation_g == CON_SUM)
+ return (do_check_con_sum (values_num, values, values_names));
+
+ free (values);
+ free (values_names);
+
+ return (RET_UNKNOWN);
+}
+
+int main (int argc, char **argv)
+{
+ range_critical_g.min = NAN;
+ range_critical_g.max = NAN;
+ range_critical_g.invert = 0;
+
+ range_warning_g.min = NAN;
+ range_warning_g.max = NAN;
+ range_warning_g.invert = 0;
+
+ while (42)
+ {
+ int c;
+
+ c = getopt (argc, argv, "w:c:s:n:H:g:d:h");
+ if (c < 0)
+ break;
+
+ switch (c)
+ {
+ case 'c':
+ parse_range (optarg, &range_critical_g);
+ break;
+ case 'w':
+ parse_range (optarg, &range_warning_g);
+ break;
+ case 's':
+ socket_file_g = optarg;
+ break;
+ case 'n':
+ value_string_g = optarg;
+ break;
+ case 'H':
+ hostname_g = optarg;
+ break;
+ case 'g':
+ if (strcasecmp (optarg, "none") == 0)
+ consolitation_g = CON_NONE;
+ else if (strcasecmp (optarg, "average") == 0)
+ consolitation_g = CON_AVERAGE;
+ else if (strcasecmp (optarg, "sum") == 0)
+ consolitation_g = CON_SUM;
+ else
+ usage (argv[0]);
+ break;
+ case 'd':
+ {
+ char **tmp;
+ tmp = (char **) realloc (match_ds_g,
+ (match_ds_num_g + 1)
+ * sizeof (char *));
+ if (tmp == NULL)
+ {
+ fprintf (stderr, "realloc failed: %s\n",
+ strerror (errno));
+ return (RET_UNKNOWN);
+ }
+ match_ds_g = tmp;
+ match_ds_g[match_ds_num_g] = strdup (optarg);
+ if (match_ds_g[match_ds_num_g] == NULL)
+ {
+ fprintf (stderr, "strdup failed: %s\n",
+ strerror (errno));
+ return (RET_UNKNOWN);
+ }
+ match_ds_num_g++;
+ break;
+ }
+ default:
+ usage (argv[0]);
+ } /* switch (c) */
+ }
+
+ if ((socket_file_g == NULL) || (value_string_g == NULL)
+ || (hostname_g == NULL))
+ usage (argv[0]);
+
+ return (do_check ());
+} /* int main */
*
* 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; either version 2 of the License, or (at your
- * option) any later version.
+ * 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
#if HAVE_LIBRRD
static int start_server (void)
{
+ /* FIXME */
+#if 0
char *host;
char *type;
char *instance;
if (values != NULL) free (values); values = NULL;
}
+#endif
return (0);
} /* static int start_server (void) */
#endif /* HAVE_LIBRRD */
@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
@BUILD_MODULE_NTPD_TRUE@LoadPlugin ntpd
@BUILD_MODULE_PING_TRUE@LoadPlugin ping
@BUILD_MODULE_PROCESSES_TRUE@LoadPlugin processes
+@BUILD_WITH_RRDTOOL_TRUE@LoadPlugin rrdtool
@BUILD_MODULE_SENSORS_TRUE@LoadPlugin sensors
@BUILD_MODULE_SERIAL_TRUE@LoadPlugin serial
@BUILD_MODULE_SWAP_TRUE@LoadPlugin swap
# Process name
#</Plugin>
+#<Plugin rrdtool>
+# CacheTimeout 120
+#</Plugin>
+
## There are two different naming schemes for the sensors plugin, to preserver
## backwards compatibility. The `extended naming' is prefered, but not the
## default for this reason. See `collectd.conf(5)' for more information.
=back
+=head2 Plugin C<rrdtool>
+
+=over 4
+
+=item B<CacheTimeout> I<Seconds>
+
+If this option is set to a value greater than zero, the C<rrdtool>-plugin will
+write values every I<Seconds> seconds to the RRD-files. Writing multiple values
+at once reduces IO-operations and thus lessens the load produced by updating
+the files. The tradeoff is that the graphs kind of "drag behind" and that more
+memory is used.
+
+=back
+
=head2 Plugin C<sensors>
=over 4
*
* 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; either version 2 of the License, or (at your
- * option) any later version.
+ * 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
# define assert(...) /* nop */
#endif
+/*
+ * This weird macro cascade forces the glibc to define `NAN'. I don't know
+ * another way to solve this, so more intelligent solutions are welcome. -octo
+ */
+#ifndef __USE_ISOC99
+# define DISABLE__USE_ISOC99 1
+# define __USE_ISOC99 1
+#endif
+#include <math.h>
+#ifdef DISABLE__USE_ISOC99
+# undef DISABLE__USE_ISOC99
+# undef __USE_ISOC99
+#endif
+
#if HAVE_DIRENT_H
# include <dirent.h>
# define NAMLEN(dirent) strlen((dirent)->d_name)
/**
* collectd - src/common.c
- * Copyright (C) 2005,2006 Florian octo Forster
+ * Copyright (C) 2005-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 Li-
- * cence as published by the Free Software Foundation; either
- * version 2 of the Licence, or any later version.
+ * 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 use-
- * ful, but WITHOUT ANY WARRANTY; without even the implied war-
- * ranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- * See the GNU General Public Licence for more details.
+ * 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
- * Licence along with this program; if not, write to the Free
- * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139,
- * USA.
+ * 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 <octo at verplant.org>
# include <math.h>
#endif
+/* for ntohl and htonl */
+#if HAVE_ARPA_INET_H
+# include <arpa/inet.h>
+#endif
+
extern int operating_mode;
#ifdef HAVE_LIBKSTAT
extern kstat_ctl_t *kc;
#endif
-#ifdef HAVE_LIBRRD
-#if 0
-static char *rra_def[] =
-{
- "RRA:AVERAGE:0.0:1:1500",
- "RRA:AVERAGE:0.2:6:1500",
- "RRA:AVERAGE:0.1:180:1680",
- "RRA:AVERAGE:0.1:2160:1520",
- "RRA:MIN:0.0:1:1500",
- "RRA:MIN:0.2:6:1500",
- "RRA:MIN:0.1:180:1680",
- "RRA:MIN:0.1:2160:1520",
- "RRA:MAX:0.0:1:1500",
- "RRA:MAX:0.2:6:1500",
- "RRA:MAX:0.1:180:1680",
- "RRA:MAX:0.1:2160:1520",
- NULL
-};
-static int rra_num = 12;
-#endif
-
-static int rra_timespans[] =
-{
- 3600,
- 86400,
- 604800,
- 2678400,
- 31622400,
- 0
-};
-static int rra_timespans_num = 5;
-
-static char *rra_types[] =
-{
- "AVERAGE",
- "MIN",
- "MAX",
- NULL
-};
-static int rra_types_num = 3;
-#endif /* HAVE_LIBRRD */
-
void sstrncpy (char *d, const char *s, int len)
{
strncpy (d, s, len);
return (0);
}
-static int check_create_dir (const char *file_orig)
+int check_create_dir (const char *file_orig)
{
struct stat statbuf;
return (0);
}
-/* * * * *
- * Magic *
- * * * * */
-#if HAVE_LIBRRD
-static int rra_get (char ***ret)
-{
- static char **rra_def = NULL;
- static int rra_num = 0;
-
- int rra_max = rra_timespans_num * rra_types_num;
-
- int step;
- int rows;
- int span;
-
- int cdp_num;
- int cdp_len;
- int i, j;
-
- char buffer[64];
-
- if ((rra_num != 0) && (rra_def != NULL))
- {
- *ret = rra_def;
- return (rra_num);
- }
-
- if ((rra_def = (char **) malloc ((rra_max + 1) * sizeof (char *))) == NULL)
- return (-1);
- memset (rra_def, '\0', (rra_max + 1) * sizeof (char *));
-
- step = atoi (COLLECTD_STEP);
- rows = atoi (COLLECTD_ROWS);
-
- if ((step <= 0) || (rows <= 0))
- {
- *ret = NULL;
- return (-1);
- }
-
- cdp_len = 0;
- for (i = 0; i < rra_timespans_num; i++)
- {
- span = rra_timespans[i];
-
- if ((span / step) < rows)
- continue;
-
- if (cdp_len == 0)
- cdp_len = 1;
- else
- cdp_len = (int) floor (((double) span) / ((double) (rows * step)));
-
- cdp_num = (int) ceil (((double) span) / ((double) (cdp_len * step)));
-
- for (j = 0; j < rra_types_num; j++)
- {
- if (rra_num >= rra_max)
- break;
-
- if (snprintf (buffer, sizeof(buffer), "RRA:%s:%3.1f:%u:%u",
- rra_types[j], COLLECTD_XFF,
- cdp_len, cdp_num) >= sizeof (buffer))
- {
- syslog (LOG_ERR, "rra_get: Buffer would have been truncated.");
- continue;
- }
-
- rra_def[rra_num++] = sstrdup (buffer);
- }
- }
-
-#if COLLECT_DEBUG
- DBG ("rra_num = %i", rra_num);
- for (i = 0; i < rra_num; i++)
- DBG (" %s", rra_def[i]);
-#endif
-
- *ret = rra_def;
- return (rra_num);
-}
-#endif /* HAVE_LIBRRD */
-
-static int log_create_file (char *filename, char **ds_def, int ds_num)
-{
- FILE *log;
- int i;
-
- if (check_create_dir (filename))
- return (-1);
-
- log = fopen (filename, "w");
- if (log == NULL)
- {
- syslog (LOG_WARNING, "Failed to create %s: %s", filename,
- strerror(errno));
- return (-1);
- }
-
- fprintf (log, "epoch");
- for (i = 0; i < ds_num; i++)
- {
- char *name;
- char *tmp;
-
- name = strchr (ds_def[i], ':');
- if (name == NULL)
- {
- syslog (LOG_WARNING, "Invalid DS definition '%s' for %s",
- ds_def[i], filename);
- fclose(log);
- remove(filename);
- return (-1);
- }
-
- name += 1;
- tmp = strchr (name, ':');
- if (tmp == NULL)
- {
- syslog (LOG_WARNING, "Invalid DS definition '%s' for %s",
- ds_def[i], filename);
- fclose(log);
- remove(filename);
- return (-1);
- }
-
- /* The `%.*s' is needed because there is no null-byte behind
- * the name. */
- fprintf(log, ",%.*s", (int) (tmp - name), name);
- }
- fprintf(log, "\n");
- fclose(log);
-
- return 0;
-}
-
-static int log_update_file (char *host, char *file, char *values,
- char **ds_def, int ds_num)
-{
- char *tmp;
- FILE *fp;
- struct stat statbuf;
- char full_file[1024];
-
- /* Cook the values a bit: Substitute colons with commas */
- strsubstitute (values, ':', ',');
-
- /* host == NULL => local mode */
- if (host != NULL)
- {
- if (snprintf (full_file, 1024, "%s/%s", host, file) >= 1024)
- return (-1);
- }
- else
- {
- if (snprintf (full_file, 1024, "%s", file) >= 1024)
- return (-1);
- }
-
- strncpy (full_file, file, 1024);
-
- tmp = full_file + strlen (full_file) - 4;
- assert ((tmp != NULL) && (tmp > full_file));
-
- /* Change the filename for logfiles. */
- if (strncmp (tmp, ".rrd", 4) == 0)
- {
- 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 (tmp, 1024 - (tmp - full_file), "-%Y-%m-%d", tm);
-
- /* `localtime(3)' returns a pointer to static data,
- * therefore the pointer may not be free'd. */
- }
- else
- DBG ("The filename ends with `%s' which is unexpected.", tmp);
-
- if (stat (full_file, &statbuf) == -1)
- {
- if (errno == ENOENT)
- {
- if (log_create_file (full_file, ds_def, ds_num))
- return (-1);
- }
- else
- {
- syslog (LOG_ERR, "stat %s: %s", full_file, strerror (errno));
- return (-1);
- }
- }
- else if (!S_ISREG (statbuf.st_mode))
- {
- syslog (LOG_ERR, "stat %s: Not a regular file!", full_file);
- return (-1);
- }
-
-
- fp = fopen (full_file, "a");
- if (fp == NULL)
- {
- syslog (LOG_WARNING, "Failed to append to %s: %s", full_file,
- strerror(errno));
- return (-1);
- }
- fprintf(fp, "%s\n", values);
- fclose(fp);
-
- return (0);
-} /* int log_update_file */
-
-#if HAVE_LIBRRD
-static int rrd_create_file (char *filename, char **ds_def, int ds_num)
-{
- char **argv;
- int argc;
- char **rra_def;
- int rra_num;
- int i, j;
- int status = 0;
-
- if (check_create_dir (filename))
- return (-1);
-
- if ((rra_num = rra_get (&rra_def)) < 1)
- {
- syslog (LOG_ERR, "rra_create failed: Could not calculate RRAs");
- return (-1);
- }
-
- argc = ds_num + rra_num + 4;
-
- if ((argv = (char **) malloc (sizeof (char *) * (argc + 1))) == NULL)
- {
- syslog (LOG_ERR, "rrd_create failed: %s", strerror (errno));
- return (-1);
- }
-
- argv[0] = "create";
- argv[1] = filename;
- argv[2] = "-s";
- argv[3] = COLLECTD_STEP;
-
- j = 4;
- 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)
- {
- syslog (LOG_ERR, "rrd_create failed: %s: %s", filename, rrd_get_error ());
- status = -1;
- }
-
- free (argv);
-
- return (status);
-}
-#endif /* HAVE_LIBRRD */
-
-int rrd_update_file (char *host, char *file, char *values,
- char **ds_def, int ds_num)
-{
-#if HAVE_LIBRRD
- struct stat statbuf;
- char full_file[1024];
- char *argv[4] = { "update", full_file, values, NULL };
-#endif /* HAVE_LIBRRD */
-
- /* I'd rather have a function `common_update_file' to make this
- * decission, but for that we'd need to touch all plugins.. */
- if (operating_mode == MODE_LOG)
- return (log_update_file (host, file, values,
- ds_def, ds_num));
-
-#if HAVE_LIBRRD
- /* host == NULL => local mode */
- if (host != NULL)
- {
- if (snprintf (full_file, 1024, "%s/%s", host, file) >= 1024)
- return (-1);
- }
- else
- {
- if (snprintf (full_file, 1024, "%s", file) >= 1024)
- return (-1);
- }
-
- if (stat (full_file, &statbuf) == -1)
- {
- if (errno == ENOENT)
- {
- if (rrd_create_file (full_file, ds_def, ds_num))
- return (-1);
- }
- else
- {
- syslog (LOG_ERR, "stat %s: %s", full_file, strerror (errno));
- return (-1);
- }
- }
- else if (!S_ISREG (statbuf.st_mode))
- {
- syslog (LOG_ERR, "stat %s: Not a regular file!", full_file);
- return (-1);
- }
-
- optind = 0; /* bug in librrd? */
- rrd_clear_error ();
- if (rrd_update (3, argv) == -1)
- {
- syslog (LOG_WARNING, "rrd_update failed: %s: %s", full_file, rrd_get_error ());
- return (-1);
- }
- return (0);
-/* #endif HAVE_LIBRRD */
-
-#else
- syslog (LOG_ERR, "`rrd_update_file' was called, but collectd isn't linked against librrd!");
- return (-1);
-#endif
-}
-
#ifdef HAVE_LIBKSTAT
int get_kstat (kstat_t **ksp_ptr, char *module, int instance, char *name)
{
return (retval);
}
#endif /* HAVE_LIBKSTAT */
+
+unsigned long long ntohll (unsigned long long n)
+{
+#if __BYTE_ORDER == __BIG_ENDIAN
+ return (n);
+#else
+ return (((unsigned long long) ntohl (n)) << 32) + ntohl (n >> 32);
+#endif
+}
+
+unsigned long long htonll (unsigned long long n)
+{
+#if __BYTE_ORDER == __BIG_ENDIAN
+ return (n);
+#else
+ return (((unsigned long long) htonl (n)) << 32) + htonl (n >> 32);
+#endif
+}
/**
* collectd - src/common.h
- * Copyright (C) 2005,2006 Florian octo Forster
+ * Copyright (C) 2005-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 Li-
- * cence as published by the Free Software Foundation; either
- * version 2 of the Licence, or any later version.
+ * 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 use-
- * ful, but WITHOUT ANY WARRANTY; without even the implied war-
- * ranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- * See the GNU General Public Licence for more details.
+ * 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
- * Licence along with this program; if not, write to the Free
- * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139,
- * USA.
+ * 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 <octo at verplant.org>
/* FIXME: `timeval_sub_timespec' needs a description */
int timeval_sub_timespec (struct timeval *tv0, struct timeval *tv1, struct timespec *ret);
-int rrd_update_file (char *host, char *file, char *values,
- char **ds_def, int ds_num);
+int check_create_dir (const char *file_orig);
#ifdef HAVE_LIBKSTAT
int get_kstat (kstat_t **ksp_ptr, char *module, int instance, char *name);
long long get_kstat_value (kstat_t *ksp, char *name);
#endif
+unsigned long long ntohll (unsigned long long n);
+unsigned long long htonll (unsigned long long n);
+
#endif /* COMMON_H */
typedef struct cf_callback
{
- char *type;
- int (*callback) (char *, char *);
- char **keys;
+ const char *type;
+ int (*callback) (const char *, const char *);
+ const char **keys;
int keys_num;
struct cf_callback *next;
} cf_callback_t;
return (ret);
}
-void cf_unregister (char *type)
+void cf_unregister (const char *type)
{
cf_callback_t *this, *prev;
}
}
-void cf_register (char *type,
- int (*callback) (char *, char *),
- char **keys, int keys_num)
+void cf_register (const char *type,
+ int (*callback) (const char *, const char *),
+ const char **keys, int keys_num)
{
cf_callback_t *cf_cb;
char buf[64];
return (LC_CBRET_OKAY);
}
-static int cf_callback_socket (const char *shortvar, const char *var,
- const char *arguments, const char *value, lc_flags_t flags,
- void *extra)
-{
- char *buffer;
-
- char *fields[3];
- int numfields;
-
- char *node;
- char *service = NET_DEFAULT_PORT;
-
- DEBUG_CALLBACK (shortvar, var, arguments, value);
-
- buffer = strdup (value);
- if (buffer == NULL)
- return (LC_CBRET_ERROR);
-
- numfields = strsplit (buffer, fields, 3);
-
- if ((numfields != 1) && (numfields != 2))
- {
- syslog (LOG_ERR, "Invalid number of arguments to `%s'",
- shortvar);
- free (buffer);
- return (LC_CBRET_ERROR);
- }
-
- node = fields[0];
- if (numfields == 2)
- service = fields[1];
-
- /* Still return `LC_CBRET_OKAY' because this is not an syntax error */
- if (network_create_socket (node, service) < 1)
- syslog (LOG_ERR, "network_create_socket (%s, %s) failed",
- node, service);
-
- free (buffer);
-
- return (LC_CBRET_OKAY);
-}
-
/*
* `cf_callback_plugin'
* Start/end section `plugin'
lc_register_callback ("LoadPlugin", SHORTOPT_NONE,
LC_VAR_STRING, cf_callback_mode_loadmodule, NULL);
- lc_register_callback ("Listen", SHORTOPT_NONE,
- LC_VAR_STRING, cf_callback_socket, NULL);
- lc_register_callback ("Server", SHORTOPT_NONE,
- LC_VAR_STRING, cf_callback_socket, NULL);
-
for (i = 0; i < cf_mode_num; i++)
{
cf_mode_item_t *item;
* `type' Name of the plugin (must be the same as passed to
* `plugin_register'
*/
-void cf_unregister (char *type);
+void cf_unregister (const char *type);
/*
* DESCRIPTION
* exists for each `type' at any time. This means that `cf_register' may be
* called multiple times, but only the last call will have an effect.
*/
-void cf_register (char *type,
- int (*callback) (char *, char *),
- char **keys, int keys_num);
+void cf_register (const char *type,
+ int (*callback) (const char *, const char *),
+ const char **keys, int keys_num);
/*
* DESCRIPTION
/**
* collectd - src/cpu.c
- * Copyright (C) 2005,2006 Florian octo Forster
+ * Copyright (C) 2005-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; either version 2 of the License, or (at your
- * option) any later version.
+ * 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
#include "plugin.h"
#include "utils_debug.h"
-#define MODULE_NAME "cpu"
-
#ifdef HAVE_MACH_KERN_RETURN_H
# include <mach/kern_return.h>
#endif
# define CPU_HAVE_READ 0
#endif
+static data_source_t dsrc[1] =
+{
+ {"value", DS_TYPE_COUNTER, 0, 4294967295.0}
+};
+
+static data_set_t ds =
+{
+ "cpu", 1, dsrc
+};
+
+#if CPU_HAVE_READ
#ifdef PROCESSOR_CPU_LOAD_INFO
static mach_port_t port_host;
static processor_port_array_t cpu_list;
static int numcpu;
#endif /* HAVE_SYSCTLBYNAME */
-static char *cpu_filename = "cpu-%s.rrd";
-
-static char *ds_def[] =
-{
- "DS:user:COUNTER:"COLLECTD_HEARTBEAT":0:U",
- "DS:nice:COUNTER:"COLLECTD_HEARTBEAT":0:U",
- "DS:syst:COUNTER:"COLLECTD_HEARTBEAT":0:U",
- "DS:idle:COUNTER:"COLLECTD_HEARTBEAT":0:U",
- "DS:wait:COUNTER:"COLLECTD_HEARTBEAT":0:U",
- NULL
-};
-static int ds_num = 5;
-
-static void cpu_init (void)
+static int init (void)
{
#if PROCESSOR_CPU_LOAD_INFO || PROCESSOR_TEMPERATURE
kern_return_t status;
/* FIXME: Free `cpu_list' if it's not NULL */
if ((status = host_processors (port_host, &cpu_list, &cpu_list_len)) != KERN_SUCCESS)
{
- syslog (LOG_ERR, "cpu-plugin: host_processors returned %i\n", (int) status);
+ syslog (LOG_ERR, "cpu plugin: host_processors returned %i", (int) status);
cpu_list_len = 0;
- return;
+ return (-1);
}
DBG ("host_processors returned %i %s", (int) cpu_list_len, cpu_list_len == 1 ? "processor" : "processors");
- syslog (LOG_INFO, "cpu-plugin: Found %i processor%s.", (int) cpu_list_len, cpu_list_len == 1 ? "" : "s");
+ syslog (LOG_INFO, "cpu plugin: Found %i processor%s.", (int) cpu_list_len, cpu_list_len == 1 ? "" : "s");
collectd_step = atoi (COLLECTD_STEP);
if ((collectd_step > 0) && (collectd_step <= 86400))
numcpu = 0;
if (kc == NULL)
- return;
+ return (-1);
/* Solaris doesn't count linear.. *sigh* */
for (numcpu = 0, ksp_chain = kc->kc_chain;
if (sysctlbyname ("hw.ncpu", &numcpu, &numcpu_size, NULL, 0) < 0)
{
syslog (LOG_WARNING, "cpu: sysctlbyname: %s", strerror (errno));
- return;
+ return (-1);
}
if (numcpu != 1)
syslog (LOG_NOTICE, "cpu: Only one processor supported when using `sysctlbyname' (found %i)", numcpu);
#endif
- return;
-}
+ return (0);
+} /* int init */
-static void cpu_write (char *host, char *inst, char *val)
+static void submit (int cpu_num, const char *type_instance, counter_t value)
{
- char file[512];
- int status;
-
- status = snprintf (file, 512, cpu_filename, inst);
- if (status < 1)
- return;
- else if (status >= 512)
- return;
-
- rrd_update_file (host, file, val, ds_def, ds_num);
+ value_t values[1];
+ value_list_t vl = VALUE_LIST_INIT;
+
+ values[0].counter = value;
+
+ vl.values = values;
+ vl.values_len = 1;
+ vl.time = time (NULL);
+ strcpy (vl.host, hostname);
+ strcpy (vl.plugin, "cpu");
+ snprintf (vl.plugin_instance, sizeof (vl.type_instance),
+ "%i", cpu_num);
+ vl.plugin_instance[DATA_MAX_NAME_LEN - 1] = '\0';
+ strcpy (vl.type_instance, type_instance);
+
+ plugin_dispatch_values ("cpu", &vl);
}
-#if CPU_HAVE_READ
-#define BUFSIZE 512
-static void cpu_submit (int cpu_num, unsigned long long user,
- unsigned long long nice, unsigned long long syst,
- unsigned long long idle, unsigned long long wait)
-{
- char buf[BUFSIZE];
- char cpu[16];
-
- if (snprintf (buf, BUFSIZE, "%u:%llu:%llu:%llu:%llu:%llu", (unsigned int) curtime,
- user, nice, syst, idle, wait) >= BUFSIZE)
- return;
- snprintf (cpu, 16, "%i", cpu_num);
-
- plugin_submit (MODULE_NAME, cpu, buf);
-}
-#undef BUFSIZE
-
-static void cpu_read (void)
+static int cpu_read (void)
{
#if PROCESSOR_CPU_LOAD_INFO || PROCESSOR_TEMPERATURE
int cpu;
PROCESSOR_CPU_LOAD_INFO, &cpu_host,
(processor_info_t) &cpu_info, &cpu_info_len)) != KERN_SUCCESS)
{
- syslog (LOG_ERR, "cpu-plugin: processor_info failed with status %i\n", (int) status);
+ syslog (LOG_ERR, "cpu plugin: processor_info failed with status %i", (int) status);
continue;
}
if (cpu_info_len < CPU_STATE_MAX)
{
- syslog (LOG_ERR, "cpu-plugin: processor_info returned only %i elements..\n", cpu_info_len);
+ syslog (LOG_ERR, "cpu plugin: processor_info returned only %i elements..", cpu_info_len);
continue;
}
- cpu_submit (cpu, cpu_info.cpu_ticks[CPU_STATE_USER],
- cpu_info.cpu_ticks[CPU_STATE_NICE],
- cpu_info.cpu_ticks[CPU_STATE_SYSTEM],
- cpu_info.cpu_ticks[CPU_STATE_IDLE],
- 0ULL);
+ submit (cpu, "user", (counter_t) cpu_info.cpu_ticks[CPU_STATE_USER]);
+ submit (cpu, "nice", (counter_t) cpu_info.cpu_ticks[CPU_STATE_USER]);
+ submit (cpu, "system", (counter_t) cpu_info.cpu_ticks[CPU_STATE_USER]);
+ submit (cpu, "idle", (counter_t) cpu_info.cpu_ticks[CPU_STATE_USER]);
#endif /* PROCESSOR_CPU_LOAD_INFO */
#if PROCESSOR_TEMPERATURE
/*
cpu_temp, &cpu_temp_len);
if (status != KERN_SUCCESS)
{
- syslog (LOG_ERR, "cpu-plugin: processor_info failed: %s",
+ syslog (LOG_ERR, "cpu plugin: processor_info failed: %s",
mach_error_string (status));
cpu_temp_retry_counter = cpu_temp_retry_step;
/* #endif PROCESSOR_CPU_LOAD_INFO */
#elif defined(KERNEL_LINUX)
-# define BUFSIZE 1024
int cpu;
- unsigned long long user, nice, syst, idle;
- unsigned long long wait, intr, sitr; /* sitr == soft interrupt */
+ counter_t user, nice, syst, idle;
+ counter_t wait, intr, sitr; /* sitr == soft interrupt */
FILE *fh;
- char buf[BUFSIZE];
+ char buf[1024];
char *fields[9];
int numfields;
plugin_complain (LOG_ERR, &complain_obj, "cpu plugin: "
"fopen (/proc/stat) failed: %s",
strerror (errno));
- return;
+ return (-1);
}
plugin_relief (LOG_NOTICE, &complain_obj, "cpu plugin: "
"fopen (/proc/stat) succeeded.");
- while (fgets (buf, BUFSIZE, fh) != NULL)
+ while (fgets (buf, 1024, fh) != NULL)
{
if (strncmp (buf, "cpu", 3))
continue;
syst = atoll (fields[3]);
idle = atoll (fields[4]);
+ submit (cpu, "user", user);
+ submit (cpu, "nice", nice);
+ submit (cpu, "system", syst);
+ submit (cpu, "idle", idle);
+
if (numfields >= 8)
{
wait = atoll (fields[5]);
intr = atoll (fields[6]);
sitr = atoll (fields[7]);
- /* I doubt anyone cares about the time spent in
- * interrupt handlers.. */
- syst += intr + sitr;
- }
- else
- {
- wait = 0LL;
+ submit (cpu, "wait", wait);
+ submit (cpu, "interrupt", intr);
+ submit (cpu, "softirq", sitr);
}
-
- cpu_submit (cpu, user, nice, syst, idle, wait);
}
fclose (fh);
-#undef BUFSIZE
/* #endif defined(KERNEL_LINUX) */
#elif defined(HAVE_LIBKSTAT)
int cpu;
- unsigned long long user, syst, idle, wait;
+ counter_t user, syst, idle, wait;
static cpu_stat_t cs;
if (kc == NULL)
if (kstat_read (kc, ksp[cpu], &cs) == -1)
continue; /* error message? */
- idle = (unsigned long long) cs.cpu_sysinfo.cpu[CPU_IDLE];
- user = (unsigned long long) cs.cpu_sysinfo.cpu[CPU_USER];
- syst = (unsigned long long) cs.cpu_sysinfo.cpu[CPU_KERNEL];
- wait = (unsigned long long) cs.cpu_sysinfo.cpu[CPU_WAIT];
+ idle = (counter_t) cs.cpu_sysinfo.cpu[CPU_IDLE];
+ user = (counter_t) cs.cpu_sysinfo.cpu[CPU_USER];
+ syst = (counter_t) cs.cpu_sysinfo.cpu[CPU_KERNEL];
+ wait = (counter_t) cs.cpu_sysinfo.cpu[CPU_WAIT];
- cpu_submit (ksp[cpu]->ks_instance,
- user, 0LL, syst, idle, wait);
+ submit (ksp[cpu]->ks_instance, "user", user);
+ submit (ksp[cpu]->ks_instance, "system", syst);
+ submit (ksp[cpu]->ks_instance, "idle", idle);
+ submit (ksp[cpu]->ks_instance, "wait", wait);
}
/* #endif defined(HAVE_LIBKSTAT) */
cpuinfo[CP_SYS] += cpuinfo[CP_INTR];
- /* FIXME: Instance is always `0' */
- cpu_submit (0, cpuinfo[CP_USER], cpuinfo[CP_NICE], cpuinfo[CP_SYS], cpuinfo[CP_IDLE], 0LL);
+ submit (0, "user", cpuinfo[CP_USER]);
+ submit (0, "nice", cpuinfo[CP_NICE]);
+ submit (0, "system", cpuinfo[CP_SYS]);
+ submit (0, "idle", cpuinfo[CP_IDLE]);
#endif
- return;
+ return (0);
}
-#else
-# define cpu_read NULL
#endif /* CPU_HAVE_READ */
void module_register (void)
{
- plugin_register (MODULE_NAME, cpu_init, cpu_read, cpu_write);
-}
+ plugin_register_data_set (&ds);
-#undef MODULE_NAME
+#if CPU_HAVE_READ
+ plugin_register_init ("cpu", init);
+ plugin_register_read ("cpu", cpu_read);
+#endif /* CPU_HAVE_READ */
+}
/**
* collectd - src/cpufreq.c
- * Copyright (C) 2005,2006 Peter Holik
+ * Copyright (C) 2005-2007 Peter Holik
*
* 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
# define CPUFREQ_HAVE_READ 0
#endif
-static char *cpufreq_file = "cpufreq-%s.rrd";
+static data_source_t data_source[1] =
+{
+ {"value", DS_TYPE_GAUGE, 0, NAN}
+};
-static char *ds_def[] =
+static data_set_t data_set =
{
- "DS:value:GAUGE:"COLLECTD_HEARTBEAT":0:U",
- NULL
+ "cpufreq", 1, data_source
};
-static int ds_num = 1;
+#if CPUFREQ_HAVE_READ
#ifdef KERNEL_LINUX
static int num_cpu = 0;
#endif
-#define BUFSIZE 256
-
-static void cpufreq_init (void)
+static int cpufreq_init (void)
{
#ifdef KERNEL_LINUX
int status;
- char filename[BUFSIZE];
+ char filename[256];
num_cpu = 0;
while (1)
{
- status = snprintf (filename, BUFSIZE, "/sys/devices/system/cpu/cpu%d/cpufreq/scaling_cur_freq", num_cpu);
- if (status < 1 || status >= BUFSIZE)
+ status = snprintf (filename, sizeof (filename),
+ "/sys/devices/system/cpu/cpu%d/cpufreq/"
+ "scaling_cur_freq", num_cpu);
+ if (status < 1 || status >= sizeof (filename))
break;
- if (access(filename, R_OK))
+ if (access (filename, R_OK))
break;
num_cpu++;
}
- syslog (LOG_INFO, MODULE_NAME" found %d cpu(s)", num_cpu);
+ syslog (LOG_INFO, "cpufreq plugin: Found %d CPU%s", num_cpu,
+ (num_cpu == 1) ? "" : "s");
+
+ if (num_cpu == 0)
+ plugin_unregister_read ("cpufreq");
#endif /* defined(KERNEL_LINUX) */
- return;
-}
+ return (0);
+} /* int cpufreq_init */
-static void cpufreq_write (char *host, char *inst, char *val)
+static void cpufreq_submit (int cpu_num, double value)
{
- int status;
- char file[BUFSIZE];
-
- status = snprintf (file, BUFSIZE, cpufreq_file, inst);
- if (status < 1 || status >= BUFSIZE)
- return;
-
- rrd_update_file (host, file, val, ds_def, ds_num);
-}
+ value_t values[1];
+ value_list_t vl = VALUE_LIST_INIT;
-#if CPUFREQ_HAVE_READ
-static void cpufreq_submit (int cpu_num, unsigned long long val)
-{
- char buf[BUFSIZE];
- char cpu[16];
+ values[0].gauge = value;
- if (snprintf (buf, BUFSIZE, "%u:%llu", (unsigned int) curtime, val) >= BUFSIZE)
- return;
- snprintf (cpu, 16, "%i", cpu_num);
+ vl.values = values;
+ vl.values_len = 1;
+ vl.time = time (NULL);
+ strcpy (vl.host, hostname);
+ strcpy (vl.plugin, "cpufreq");
+ snprintf (vl.type_instance, sizeof (vl.type_instance),
+ "%i", cpu_num);
- plugin_submit (MODULE_NAME, cpu, buf);
+ plugin_dispatch_values ("cpufreq", &vl);
}
-static void cpufreq_read (void)
+static int cpufreq_read (void)
{
#ifdef KERNEL_LINUX
int status;
unsigned long long val;
int i = 0;
FILE *fp;
- char filename[BUFSIZE];
+ char filename[256];
char buffer[16];
for (i = 0; i < num_cpu; i++)
{
- status = snprintf (filename, BUFSIZE, "/sys/devices/system/cpu/cpu%d/cpufreq/scaling_cur_freq", i);
- if (status < 1 || status >= BUFSIZE)
- return;
+ status = snprintf (filename, sizeof (filename),
+ "/sys/devices/system/cpu/cpu%d/cpufreq/"
+ "scaling_cur_freq", i);
+ if (status < 1 || status >= sizeof (filename))
+ return (-1);
if ((fp = fopen (filename, "r")) == NULL)
{
syslog (LOG_WARNING, "cpufreq: fopen: %s", strerror (errno));
- return;
+ return (-1);
}
if (fgets (buffer, 16, fp) == NULL)
{
syslog (LOG_WARNING, "cpufreq: fgets: %s", strerror (errno));
fclose (fp);
- return;
+ return (-1);
}
if (fclose (fp))
}
#endif /* defined(KERNEL_LINUX) */
- return;
-}
-#else
-#define cpufreq_read NULL
-#endif
+ return (0);
+} /* int cpufreq_read */
+#endif /* CPUFREQ_HAVE_READ */
#undef BUFSIZE
void module_register (void)
{
- plugin_register (MODULE_NAME, cpufreq_init, cpufreq_read, cpufreq_write);
-}
+ plugin_register_data_set (&data_set);
-#undef MODULE_NAME
+#if CPUFREQ_HAVE_READ
+ plugin_register_init ("cpufreq", cpufreq_init);
+ plugin_register_read ("cpufreq", cpufreq_read);
+#endif /* CPUFREQ_HAVE_READ */
+}
--- /dev/null
+/**
+ * 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 <octo at verplant.org>
+ **/
+
+#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;
+ 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);
+
+ memset (&fl, '\0', sizeof (fl));
+ fl.l_start = 0;
+ fl.l_len = 0; /* till end of file */
+ fl.l_pid = getpid ();
+ fl.l_type = F_WRLCK;
+ fl.l_whence = SEEK_SET;
+
+ 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);
+}
/**
* collectd - src/df.c
- * Copyright (C) 2005,2006 Florian octo Forster
+ * Copyright (C) 2005-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; either version 2 of the License, or (at your
- * option) any later version.
+ * 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
#include "utils_mount.h"
#include "utils_ignorelist.h"
-#define MODULE_NAME "df"
-
#if HAVE_STATFS || HAVE_STATVFS
# define DF_HAVE_READ 1
#else
# define BLOCKSIZE(s) (s).f_bsize
#endif
-static char *filename_template = "df-%s.rrd";
+/* 2^50 - 1 == 1125899906842623 = 1 Petabyte */
+static data_source_t dsrc[2] =
+{
+ {"free", DS_TYPE_GAUGE, 0, 1125899906842623.0},
+ {"used", DS_TYPE_GAUGE, 0, 1125899906842623.0}
+};
-static char *ds_def[] =
+static data_set_t ds =
{
- "DS:used:GAUGE:"COLLECTD_HEARTBEAT":0:U",
- "DS:free:GAUGE:"COLLECTD_HEARTBEAT":0:U",
- NULL
+ "df", 2, dsrc
};
-static int ds_num = 2;
-static char *config_keys[] =
+#if DF_HAVE_READ
+static const char *config_keys[] =
{
"Device",
"MountPoint",
static ignorelist_t *il_mountpoint = NULL;
static ignorelist_t *il_fstype = NULL;
-#define BUFSIZE 512
-
-static void df_init (void)
+static int df_init (void)
{
if (il_device == NULL)
il_device = ignorelist_create (1);
if (il_fstype == NULL)
il_fstype = ignorelist_create (1);
- return;
+ return (0);
}
-static int df_config (char *key, char *value)
+static int df_config (const char *key, const char *value)
{
df_init ();
return (-1);
}
-static void df_write (char *host, char *inst, char *val)
-{
- char file[BUFSIZE];
- int status;
-
- status = snprintf (file, BUFSIZE, filename_template, inst);
- if (status < 1)
- return;
- else if (status >= BUFSIZE)
- return;
-
- rrd_update_file (host, file, val, ds_def, ds_num);
-}
-
-#if DF_HAVE_READ
static void df_submit (char *df_name,
- unsigned long long df_used,
- unsigned long long df_free)
+ gauge_t df_used,
+ gauge_t df_free)
{
- char buf[BUFSIZE];
+ value_t values[2];
+ value_list_t vl = VALUE_LIST_INIT;
- if (snprintf (buf, BUFSIZE, "%u:%llu:%llu", (unsigned int) curtime,
- df_used, df_free) >= BUFSIZE)
- return;
+ values[0].gauge = df_used;
+ values[1].gauge = df_free;
- plugin_submit (MODULE_NAME, df_name, buf);
-}
+ vl.values = values;
+ vl.values_len = 2;
+ vl.time = time (NULL);
+ strcpy (vl.host, hostname);
+ strcpy (vl.plugin, "df");
+ strcpy (vl.plugin_instance, "");
+ strncpy (vl.type_instance, df_name, sizeof (vl.type_instance));
-static void df_read (void)
+ plugin_dispatch_values ("df", &vl);
+} /* void df_submit */
+
+static int df_read (void)
{
#if HAVE_STATVFS
struct statvfs statbuf;
cu_mount_t *mnt_ptr;
unsigned long long blocksize;
- unsigned long long df_free;
- unsigned long long df_used;
- char mnt_name[BUFSIZE];
+ gauge_t df_free;
+ gauge_t df_used;
+ char mnt_name[256];
mnt_list = NULL;
if (cu_mount_getlist (&mnt_list) == NULL)
- return;
+ return (-1);
for (mnt_ptr = mnt_list; mnt_ptr != NULL; mnt_ptr = mnt_ptr->next)
{
if (strcmp (mnt_ptr->dir, "/") == 0)
{
- strncpy (mnt_name, "root", BUFSIZE);
+ strncpy (mnt_name, "root", sizeof (mnt_name));
}
else
{
int i, len;
- strncpy (mnt_name, mnt_ptr->dir + 1, BUFSIZE);
+ strncpy (mnt_name, mnt_ptr->dir + 1, sizeof (mnt_name));
len = strlen (mnt_name);
for (i = 0; i < len; i++)
}
cu_mount_freelist (mnt_list);
-} /* static void df_read (void) */
-#else
-# define df_read NULL
+
+ return (0);
+} /* int df_read */
#endif /* DF_HAVE_READ */
void module_register (void)
{
- plugin_register (MODULE_NAME, df_init, df_read, df_write);
- cf_register (MODULE_NAME, df_config, config_keys, config_keys_num);
-}
+ plugin_register_data_set (&ds);
-#undef BUFSIZE
-#undef MODULE_NAME
+#if DF_HAVE_READ
+ plugin_register_config ("df", df_config, config_keys, config_keys_num);
+ plugin_register_init ("df", df_init);
+ plugin_register_read ("df", df_read);
+#endif
+} /* void module_register */
/**
* collectd - src/disk.c
- * Copyright (C) 2005,2006 Florian octo Forster
+ * Copyright (C) 2005-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; either version 2 of the License, or (at your
- * option) any later version.
+ * 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
#include "plugin.h"
#include "utils_debug.h"
-#define MODULE_NAME "disk"
-
#if HAVE_MACH_MACH_TYPES_H
# include <mach/mach_types.h>
#endif
# define DISK_HAVE_READ 0
#endif
-static char *disk_filename_template = "disk-%s.rrd";
-static char *part_filename_template = "partition-%s.rrd";
+/* 2^34 = 17179869184 = ~17.2GByte/s */
+static data_source_t octets_dsrc[2] =
+{
+ {"read", DS_TYPE_COUNTER, 0, 17179869183.0},
+ {"write", DS_TYPE_COUNTER, 0, 17179869183.0}
+};
+
+static data_set_t octets_ds =
+{
+ "disk_octets", 2, octets_dsrc
+};
+
+static data_source_t operations_dsrc[2] =
+{
+ {"read", DS_TYPE_COUNTER, 0, 4294967295.0},
+ {"write", DS_TYPE_COUNTER, 0, 4294967295.0}
+};
-/* 104857600 == 100 MB */
-static char *disk_ds_def[] =
+static data_set_t operations_ds =
{
- "DS:rcount:COUNTER:"COLLECTD_HEARTBEAT":0:U",
- "DS:rmerged:COUNTER:"COLLECTD_HEARTBEAT":0:U",
- "DS:rbytes:COUNTER:"COLLECTD_HEARTBEAT":0:104857600",
- "DS:rtime:COUNTER:"COLLECTD_HEARTBEAT":0:U",
- "DS:wcount:COUNTER:"COLLECTD_HEARTBEAT":0:U",
- "DS:wmerged:COUNTER:"COLLECTD_HEARTBEAT":0:U",
- "DS:wbytes:COUNTER:"COLLECTD_HEARTBEAT":0:104857600",
- "DS:wtime:COUNTER:"COLLECTD_HEARTBEAT":0:U",
- NULL
+ "disk_ops", 2, operations_dsrc
};
-static int disk_ds_num = 8;
-static char *part_ds_def[] =
+static data_source_t merged_dsrc[2] =
{
- "DS:rcount:COUNTER:"COLLECTD_HEARTBEAT":0:U",
- "DS:rbytes:COUNTER:"COLLECTD_HEARTBEAT":0:104857600",
- "DS:wcount:COUNTER:"COLLECTD_HEARTBEAT":0:U",
- "DS:wbytes:COUNTER:"COLLECTD_HEARTBEAT":0:104857600",
- NULL
+ {"read", DS_TYPE_COUNTER, 0, 4294967295.0},
+ {"write", DS_TYPE_COUNTER, 0, 4294967295.0}
};
-static int part_ds_num = 4;
+static data_set_t merged_ds =
+{
+ "disk_merged", 2, merged_dsrc
+};
+
+/* max is 1000000us per second. */
+static data_source_t time_dsrc[2] =
+{
+ {"read", DS_TYPE_COUNTER, 0, 1000000.0},
+ {"write", DS_TYPE_COUNTER, 0, 1000000.0}
+};
+
+static data_set_t time_ds =
+{
+ "disk_time", 2, time_dsrc
+};
+
+#if DISK_HAVE_READ
#if HAVE_IOKIT_IOKITLIB_H
static mach_port_t io_master_port = MACH_PORT_NULL;
/* #endif HAVE_IOKIT_IOKITLIB_H */
/* This overflows in roughly 1361 year */
unsigned int poll_count;
- unsigned long long read_sectors;
- unsigned long long write_sectors;
+ counter_t read_sectors;
+ counter_t write_sectors;
- unsigned long long read_bytes;
- unsigned long long write_bytes;
+ counter_t read_bytes;
+ counter_t write_bytes;
struct diskstats *next;
} diskstats_t;
static int numdisk = 0;
#endif /* HAVE_LIBKSTAT */
-static void disk_init (void)
+static int disk_init (void)
{
#if HAVE_IOKIT_IOKITLIB_H
kern_return_t status;
syslog (LOG_ERR, "IOMasterPort failed: %s",
mach_error_string (status));
io_master_port = MACH_PORT_NULL;
- return;
+ return (-1);
}
/* #endif HAVE_IOKIT_IOKITLIB_H */
numdisk = 0;
if (kc == NULL)
- return;
+ return (-1);
for (numdisk = 0, ksp_chain = kc->kc_chain;
(numdisk < MAX_NUMDISK) && (ksp_chain != NULL);
}
#endif /* HAVE_LIBKSTAT */
- return;
-}
+ return (0);
+} /* int disk_init */
-static void disk_write (char *host, char *inst, char *val)
+static void disk_submit (const char *plugin_instance,
+ const char *type,
+ counter_t read, counter_t write)
{
- char file[512];
- int status;
+ value_t values[2];
+ value_list_t vl = VALUE_LIST_INIT;
- status = snprintf (file, 512, disk_filename_template, inst);
- if (status < 1)
- return;
- else if (status >= 512)
- return;
+ values[0].counter = read;
+ values[1].counter = write;
- rrd_update_file (host, file, val, disk_ds_def, disk_ds_num);
-}
+ vl.values = values;
+ vl.values_len = 2;
+ vl.time = time (NULL);
+ strcpy (vl.host, hostname);
+ strcpy (vl.plugin, "disk");
+ strncpy (vl.plugin_instance, plugin_instance,
+ sizeof (vl.plugin_instance));
-static void partition_write (char *host, char *inst, char *val)
-{
- char file[512];
- int status;
-
- status = snprintf (file, 512, part_filename_template, inst);
- if (status < 1)
- return;
- else if (status >= 512)
- return;
-
- rrd_update_file (host, file, val, part_ds_def, part_ds_num);
-}
-
-#if DISK_HAVE_READ
-#define BUFSIZE 512
-static void disk_submit (char *disk_name,
- unsigned long long read_count,
- unsigned long long read_merged,
- unsigned long long read_bytes,
- unsigned long long read_time,
- unsigned long long write_count,
- unsigned long long write_merged,
- unsigned long long write_bytes,
- unsigned long long write_time)
-{
- char buf[BUFSIZE];
-
- if (snprintf (buf, BUFSIZE, "%u:%llu:%llu:%llu:%llu:%llu:%llu:%llu:%llu",
- (unsigned int) curtime,
- read_count, read_merged, read_bytes, read_time,
- write_count, write_merged, write_bytes,
- write_time) >= BUFSIZE)
- return;
-
- DBG ("disk_name = %s; buf = %s;",
- disk_name, buf);
-
- plugin_submit (MODULE_NAME, disk_name, buf);
-}
-
-#if KERNEL_LINUX || HAVE_LIBKSTAT
-static void partition_submit (char *part_name,
- unsigned long long read_count,
- unsigned long long read_bytes,
- unsigned long long write_count,
- unsigned long long write_bytes)
-{
- char buf[BUFSIZE];
-
- if (snprintf (buf, BUFSIZE, "%u:%llu:%llu:%llu:%llu",
- (unsigned int) curtime,
- read_count, read_bytes, write_count,
- write_bytes) >= BUFSIZE)
- return;
-
- plugin_submit ("partition", part_name, buf);
-}
-#endif /* KERNEL_LINUX || HAVE_LIBKSTAT */
-#undef BUFSIZE
+ plugin_dispatch_values (type, &vl);
+} /* void disk_submit */
#if HAVE_IOKIT_IOKITLIB_H
static signed long long dict_get_value (CFDictionaryRef dict, const char *key)
}
#endif /* HAVE_IOKIT_IOKITLIB_H */
-static void disk_read (void)
+static int disk_read (void)
{
#if HAVE_IOKIT_IOKITLIB_H
io_registry_entry_t disk;
{
plugin_complain (LOG_ERR, &complain_obj, "disk plugin: "
"IOServiceGetMatchingServices failed.");
- return;
+ return (-1);
}
else if (complain_obj.interval != 0)
{
continue;
}
+ /* kIOBSDNameKey */
disk_major = (int) dict_get_value (child_dict,
kIOBSDMajorKey);
disk_minor = (int) dict_get_value (child_dict,
kIOBlockStorageDriverStatisticsWritesKey);
write_byt = dict_get_value (stats_dict,
kIOBlockStorageDriverStatisticsBytesWrittenKey);
+ /* This property describes the number of nanoseconds spent
+ * performing writes since the block storage driver was
+ * instantiated. It is one of the statistic entries listed
+ * under the top-level kIOBlockStorageDriverStatisticsKey
+ * property table. It has an OSNumber value. */
write_tme = dict_get_value (stats_dict,
kIOBlockStorageDriverStatisticsTotalWriteTimeKey);
}
DBG ("disk_name = %s", disk_name);
- if ((read_ops != -1LL)
- || (read_byt != -1LL)
- || (read_tme != -1LL)
- || (write_ops != -1LL)
- || (write_byt != -1LL)
- || (write_tme != -1LL))
- disk_submit (disk_name,
- read_ops, 0ULL, read_byt, read_tme,
- write_ops, 0ULL, write_byt, write_tme);
+ if ((read_byt != -1LL) || (write_byt != -1LL))
+ disk_submit (disk_name, "disk_octets", read_byt, write_byt);
+ if ((read_ops != -1LL) || (write_ops != -1LL))
+ disk_submit (disk_name, "disk_ops", read_ops, write_ops);
+ if ((read_tme != -1LL) || (write_tme != -1LL))
+ disk_submit (disk_name, "disk_time",
+ read_tme / 1000,
+ write_tme / 1000);
CFRelease (child_dict);
IOObjectRelease (disk_child);
#elif KERNEL_LINUX
FILE *fh;
char buffer[1024];
- char disk_name[128];
char *fields[32];
int numfields;
int major = 0;
int minor = 0;
- unsigned long long read_sectors = 0ULL;
- unsigned long long write_sectors = 0ULL;
-
- unsigned long long read_count = 0ULL;
- unsigned long long read_merged = 0ULL;
- unsigned long long read_bytes = 0ULL;
- unsigned long long read_time = 0ULL;
- unsigned long long write_count = 0ULL;
- unsigned long long write_merged = 0ULL;
- unsigned long long write_bytes = 0ULL;
- unsigned long long write_time = 0ULL;
+ counter_t read_sectors = 0;
+ counter_t write_sectors = 0;
+
+ counter_t read_count = 0;
+ counter_t read_merged = 0;
+ counter_t read_bytes = 0;
+ counter_t read_time = 0;
+ counter_t write_count = 0;
+ counter_t write_merged = 0;
+ counter_t write_bytes = 0;
+ counter_t write_time = 0;
int is_disk = 0;
diskstats_t *ds, *pre_ds;
{
if ((fh = fopen ("/proc/partitions", "r")) == NULL)
{
- plugin_complain (LOG_ERR, &complain_obj, "disk plugin: Failed to open /proc/{diskstats,partitions}.");
- return;
+ plugin_complain (LOG_ERR, &complain_obj,
+ "disk plugin: Failed to open /proc/"
+ "{diskstats,partitions}.");
+ return (-1);
}
/* Kernel is 2.4.* */
fieldshift = 1;
}
- plugin_relief (LOG_NOTICE, &complain_obj, "disk plugin: Succeeded to open /proc/{diskstats,partitions}.");
+ plugin_relief (LOG_NOTICE, &complain_obj, "disk plugin: "
+ "Succeeded to open /proc/{diskstats,partitions}.");
- while (fgets (buffer, 1024, fh) != NULL)
+ while (fgets (buffer, sizeof (buffer), fh) != NULL)
{
+ char *disk_name;
+
numfields = strsplit (buffer, fields, 32);
if ((numfields != (14 + fieldshift)) && (numfields != 7))
major = atoll (fields[0]);
minor = atoll (fields[1]);
- if (snprintf (disk_name, 128, "%i-%i", major, minor) < 1)
- continue;
- disk_name[127] = '\0';
+ disk_name = fields[2];
for (ds = disklist, pre_ds = disklist; ds != NULL; pre_ds = ds, ds = ds->next)
if (strcmp (disk_name, ds->name) == 0)
continue;
}
+ if ((read_bytes != -1LL) || (write_bytes != -1LL))
+ disk_submit (disk_name, "disk_octets", read_bytes, write_bytes);
+ if ((read_count != -1LL) || (write_count != -1LL))
+ disk_submit (disk_name, "disk_ops", read_count, write_count);
if (is_disk)
- disk_submit (disk_name, read_count, read_merged, read_bytes, read_time,
- write_count, write_merged, write_bytes, write_time);
- else
- partition_submit (disk_name, read_count, read_bytes, write_count, write_bytes);
- }
+ {
+ if ((read_merged != -1LL) || (write_merged != -1LL))
+ disk_submit (disk_name, "disk_merged",
+ read_merged, write_merged);
+ if ((read_time != -1LL) || (write_time != -1LL))
+ disk_submit (disk_name, "disk_time",
+ read_time * 1000,
+ write_time * 1000);
+ }
+ } /* while (fgets (buffer, sizeof (buffer), fh) != NULL) */
fclose (fh);
/* #endif defined(KERNEL_LINUX) */
int i;
if (kc == NULL)
- return;
+ return (-1);
for (i = 0; i < numdisk; i++)
{
continue;
if (strncmp (ksp[i]->ks_class, "disk", 4) == 0)
- disk_submit (ksp[i]->ks_name,
- kio.reads, 0LL, kio.nread, kio.rtime,
- kio.writes, 0LL, kio.nwritten, kio.wtime);
+ {
+ disk_submit (ksp[i]->ks_name, "disk_octets", kio.reads, kio.writes);
+ disk_submit (ksp[i]->ks_name, "disk_ops", kio.nreads, kio.nwrites);
+ /* FIXME: Convert this to microseconds if necessary */
+ disk_submit (ksp[i]->ks_name, "disk_time", kio.rtime, kio.wtime);
+ }
else if (strncmp (ksp[i]->ks_class, "partition", 9) == 0)
- partition_submit (ksp[i]->ks_name,
- kio.reads, kio.nread,
- kio.writes,kio.nwritten);
+ {
+ disk_submit (ksp[i]->ks_name, "disk_octets", kio.reads, kio.writes);
+ disk_submit (ksp[i]->ks_name, "disk_ops", kio.nreads, kio.nwrites);
+ }
}
#endif /* defined(HAVE_LIBKSTAT) */
-} /* static void disk_read (void) */
-#else
-# define disk_read NULL
+
+ return (0);
+} /* int disk_read */
#endif /* DISK_HAVE_READ */
void module_register (void)
{
- plugin_register ("partition", NULL, NULL, partition_write);
- plugin_register (MODULE_NAME, disk_init, disk_read, disk_write);
-}
+ plugin_register_data_set (&octets_ds);
+ plugin_register_data_set (&operations_ds);
+ plugin_register_data_set (&merged_ds);
+ plugin_register_data_set (&time_ds);
-#undef MODULE_NAME
+#if DISK_HAVE_READ
+ plugin_register_init ("disk", disk_init);
+ plugin_register_read ("disk", disk_read);
+#endif /* DISK_HAVE_READ */
+}
/**
* collectd - src/dns.c
- * Copyright (C) 2006 Florian octo Forster
+ * Copyright (C) 2006,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; either version 2 of the License, or (at your
- * option) any later version.
+ * 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
#include "configfile.h"
#include "utils_debug.h"
-#define MODULE_NAME "dns"
-
#if HAVE_LIBPCAP && HAVE_LIBPTHREAD
# include "utils_dns.h"
# include <pthread.h>
# include <pcap.h>
-# include <sys/poll.h>
+# include <poll.h>
# define DNS_HAVE_READ 1
#else
# define DNS_HAVE_READ 0
/*
* Private variables
*/
-static char *traffic_file = "dns/dns_traffic.rrd";
-static char *qtype_file = "dns/qtype-%s.rrd";
-static char *opcode_file = "dns/opcode-%s.rrd";
-static char *rcode_file = "dns/rcode-%s.rrd";
+static data_source_t octets_dsrc[2] =
+{
+ {"queries", DS_TYPE_COUNTER, 0, 125000000.0},
+ {"responses", DS_TYPE_COUNTER, 0, 125000000.0}
+};
-static char *traffic_ds_def[] =
+static data_set_t octets_ds =
{
- /* Limit to 1GBit/s */
- "DS:queries:COUNTER:"COLLECTD_HEARTBEAT":0:125000000",
- "DS:responses:COUNTER:"COLLECTD_HEARTBEAT":0:125000000",
- NULL
+ "dns_octets", 2, octets_dsrc
};
-static int traffic_ds_num = 2;
-static char *qtype_ds_def[] =
+static data_source_t counter_dsrc[1] =
{
- "DS:value:COUNTER:"COLLECTD_HEARTBEAT":0:65535",
- NULL
+ {"value", DS_TYPE_COUNTER, 0, 65535.0}
};
-static int qtype_ds_num = 1;
-static char *opcode_ds_def[] =
+static data_set_t qtype_ds =
{
- "DS:value:COUNTER:"COLLECTD_HEARTBEAT":0:65535",
- NULL
+ "dns_qtype", 1, counter_dsrc
};
-static int opcode_ds_num = 1;
-static char *rcode_ds_def[] =
+static data_set_t opcode_ds =
{
- "DS:value:COUNTER:"COLLECTD_HEARTBEAT":0:65535",
- NULL
+ "dns_opcode", 1, counter_dsrc
+};
+
+static data_set_t rcode_ds =
+{
+ "dns_rcode", 1, counter_dsrc
};
-static int rcode_ds_num = 1;
#if DNS_HAVE_READ
-static char *config_keys[] =
+static const char *config_keys[] =
{
"Interface",
"IgnoreSource",
#define PCAP_SNAPLEN 1460
static char *pcap_device = NULL;
-static unsigned int tr_queries;
-static unsigned int tr_responses;
+static counter_t tr_queries;
+static counter_t tr_responses;
static counter_list_t *qtype_list;
static counter_list_t *opcode_list;
static counter_list_t *rcode_list;
DBG ("return ()");
}
-static int dns_config (char *key, char *value)
+static int dns_config (const char *key, const char *value)
{
if (strcasecmp (key, "Interface") == 0)
{
return (NULL);
} /* static void dns_child_loop (void) */
-#endif /* DNS_HAVE_READ */
-static void dns_init (void)
+static int dns_init (void)
{
-#if DNS_HAVE_READ
/* clean up an old thread */
int status;
pthread_mutex_unlock (&traffic_mutex);
if (listen_thread_init != 0)
- return;
+ return (-1);
status = pthread_create (&listen_thread, NULL, dns_child_loop,
(void *) 0);
{
syslog (LOG_ERR, "dns plugin: pthread_create failed: %s",
strerror (status));
- return;
+ return (-1);
}
listen_thread_init = 1;
-#endif /* DNS_HAVE_READ */
-}
-
-static void traffic_write (char *host, char *inst, char *val)
-{
- rrd_update_file (host, traffic_file, val,
- traffic_ds_def, traffic_ds_num);
-}
-
-static void qtype_write (char *host, char *inst, char *val)
-{
- char file[512];
- int status;
-
- status = snprintf (file, 512, qtype_file, inst);
- if (status < 1)
- return;
- else if (status >= 512)
- return;
-
- rrd_update_file (host, file, val, qtype_ds_def, qtype_ds_num);
-}
-
-static void rcode_write (char *host, char *inst, char *val)
-{
- char file[512];
- int status;
-
- status = snprintf (file, 512, rcode_file, inst);
- if (status < 1)
- return;
- else if (status >= 512)
- return;
- rrd_update_file (host, file, val, rcode_ds_def, rcode_ds_num);
-}
-
-static void opcode_write (char *host, char *inst, char *val)
-{
- char file[512];
- int status;
-
- status = snprintf (file, 512, opcode_file, inst);
- if (status < 1)
- return;
- else if (status >= 512)
- return;
-
- rrd_update_file (host, file, val, opcode_ds_def, opcode_ds_num);
-}
-
-#if DNS_HAVE_READ
-static void traffic_submit (unsigned int queries, unsigned int replies)
-{
- char buffer[64];
- int status;
-
- status = snprintf (buffer, 64, "N:%u:%u", queries, replies);
- if ((status < 1) || (status >= 64))
- return;
-
- plugin_submit ("dns_traffic", "-", buffer);
-}
-
-static void qtype_submit (int qtype, unsigned int counter)
-{
- char inst[32];
- char buffer[32];
- int status;
-
- strncpy (inst, qtype_str (qtype), 32);
- inst[31] = '\0';
-
- status = snprintf (buffer, 32, "N:%u", counter);
- if ((status < 1) || (status >= 32))
- return;
-
- plugin_submit ("dns_qtype", inst, buffer);
-}
+ return (0);
+} /* int dns_init */
-static void rcode_submit (int rcode, unsigned int counter)
+static void submit_counter (const char *type, const char *type_instance,
+ counter_t value)
{
- char inst[32];
- char buffer[32];
- int status;
+ value_t values[1];
+ value_list_t vl = VALUE_LIST_INIT;
- strncpy (inst, rcode_str (rcode), 32);
- inst[31] = '\0';
+ values[0].counter = value;
- status = snprintf (buffer, 32, "N:%u", counter);
- if ((status < 1) || (status >= 32))
- return;
+ vl.values = values;
+ vl.values_len = 1;
+ vl.time = time (NULL);
+ strcpy (vl.host, hostname);
+ strcpy (vl.plugin, "dns");
+ strncpy (vl.type_instance, type_instance, sizeof (vl.type_instance));
- plugin_submit ("dns_rcode", inst, buffer);
-}
+ plugin_dispatch_values (type, &vl);
+} /* void submit_counter */
-static void opcode_submit (int opcode, unsigned int counter)
+static void submit_octets (counter_t queries, counter_t responses)
{
- char inst[32];
- char buffer[32];
- int status;
+ value_t values[2];
+ value_list_t vl = VALUE_LIST_INIT;
- strncpy (inst, opcode_str (opcode), 32);
- inst[31] = '\0';
+ values[0].counter = queries;
+ values[1].counter = responses;
- status = snprintf (buffer, 32, "N:%u", counter);
- if ((status < 1) || (status >= 32))
- return;
+ vl.values = values;
+ vl.values_len = 2;
+ vl.time = time (NULL);
+ strcpy (vl.host, hostname);
+ strcpy (vl.plugin, "dns");
- plugin_submit ("dns_opcode", inst, buffer);
-}
+ plugin_dispatch_values ("dns_octets", &vl);
+} /* void submit_counter */
-static void dns_read (void)
+static int dns_read (void)
{
unsigned int keys[T_MAX];
unsigned int values[T_MAX];
values[0] = tr_queries;
values[1] = tr_responses;
pthread_mutex_unlock (&traffic_mutex);
- traffic_submit (values[0], values[1]);
+ submit_octets (values[0], values[1]);
pthread_mutex_lock (&qtype_mutex);
for (ptr = qtype_list, len = 0;
for (i = 0; i < len; i++)
{
DBG ("qtype = %u; counter = %u;", keys[i], values[i]);
- qtype_submit (keys[i], values[i]);
+ submit_counter ("dns_qtype", qtype_str (keys[i]), values[i]);
}
pthread_mutex_lock (&opcode_mutex);
for (i = 0; i < len; i++)
{
DBG ("opcode = %u; counter = %u;", keys[i], values[i]);
- opcode_submit (keys[i], values[i]);
+ submit_counter ("dns_opcode", opcode_str (keys[i]), values[i]);
}
pthread_mutex_lock (&rcode_mutex);
for (i = 0; i < len; i++)
{
DBG ("rcode = %u; counter = %u;", keys[i], values[i]);
- rcode_submit (keys[i], values[i]);
+ submit_counter ("dns_rcode", rcode_str (keys[i]), values[i]);
}
-}
-#else /* if !DNS_HAVE_READ */
-# define dns_read NULL
+
+ return (0);
+} /* int dns_read */
#endif
void module_register (void)
{
- plugin_register (MODULE_NAME, dns_init, dns_read, NULL);
- plugin_register ("dns_traffic", NULL, NULL, traffic_write);
- plugin_register ("dns_qtype", NULL, NULL, qtype_write);
- plugin_register ("dns_rcode", NULL, NULL, rcode_write);
- plugin_register ("dns_opcode", NULL, NULL, opcode_write);
+ plugin_register_data_set (&octets_ds);
+ plugin_register_data_set (&qtype_ds);
+ plugin_register_data_set (&opcode_ds);
+ plugin_register_data_set (&rcode_ds);
+
#if DNS_HAVE_READ
- cf_register (MODULE_NAME, dns_config, config_keys, config_keys_num);
+ plugin_register_config ("dns", dns_config, config_keys, config_keys_num);
+ plugin_register_init ("dns", dns_init);
+ plugin_register_read ("dns", dns_read);
#endif
-}
-
-#undef MODULE_NAME
+} /* void module_register */
--- /dev/null
+/**
+ * collectd - src/entropy.c
+ * Copyright (C) 2005,2006 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 <octo at verplant.org>
+ **/
+
+#include "collectd.h"
+#include "common.h"
+#include "plugin.h"
+
+#if KERNEL_LINUX
+# define ENTROPY_HAVE_READ 1
+#else
+# define ENTROPY_HAVE_READ 0
+#endif
+
+#define ENTROPY_FILE "/proc/sys/kernel/random/entropy_avail"
+
+static data_source_t dsrc[1] =
+{
+ {"entropy", DS_TYPE_GAUGE, 0.0, 4294967295.0}
+};
+
+static data_set_t ds =
+{
+ "entropy", 1, dsrc
+};
+
+#if ENTROPY_HAVE_READ
+static void entropy_submit (double entropy)
+{
+ value_t values[1];
+ value_list_t vl = VALUE_LIST_INIT;
+
+ values[0].gauge = entropy;
+
+ vl.values = values;
+ vl.values_len = 1;
+ vl.time = time (NULL);
+ strcpy (vl.host, hostname);
+ strcpy (vl.plugin, "entropy");
+ strcpy (vl.plugin_instance, "");
+ strcpy (vl.type_instance, "");
+
+ plugin_dispatch_values ("entropy", &vl);
+}
+
+static int entropy_read (void)
+{
+#if KERNEL_LINUX
+ double entropy;
+ FILE *fh;
+ char buffer[64];
+
+ fh = fopen (ENTROPY_FILE, "r");
+ if (fh == NULL)
+ return (-1);
+
+ if (fgets (buffer, sizeof (buffer), fh) == NULL)
+ {
+ fclose (fh);
+ return (-1);
+ }
+ fclose (fh);
+
+ entropy = atof (buffer);
+
+ if (entropy > 0.0)
+ entropy_submit (entropy);
+#endif /* KERNEL_LINUX */
+
+ return (0);
+}
+#endif /* ENTROPY_HAVE_READ */
+
+void module_register (void)
+{
+ plugin_register_data_set (&ds);
+#if ENTROPY_HAVE_READ
+ plugin_register_read ("entropy", entropy_read);
+#endif
+}
#include "configfile.h"
#include "utils_debug.h"
-#define MODULE_NAME "hddtemp"
-
-#include <netdb.h>
-#include <sys/socket.h>
-#include <netinet/in.h>
-#include <netinet/tcp.h>
-#include <libgen.h> /* for basename */
+#if HAVE_NETDB_H && HAVE_SYS_SOCKET_H && HAVE_NETINET_IN_H \
+ && HAVE_NETINET_TCP_H && HAVE_LIBGEN_H
+# include <netdb.h>
+# include <sys/socket.h>
+# include <netinet/in.h>
+# include <netinet/tcp.h>
+# include <libgen.h> /* for basename */
+# define HDDTEMP_HAVE_READ 1
+#else
+# define HDDTEMP_HAVE_READ 0
+#endif
#if HAVE_LINUX_MAJOR_H
# include <linux/major.h>
#define HDDTEMP_DEF_HOST "127.0.0.1"
#define HDDTEMP_DEF_PORT "7634"
-/* BUFFER_SIZE
- Size of the buffer we use to receive from the hddtemp daemon. */
-#define BUFFER_SIZE 1024
-
-static char *filename_format = "hddtemp-%s.rrd";
+static data_source_t data_source_temperature[1] =
+{
+ {"value", DS_TYPE_GAUGE, -273.15, NAN}
+};
-static char *ds_def[] =
+static data_set_t temperature_ds =
{
- "DS:value:GAUGE:"COLLECTD_HEARTBEAT":U:U",
- NULL
+ "temperature", 1, data_source_temperature
};
-static int ds_num = 1;
-static char *config_keys[] =
+#if HDDTEMP_HAVE_READ
+static const char *config_keys[] =
{
"Host",
"Port",
return (0);
}
-static int hddtemp_config (char *key, char *value)
+static int hddtemp_config (const char *key, const char *value)
{
if (strcasecmp (key, "host") == 0)
{
/* In the init-function we initialize the `hddname_t' list used to translate
* disk-names. Under Linux that's done using `/proc/partitions'. Under other
* operating-systems, it's not done at all. */
-static void hddtemp_init (void)
+static int hddtemp_init (void)
{
#if KERNEL_LINUX
FILE *fh;
- char buf[BUFFER_SIZE];
+ char buf[1024];
int buflen;
char *fields[16];
{
DBG ("Looking at /proc/partitions...");
- while (fgets (buf, BUFFER_SIZE, fh) != NULL)
+ while (fgets (buf, sizeof (buf), fh) != NULL)
{
/* Delete trailing newlines */
buflen = strlen (buf);
DBG ("Could not open /proc/partitions: %s",
strerror (errno));
#endif /* KERNEL_LINUX */
-}
-static void hddtemp_write (char *host, char *inst, char *val)
-{
- char filename[BUFFER_SIZE];
- int status;
-
- /* construct filename */
- status = snprintf (filename, BUFFER_SIZE, filename_format, inst);
- if (status < 1)
- return;
- else if (status >= BUFFER_SIZE)
- return;
-
- rrd_update_file (host, filename, val, ds_def, ds_num);
-}
+ return (0);
+} /* int hddtemp_init */
/*
* hddtemp_get_name
return (ret);
}
-static void hddtemp_submit (char *inst, double temperature)
+static void hddtemp_submit (char *type_instance, double value)
{
- char buf[BUFFER_SIZE];
+ value_t values[1];
+ value_list_t vl = VALUE_LIST_INIT;
+
+ values[0].gauge = value;
- if (snprintf (buf, BUFFER_SIZE, "%u:%.3f", (unsigned int) curtime, temperature)
- >= BUFFER_SIZE)
- return;
+ vl.values = values;
+ vl.values_len = 1;
+ vl.time = time (NULL);
+ strcpy (vl.host, hostname);
+ strcpy (vl.plugin, "hddtemp");
+ strncpy (vl.type_instance, type_instance, sizeof (vl.type_instance));
- plugin_submit (MODULE_NAME, inst, buf);
+ plugin_dispatch_values ("temperature", &vl);
}
-static void hddtemp_read (void)
+static int hddtemp_read (void)
{
- char buf[BUFFER_SIZE];
+ char buf[1024];
char *fields[128];
char *ptr;
int num_fields;
int num_disks;
int i;
- static int wait_time = 1;
- static int wait_left = 0;
-
- if (wait_left >= 10)
- {
- wait_left -= 10;
- return;
- }
-
/* get data from daemon */
- if (hddtemp_query_daemon (buf, BUFFER_SIZE) < 0)
- {
- /* This limit is reached in log2(86400) =~ 17 steps. Since
- * there is a 2^n seconds wait between each step it will need
- * roughly one day to reach this limit. -octo */
-
- wait_time *= 2;
- if (wait_time > 86400)
- wait_time = 86400;
-
- wait_left = wait_time;
-
- return;
- }
- else
- {
- wait_time = 1;
- wait_left = 0;
- }
+ if (hddtemp_query_daemon (buf, sizeof (buf)) < 0)
+ return (-1);
/* NB: strtok will eat up "||" and leading "|"'s */
num_fields = 0;
hddtemp_submit (name, temperature);
}
}
-}
+
+ return (0);
+} /* int hddtemp_read */
+#endif /* HDDTEMP_HAVE_READ */
/* module_register
Register collectd plugin. */
void module_register (void)
{
- plugin_register (MODULE_NAME, hddtemp_init, hddtemp_read, hddtemp_write);
- cf_register (MODULE_NAME, hddtemp_config, config_keys, config_keys_num);
+ plugin_register_data_set (&temperature_ds);
+
+#if HDDTEMP_HAVE_READ
+ plugin_register_config ("hddtemp", hddtemp_config,
+ config_keys, config_keys_num);
+ plugin_register_init ("hddtemp", hddtemp_init);
+ plugin_register_read ("hddtemp", hddtemp_read);
+#endif /* HDDTEMP_HAVE_READ */
}
-
-#undef MODULE_NAME
*
* 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; either version 2 of the License, or (at your
- * option) any later version.
+ * 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
#endif
#endif /* defined(HAVE_GETLOADAVG) */
-static char *load_file = "load.rrd";
-
-static char *ds_def[] =
+static data_source_t dsrc[3] =
{
- "DS:shortterm:GAUGE:"COLLECTD_HEARTBEAT":0:100",
- "DS:midterm:GAUGE:"COLLECTD_HEARTBEAT":0:100",
- "DS:longterm:GAUGE:"COLLECTD_HEARTBEAT":0:100",
- NULL
+ {"shortterm", DS_TYPE_GAUGE, 0.0, 100.0},
+ {"midterm", DS_TYPE_GAUGE, 0.0, 100.0},
+ {"longterm", DS_TYPE_GAUGE, 0.0, 100.0}
};
-static int ds_num = 3;
-
-static void load_init (void)
-{
- return;
-}
-static void load_write (char *host, char *inst, char *val)
+static data_set_t ds =
{
- rrd_update_file (host, load_file, val, ds_def, ds_num);
-}
+ "load", 3, dsrc
+};
#if LOAD_HAVE_READ
-#define BUFSIZE 256
static void load_submit (double snum, double mnum, double lnum)
{
- char buf[BUFSIZE];
-
- if (snprintf (buf, BUFSIZE, "%u:%.2f:%.2f:%.2f", (unsigned int) curtime,
- snum, mnum, lnum) >= BUFSIZE)
- return;
-
- plugin_submit (MODULE_NAME, "-", buf);
+ value_t values[3];
+ value_list_t vl = VALUE_LIST_INIT;
+
+ values[0].gauge = snum;
+ values[1].gauge = mnum;
+ values[2].gauge = lnum;
+
+ vl.values = values;
+ vl.values_len = 3;
+ vl.time = time (NULL);
+ strcpy (vl.host, hostname);
+ strcpy (vl.plugin, "load");
+ strcpy (vl.plugin_instance, "");
+ strcpy (vl.type_instance, "");
+
+ plugin_dispatch_values ("load", &vl);
}
-#undef BUFSIZE
-static void load_read (void)
+static int load_read (void)
{
#if defined(HAVE_GETLOADAVG)
double load[3];
load_submit (snum, mnum, lnum);
#endif /* HAVE_LIBSTATGRAB */
+
+ return (0);
}
-#else
-# define load_read NULL
#endif /* LOAD_HAVE_READ */
void module_register (void)
{
- plugin_register (MODULE_NAME, load_init, load_read, load_write);
+ plugin_register_data_set (&ds);
+#if LOAD_HAVE_READ
+ plugin_register_read ("load", load_read);
+#endif
}
#undef MODULE_NAME
#include "configfile.h"
#include "utils_debug.h"
-#define MODULE_NAME "mbmon"
-
-#include <netdb.h>
-#include <sys/socket.h>
-#include <netinet/in.h>
-#include <netinet/tcp.h>
+#if HAVE_NETDB_H && HAVE_SYS_SOCKET_H && HAVE_NETINET_IN_H && HAVE_NETINET_TCP_H
+# include <netdb.h>
+# include <sys/socket.h>
+# include <netinet/in.h>
+# include <netinet/tcp.h>
+# define MBMON_HAVE_READ 1
+#else
+# define MBMON_HAVE_READ 0
+#endif
#define MBMON_DEF_HOST "127.0.0.1"
#define MBMON_DEF_PORT "411" /* the default for Debian */
-/* BUFFER_SIZE
- Size of the buffer we use to receive from the mbmon daemon. */
-#define BUFFER_SIZE 1024
+static data_source_t data_source_fanspeed[1] =
+{
+ {"value", DS_TYPE_GAUGE, 0, NAN}
+};
-static char *filename_temperature = "mbmon/temperature-%s.rrd";
-static char *filename_fanspeed = "mbmon/fanspeed-%s.rrd";
-static char *filename_voltage = "mbmon/voltage-%s.rrd";
+static data_set_t fanspeed_ds =
+{
+ "fanspeed", 1, data_source_fanspeed
+};
-/* temperature and fan sensors */
-static char *ds_def[] =
+static data_source_t data_source_temperature[1] =
{
- "DS:value:GAUGE:"COLLECTD_HEARTBEAT":U:U",
- NULL
+ {"value", DS_TYPE_GAUGE, -273.15, NAN}
};
-static int ds_num = 1;
-/* voltage sensors */
-static char *voltage_ds_def[] =
+static data_set_t temperature_ds =
{
- "DS:voltage:GAUGE:"COLLECTD_HEARTBEAT":U:U",
- NULL
+ "temperature", 1, data_source_temperature
+};
+
+static data_source_t data_source_voltage[1] =
+{
+ {"voltage", DS_TYPE_GAUGE, NAN, NAN}
};
-static int voltage_ds_num = 1;
-static char *config_keys[] =
+static data_set_t voltage_ds =
+{
+ "voltage", 1, data_source_voltage
+};
+
+static const char *config_keys[] =
{
"Host",
"Port",
};
static int config_keys_num = 2;
+#if MBMON_HAVE_READ
static char *mbmon_host = NULL;
static char *mbmon_port = NULL;
return (0);
}
-static int mbmon_config (char *key, char *value)
+static int mbmon_config (const char *key, const char *value)
{
if (strcasecmp (key, "host") == 0)
{
return (0);
}
-static void mbmon_init (void)
-{
- return;
-}
-
-static void mbmon_write_temperature (char *host, char *inst, char *val)
-{
- char filename[BUFFER_SIZE];
- int status;
-
- /* construct filename */
- status = snprintf (filename, BUFFER_SIZE, filename_temperature, inst);
- if ((status < 1) || (status >= BUFFER_SIZE))
- return;
-
- rrd_update_file (host, filename, val, ds_def, ds_num);
-}
-
-static void mbmon_write_fanspeed (char *host, char *inst, char *val)
-{
- char filename[BUFFER_SIZE];
- int status;
-
- /* construct filename */
- status = snprintf (filename, BUFFER_SIZE, filename_fanspeed, inst);
- if ((status < 1) || (status >= BUFFER_SIZE))
- return;
-
- rrd_update_file (host, filename, val, ds_def, ds_num);
-}
-
-static void mbmon_write_voltage (char *host, char *inst, char *val)
+static void mbmon_submit (const char *type, const char *type_instance,
+ double value)
{
- char filename[BUFFER_SIZE];
- int status;
-
- /* construct filename */
- status = snprintf (filename, BUFFER_SIZE, filename_voltage, inst);
- if ((status < 1) || (status >= BUFFER_SIZE))
- return;
-
- rrd_update_file (host, filename, val, voltage_ds_def, voltage_ds_num);
-}
+ value_t values[1];
+ value_list_t vl = VALUE_LIST_INIT;
-static void mbmon_submit (char *type, char *inst, double value)
-{
- char buf[BUFFER_SIZE];
+ values[0].gauge = value;
- if (snprintf (buf, BUFFER_SIZE, "%u:%.3f", (unsigned int) curtime, value)
- >= BUFFER_SIZE)
- return;
+ vl.values = values;
+ vl.values_len = 1;
+ vl.time = time (NULL);
+ strcpy (vl.host, hostname);
+ strcpy (vl.plugin, "mbmon");
+ strncpy (vl.type_instance, type_instance, sizeof (vl.type_instance));
- plugin_submit (type, inst, buf);
-}
+ plugin_dispatch_values (type, &vl);
+} /* void mbmon_submit */
/* Trim trailing whitespace from a string. */
static void trim_spaces (char *s)
s[l] = '\0';
}
-static void mbmon_read (void)
+static int mbmon_read (void)
{
- char buf[BUFFER_SIZE];
+ char buf[1024];
char *s, *t;
- static int wait_time = 1;
- static int wait_left = 0;
-
- if (wait_left >= 10)
- {
- wait_left -= 10;
- return;
- }
-
/* get data from daemon */
- if (mbmon_query_daemon (buf, BUFFER_SIZE) < 0)
- {
- /* This limit is reached in log2(86400) =~ 17 steps. Since
- * there is a 2^n seconds wait between each step it will need
- * roughly one day to reach this limit. -octo */
-
- wait_time *= 2;
- if (wait_time > 86400)
- wait_time = 86400;
-
- wait_left = wait_time;
-
- return;
- }
- else
- {
- wait_time = 1;
- wait_left = 0;
- }
+ if (mbmon_query_daemon (buf, sizeof (buf)) < 0)
+ return (-1);
s = buf;
while ((t = strchr (s, ':')) != NULL)
if (strncmp (s, "TEMP", 4) == 0)
{
inst = s + 4;
- type = "mbmon_temperature";
+ type = "temperature";
}
else if (strncmp (s, "FAN", 3) == 0)
{
inst = s + 3;
- type = "mbmon_fanspeed";
+ type = "fanspeed";
}
else if (strncmp (s, "V", 1) == 0)
{
inst = s + 1;
- type = "mbmon_voltage";
+ type = "voltage";
}
else
{
s = nextc + 1;
}
+
+ return (0);
} /* void mbmon_read */
+#endif /* MBMON_HAVE_READ */
/* module_register
Register collectd plugin. */
void module_register (void)
{
- plugin_register (MODULE_NAME, mbmon_init, mbmon_read, NULL);
- plugin_register ("mbmon_temperature", NULL, NULL, mbmon_write_temperature);
- plugin_register ("mbmon_fanspeed", NULL, NULL, mbmon_write_fanspeed);
- plugin_register ("mbmon_voltage", NULL, NULL, mbmon_write_voltage);
- cf_register (MODULE_NAME, mbmon_config, config_keys, config_keys_num);
+ plugin_register_data_set (&fanspeed_ds);
+ plugin_register_data_set (&temperature_ds);
+ plugin_register_data_set (&voltage_ds);
+
+#if MBMON_HAVE_READ
+ plugin_register_config ("mbmon", mbmon_config, config_keys, config_keys_num);
+ plugin_register_read ("mbmon", mbmon_read);
+#endif /* MBMON_HAVE_READ */
}
-
-#undef MODULE_NAME
/**
* collectd - src/memory.c
- * Copyright (C) 2005,2006 Florian octo Forster
+ * Copyright (C) 2005-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; either version 2 of the License, or (at your
- * option) any later version.
+ * 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
# define MEMORY_HAVE_READ 0
#endif
-#define MODULE_NAME "memory"
-
-static char *memory_file = "memory.rrd";
+/* 2^48 = 281474976710656 */
+static data_source_t dsrc[4] =
+{
+ {"used", DS_TYPE_GAUGE, 0, 281474976710656.0},
+ {"free", DS_TYPE_GAUGE, 0, 281474976710656.0},
+ {"buffers", DS_TYPE_GAUGE, 0, 281474976710656.0},
+ {"cached", DS_TYPE_GAUGE, 0, 281474976710656.0}
+};
-/* 9223372036854775807 == LLONG_MAX */
-static char *ds_def[] =
+static data_set_t ds =
{
- "DS:used:GAUGE:"COLLECTD_HEARTBEAT":0:9223372036854775807",
- "DS:free:GAUGE:"COLLECTD_HEARTBEAT":0:9223372036854775807",
- "DS:buffers:GAUGE:"COLLECTD_HEARTBEAT":0:9223372036854775807",
- "DS:cached:GAUGE:"COLLECTD_HEARTBEAT":0:9223372036854775807",
- NULL
+ "memory", 4, dsrc
};
-static int ds_num = 4;
/* vm_statistics_data_t */
#if defined(HOST_VM_INFO)
static kstat_t *ksp;
#endif /* HAVE_LIBKSTAT */
-static void memory_init (void)
+#if MEMORY_HAVE_READ
+static int memory_init (void)
{
#if defined(HOST_VM_INFO)
port_host = mach_host_self ();
ksp = NULL;
#endif /* HAVE_LIBKSTAT */
- return;
-}
-
-static void memory_write (char *host, char *inst, char *val)
-{
- rrd_update_file (host, memory_file, val, ds_def, ds_num);
-}
+ return (0);
+} /* int memory_init */
-#if MEMORY_HAVE_READ
-#define BUFSIZE 512
static void memory_submit (long long mem_used, long long mem_buffered,
long long mem_cached, long long mem_free)
{
- char buf[BUFSIZE];
+ value_t values[4];
+ value_list_t vl = VALUE_LIST_INIT;
+
+ values[0].gauge = mem_used;
+ values[1].gauge = mem_free;
+ values[2].gauge = mem_buffered;
+ values[3].gauge = mem_cached;
- if (snprintf (buf, BUFSIZE, "%u:%lli:%lli:%lli:%lli",
- (unsigned int) curtime, mem_used, mem_free,
- mem_buffered, mem_cached) >= BUFSIZE)
- return;
+ vl.values = values;
+ vl.values_len = 4;
+ vl.time = time (NULL);
+ strcpy (vl.host, hostname);
+ strcpy (vl.plugin, "memory");
- plugin_submit (MODULE_NAME, "-", buf);
+ plugin_dispatch_values ("memory", &vl);
}
-#undef BUFSIZE
-static void memory_read (void)
+static int memory_read (void)
{
#if defined(HOST_VM_INFO)
kern_return_t status;
long long free;
if (!port_host || !pagesize)
- return;
+ return (-1);
vm_data_len = sizeof (vm_data) / sizeof (natural_t);
if ((status = host_statistics (port_host, HOST_VM_INFO,
&vm_data_len)) != KERN_SUCCESS)
{
syslog (LOG_ERR, "memory-plugin: host_statistics failed and returned the value %i", (int) status);
- return;
+ return (-1);
}
/*
{
syslog (LOG_ERR, "memory plugin: sysctlbyname (%s): %s",
sysctl_keys[i], strerror (errno));
- return;
+ return (-1);
}
DBG ("%26s: %6i", sysctl_keys[i], sysctl_vals[i]);
} /* for i */
if ((fh = fopen ("/proc/meminfo", "r")) == NULL)
{
syslog (LOG_WARNING, "memory: fopen: %s", strerror (errno));
- return;
+ return (-1);
}
while (fgets (buffer, 1024, fh) != NULL)
long long mem_lock;
if (ksp == NULL)
- return;
+ return (-1);
mem_used = get_kstat_value (ksp, "pagestotal");
mem_free = get_kstat_value (ksp, "pagesfree");
mem_lock = get_kstat_value (ksp, "pageslocked");
if ((mem_used < 0LL) || (mem_free < 0LL) || (mem_lock < 0LL))
- return;
+ return (-1);
if (mem_used < (mem_free + mem_lock))
- return;
+ return (-1);
mem_used -= mem_free + mem_lock;
mem_used *= pagesize; /* If this overflows you have some serious */
if ((ios = sg_get_mem_stats ()) != NULL)
memory_submit (ios->used, 0LL, ios->cache, ios->free);
#endif /* HAVE_LIBSTATGRAB */
+
+ return (0);
}
-#else
-# define memory_read NULL
#endif /* MEMORY_HAVE_READ */
void module_register (void)
{
- plugin_register (MODULE_NAME, memory_init, memory_read, memory_write);
-}
+ plugin_register_data_set (&ds);
-#undef MODULE_NAME
+#if MEMORY_HAVE_READ
+ plugin_register_init ("memory", memory_init);
+ plugin_register_read ("memory", memory_read);
+#endif /* MEMORY_HAVE_READ */
+}
* Peter Holik <peter at holik.at>
*
* Used multimeter: Metex M-4650CR
- *
**/
-#include <termios.h>
-#include <sys/ioctl.h>
-#include <math.h>
#include "collectd.h"
#include "common.h"
#include "plugin.h"
-#define MODULE_NAME "multimeter"
-
-static char *multimeter_file = "multimeter.rrd";
+#if HAVE_TERMIOS_H && HAVE_SYS_IOCTL_H && HAVE_MATH_H
+# include <termios.h>
+# include <sys/ioctl.h>
+# include <math.h>
+# define MULTIMETER_HAVE_READ 1
+#else
+# define MULTIMETER_HAVE_READ 0
+# error "multimeter cannot read!"
+#endif
+
+static data_source_t data_source[1] =
+{
+ {"value", DS_TYPE_GAUGE, NAN, NAN}
+};
-static char *ds_def[] =
+static data_set_t data_set =
{
- "DS:value:GAUGE:"COLLECTD_HEARTBEAT":U:U",
- NULL
+ "multimeter", 1, data_source
};
-static int ds_num = 1;
+#if MULTIMETER_HAVE_READ
static int fd = -1;
static int multimeter_timeval_sub (struct timeval *tv1, struct timeval *tv2,
if (gettimeofday (&time_end, NULL) < 0)
{
- syslog (LOG_ERR, MODULE_NAME": gettimeofday failed: %s",
+ syslog (LOG_ERR, "multimeter plugin: gettimeofday failed: %s",
strerror (errno));
return (-1);
}
if (gettimeofday (&time_now, NULL) < 0)
{
- syslog (LOG_ERR, MODULE_NAME": gettimeofday failed: %s",
- strerror (errno));
+ syslog (LOG_ERR, "multimeter plugin: "
+ "gettimeofday failed: %s",
+ strerror (errno));
return (-1);
}
if (multimeter_timeval_sub (&time_end, &time_now, &timeout) == -1)
}
else /* status == -1 */
{
- syslog (LOG_ERR, MODULE_NAME": select failed: %s",
- strerror (errno));
+ syslog (LOG_ERR, "multimeter plugin: "
+ "select failed: %s",
+ strerror (errno));
break;
}
}
} while (--retry);
return (-2); /* no value received */
-}
+} /* int multimeter_read_value */
-static void multimeter_init (void)
+static int multimeter_init (void)
{
int i;
char device[] = "/dev/ttyS ";
tcsetattr(fd, TCSANOW, &tios);
ioctl(fd, TIOCMBIC, &rts);
- if (multimeter_read_value(&value) < -1)
+ if (multimeter_read_value (&value) < -1)
{
- close(fd);
+ close (fd);
fd = -1;
}
else
{
- syslog (LOG_INFO, MODULE_NAME" found (%s)", device);
- return;
+ syslog (LOG_INFO, "multimeter plugin: Device "
+ "found at %s", device);
+ return (0);
}
}
}
- syslog (LOG_ERR, MODULE_NAME" not found");
+
+ syslog (LOG_ERR, "multimeter plugin: No device found");
+ return (-1);
}
#undef LINE_LENGTH
-static void multimeter_write (char *host, char *inst, char *val)
-{
- rrd_update_file (host, multimeter_file, val, ds_def, ds_num);
-}
-#define BUFSIZE 128
-static void multimeter_submit (double *value)
+static void multimeter_submit (double value)
{
- char buf[BUFSIZE];
+ value_t values[1];
+ value_list_t vl = VALUE_LIST_INIT;
- if (snprintf (buf, BUFSIZE, "%u:%f", (unsigned int) curtime, *value) >= BUFSIZE)
- return;
+ values[0].gauge = value;
- plugin_submit (MODULE_NAME, "-", buf);
+ vl.values = values;
+ vl.values_len = 1;
+ vl.time = time (NULL);
+ strcpy (vl.host, hostname);
+ strcpy (vl.plugin, "multimeter");
+
+ plugin_dispatch_values ("multimeter", &vl);
}
-#undef BUFSIZE
-static void multimeter_read (void)
+static int multimeter_read (void)
{
double value;
- if (fd > -1 && !(multimeter_read_value(&value)))
- multimeter_submit (&value);
+ if (fd < 0)
+ return (-1);
+
+ if (multimeter_read_value (&value) != 0)
+ return (-1);
+
+ multimeter_submit (value);
+ return (0);
+} /* int multimeter_read */
+
+static int multimeter_shutdown (void)
+{
+ if (fd >= 0)
+ {
+ close (fd);
+ fd = -1;
+ }
+
+ return (0);
}
+#endif /* MULTIMETER_HAVE_READ */
void module_register (void)
{
- plugin_register (MODULE_NAME, multimeter_init, multimeter_read, multimeter_write);
-}
+ plugin_register_data_set (&data_set);
-#undef MODULE_NAME
+#if MULTIMETER_HAVE_READ
+ plugin_register_init ("multimeter", multimeter_init);
+ plugin_register_read ("multimeter", multimeter_read);
+ plugin_register_shutdown ("multimeter", multimeter_shutdown);
+#endif /* MULTIMETER_HAVE_READ */
+}
/**
* collectd - src/mysql.c
- * Copyright (C) 2006 Florian octo Forster
+ * Copyright (C) 2006,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; either version 2 of the License, or (at your
- * option) any later version.
+ * 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
#include <mysql/mysql.h>
#endif
-#define MODULE_NAME "mysql"
-
#if COLLECT_LIBMYSQL
# define MYSQL_HAVE_READ 1
#else
# define MYSQL_HAVE_READ 0
#endif
-#define BUFSIZE 512
+/* TODO: Understand `Select_*' and possibly do that stuff as well.. */
-static char *host = "localhost";
-static char *user;
-static char *pass;
-static char *db = NULL;
+static data_source_t data_source_counter[1] =
+{
+ {"value", DS_TYPE_COUNTER, 0, NAN}
+};
-/* TODO
- * understand `Select_*' and possibly do that stuff as well..
- */
+static data_set_t ds_commands =
+{
+ "mysql_commands", 1, data_source_counter
+};
-static char *commands_file = "mysql/mysql_commands-%s.rrd";
-static char *handler_file = "mysql/mysql_handler-%s.rrd";
-static char *qcache_file = "mysql/mysql_qcache.rrd";
-static char *threads_file = "mysql/mysql_threads.rrd";
-static char *traffic_file = "traffic-mysql.rrd";
+static data_set_t ds_handler =
+{
+ "mysql_handler", 1, data_source_counter
+};
-static char *commands_ds_def[] =
+static data_source_t data_source_qcache[5] =
{
- "DS:value:COUNTER:"COLLECTD_HEARTBEAT":0:U",
- NULL
+ {"hits", DS_TYPE_COUNTER, 0, NAN},
+ {"inserts", DS_TYPE_COUNTER, 0, NAN},
+ {"not_cached", DS_TYPE_COUNTER, 0, NAN},
+ {"lowmem_prunes", DS_TYPE_COUNTER, 0, NAN},
+ {"queries_in_cache", DS_TYPE_GAUGE, 0, NAN}
};
-static int commands_ds_num = 1;
-static char *handler_ds_def[] =
+static data_set_t ds_qcache =
{
- "DS:value:COUNTER:"COLLECTD_HEARTBEAT":0:U",
- NULL
+ "mysql_qcache", 5, data_source_qcache
};
-static int handler_ds_num = 1;
-static char *qcache_ds_def[] =
+static data_source_t data_source_threads[4] =
{
- "DS:hits:COUNTER:"COLLECTD_HEARTBEAT":0:U",
- "DS:inserts:COUNTER:"COLLECTD_HEARTBEAT":0:U",
- "DS:not_cached:COUNTER:"COLLECTD_HEARTBEAT":0:U",
- "DS:lowmem_prunes:COUNTER:"COLLECTD_HEARTBEAT":0:U",
- "DS:queries_in_cache:GAUGE:"COLLECTD_HEARTBEAT":0:U",
- NULL
+ {"running", DS_TYPE_GAUGE, 0, NAN},
+ {"connected", DS_TYPE_GAUGE, 0, NAN},
+ {"cached", DS_TYPE_GAUGE, 0, NAN},
+ {"created", DS_TYPE_COUNTER, 0, NAN}
};
-static int qcache_ds_num = 5;
-static char *threads_ds_def[] =
+static data_set_t ds_threads =
{
- "DS:running:GAUGE:"COLLECTD_HEARTBEAT":0:U",
- "DS:connected:GAUGE:"COLLECTD_HEARTBEAT":0:U",
- "DS:cached:GAUGE:"COLLECTD_HEARTBEAT":0:U",
- "DS:created:COUNTER:"COLLECTD_HEARTBEAT":0:U",
- NULL
+ "mysql_threads", 4, data_source_threads
};
-static int threads_ds_num = 4;
-static char *traffic_ds_def[] =
+static data_source_t data_source_octets[2] =
{
- "DS:incoming:COUNTER:"COLLECTD_HEARTBEAT":0:U",
- "DS:outgoing:COUNTER:"COLLECTD_HEARTBEAT":0:U",
- NULL
+ {"rx", DS_TYPE_COUNTER, 0, 4294967295.0},
+ {"tx", DS_TYPE_COUNTER, 0, 4294967295.0}
};
-static int traffic_ds_num = 2;
-static char *config_keys[] =
+static data_set_t ds_octets =
+{
+ "mysql_octets", 2, data_source_octets
+};
+
+#if MYSQL_HAVE_READ
+static const char *config_keys[] =
{
"Host",
"User",
};
static int config_keys_num = 4;
-#if MYSQL_HAVE_READ
+static char *host = "localhost";
+static char *user;
+static char *pass;
+static char *db = NULL;
+
static MYSQL *getconnection (void)
{
static MYSQL *con;
return (con);
}
} /* static MYSQL *getconnection (void) */
-#endif /* MYSQL_HAVE_READ */
-
-static void init (void)
-{
- return;
-}
-static int config (char *key, char *value)
+static int config (const char *key, const char *value)
{
if (strcasecmp (key, "host") == 0)
return ((host = strdup (value)) == NULL ? 1 : 0);
return (-1);
}
-static void commands_write (char *host, char *inst, char *val)
-{
- char buf[BUFSIZE];
-
- if (snprintf (buf, BUFSIZE, commands_file, inst) >= BUFSIZE)
- return;
-
- rrd_update_file (host, buf, val, commands_ds_def, commands_ds_num);
-}
-
-static void handler_write (char *host, char *inst, char *val)
-{
- char buf[BUFSIZE];
-
- if (snprintf (buf, BUFSIZE, handler_file, inst) >= BUFSIZE)
- return;
-
- rrd_update_file (host, buf, val, handler_ds_def, handler_ds_num);
-}
-
-static void qcache_write (char *host, char *inst, char *val)
-{
- rrd_update_file (host, qcache_file, val,
- qcache_ds_def, qcache_ds_num);
-}
-
-static void threads_write (char *host, char *inst, char *val)
-{
- rrd_update_file (host, threads_file, val,
- threads_ds_def, threads_ds_num);
-}
-
-static void traffic_write (char *host, char *inst, char *val)
+static void counter_submit (const char *type, const char *type_instance,
+ counter_t value)
{
- rrd_update_file (host, traffic_file, val,
- traffic_ds_def, traffic_ds_num);
-}
-
-#if MYSQL_HAVE_READ
-static void commands_submit (char *inst, unsigned long long value)
-{
- char buf[BUFSIZE];
- int status;
+ value_t values[1];
+ value_list_t vl = VALUE_LIST_INIT;
- status = snprintf (buf, BUFSIZE, "%u:%llu", (unsigned int) curtime, value);
+ values[0].counter = value;
- if (status < 0)
- {
- syslog (LOG_ERR, "snprintf failed");
- return;
- }
- else if (status >= BUFSIZE)
- {
- syslog (LOG_WARNING, "snprintf was truncated");
- return;
- }
+ vl.values = values;
+ vl.values_len = 1;
+ vl.time = time (NULL);
+ strcpy (vl.host, hostname);
+ strcpy (vl.plugin, "mysql");
+ strncpy (vl.type_instance, type_instance, sizeof (vl.type_instance));
- plugin_submit ("mysql_commands", inst, buf);
-}
+ plugin_dispatch_values (type, &vl);
+} /* void counter_submit */
-static void handler_submit (char *inst, unsigned long long value)
+static void qcache_submit (counter_t hits, counter_t inserts,
+ counter_t not_cached, counter_t lowmem_prunes,
+ gauge_t queries_in_cache)
{
- char buf[BUFSIZE];
- int status;
-
- status = snprintf (buf, BUFSIZE, "%u:%llu", (unsigned int) curtime, value);
-
- if (status < 0)
- {
- syslog (LOG_ERR, "snprintf failed");
- return;
- }
- else if (status >= BUFSIZE)
- {
- syslog (LOG_WARNING, "snprintf was truncated");
- return;
- }
-
- plugin_submit ("mysql_handler", inst, buf);
-}
-
-static void qcache_submit (unsigned long long hits, unsigned long long inserts,
- unsigned long long not_cached, unsigned long long lowmem_prunes,
- int queries_in_cache)
-{
- char buf[BUFSIZE];
- int status;
-
- status = snprintf (buf, BUFSIZE, "%u:%llu:%llu:%llu:%llu:%i",
- (unsigned int) curtime, hits, inserts, not_cached,
- lowmem_prunes, queries_in_cache);
-
- if (status < 0)
- {
- syslog (LOG_ERR, "snprintf failed");
- return;
- }
- else if (status >= BUFSIZE)
- {
- syslog (LOG_WARNING, "snprintf was truncated");
- return;
- }
-
- plugin_submit ("mysql_qcache", "-", buf);
-}
-
-static void threads_submit (int running, int connected, int cached,
- unsigned long long created)
+ value_t values[5];
+ value_list_t vl = VALUE_LIST_INIT;
+
+ values[0].counter = hits;
+ values[1].counter = inserts;
+ values[2].counter = not_cached;
+ values[3].counter = lowmem_prunes;
+ values[4].gauge = queries_in_cache;
+
+ vl.values = values;
+ vl.values_len = 5;
+ vl.time = time (NULL);
+ strcpy (vl.host, hostname);
+ strcpy (vl.plugin, "mysql");
+
+ plugin_dispatch_values ("mysql_qcache", &vl);
+} /* void qcache_submit */
+
+static void threads_submit (gauge_t running, gauge_t connected, gauge_t cached,
+ counter_t created)
{
- char buf[BUFSIZE];
- int status;
+ value_t values[4];
+ value_list_t vl = VALUE_LIST_INIT;
- status = snprintf (buf, BUFSIZE, "%u:%i:%i:%i:%llu",
- (unsigned int) curtime,
- running, connected, cached, created);
+ values[0].gauge = running;
+ values[1].gauge = connected;
+ values[2].gauge = cached;
+ values[3].counter = created;
- if (status < 0)
- {
- syslog (LOG_ERR, "snprintf failed");
- return;
- }
- else if (status >= BUFSIZE)
- {
- syslog (LOG_WARNING, "snprintf was truncated");
- return;
- }
+ vl.values = values;
+ vl.values_len = 4;
+ vl.time = time (NULL);
+ strcpy (vl.host, hostname);
+ strcpy (vl.plugin, "mysql");
- plugin_submit ("mysql_threads", "-", buf);
-}
+ plugin_dispatch_values ("mysql_threads", &vl);
+} /* void threads_submit */
-static void traffic_submit (unsigned long long incoming,
- unsigned long long outgoing)
+static void traffic_submit (counter_t rx, counter_t tx)
{
- char buf[BUFSIZE];
- int status;
+ value_t values[2];
+ value_list_t vl = VALUE_LIST_INIT;
- status = snprintf (buf, BUFSIZE, "%u:%llu:%llu", (unsigned int) curtime,
- incoming, outgoing);
+ values[0].counter = rx;
+ values[1].counter = tx;
- if (status < 0)
- {
- syslog (LOG_ERR, "snprintf failed");
- return;
- }
- else if (status >= BUFSIZE)
- {
- syslog (LOG_WARNING, "snprintf was truncated");
- return;
- }
+ vl.values = values;
+ vl.values_len = 2;
+ vl.time = time (NULL);
+ strcpy (vl.host, hostname);
+ strcpy (vl.plugin, "mysql");
- plugin_submit ("mysql_traffic", "-", buf);
-}
+ plugin_dispatch_values ("mysql_octets", &vl);
+} /* void traffic_submit */
-static void mysql_read (void)
+static int mysql_read (void)
{
MYSQL *con;
MYSQL_RES *res;
/* An error message will have been printed in this case */
if ((con = getconnection ()) == NULL)
- return;
+ return (-1);
query = "SHOW STATUS";
if (mysql_get_server_version (con) >= 50002)
{
syslog (LOG_ERR, "mysql_real_query failed: %s\n",
mysql_error (con));
- return;
+ return (-1);
}
if ((res = mysql_store_result (con)) == NULL)
{
syslog (LOG_ERR, "mysql_store_result failed: %s\n",
mysql_error (con));
- return;
+ return (-1);
}
field_num = mysql_num_fields (res);
/* Ignore `prepared statements' */
if (strncmp (key, "Com_stmt_", 9) != 0)
- commands_submit (key + 4, val);
+ counter_submit ("mysql_commands", key + 4, val);
}
else if (strncmp (key, "Handler_", 8) == 0)
{
if (val == 0ULL)
continue;
- handler_submit (key + 8, val);
+ counter_submit ("mysql_handler", key + 8, val);
}
else if (strncmp (key, "Qcache_", 7) == 0)
{
/* mysql_close (con); */
- return;
-}
-#else
-# define mysql_read NULL
+ return (0);
+} /* int mysql_read */
#endif /* MYSQL_HAVE_READ */
void module_register (void)
{
- plugin_register (MODULE_NAME, init, mysql_read, NULL);
- plugin_register ("mysql_commands", NULL, NULL, commands_write);
- plugin_register ("mysql_handler", NULL, NULL, handler_write);
- plugin_register ("mysql_qcache", NULL, NULL, qcache_write);
- plugin_register ("mysql_threads", NULL, NULL, threads_write);
- plugin_register ("mysql_traffic", NULL, NULL, traffic_write);
- cf_register (MODULE_NAME, config, config_keys, config_keys_num);
-}
+ plugin_register_data_set (&ds_commands);
+ plugin_register_data_set (&ds_handler);
+ plugin_register_data_set (&ds_qcache);
+ plugin_register_data_set (&ds_threads);
+ plugin_register_data_set (&ds_octets);
-#undef BUFSIZE
-#undef MODULE_NAME
+#if MYSQL_HAVE_READ
+ plugin_register_config ("mysql", config, config_keys, config_keys_num);
+ plugin_register_read ("mysql", mysql_read);
+#endif /* MYSQL_HAVE_READ */
+} /* void module_register */
/**
* collectd - src/network.c
- * Copyright (C) 2005,2006 Florian octo Forster
+ * Copyright (C) 2005-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; either version 2 of the License, or (at your
- * option) any later version.
+ * 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
* Florian octo Forster <octo at verplant.org>
**/
-#include <stdlib.h>
-#include <stdio.h>
-#include <string.h>
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <netdb.h>
-#include <netinet/in.h>
-#include <arpa/inet.h>
-#include <syslog.h>
-#include <errno.h>
-
-#include "network.h"
+#include "collectd.h"
+#include "plugin.h"
#include "common.h"
#include "configfile.h"
#include "utils_debug.h"
+#include "network.h"
+
+#if HAVE_PTHREAD_H
+# include <pthread.h>
+#endif
+#if HAVE_SYS_SOCKET_H
+# include <sys/socket.h>
+#endif
+#if HAVE_NETDB_H
+# include <netdb.h>
+#endif
+#if HAVE_NETINET_IN_H
+# include <netinet/in.h>
+#endif
+#if HAVE_ARPA_INET_H
+# include <arpa/inet.h>
+#endif
+#if HAVE_POLL_H
+# include <poll.h>
+#endif
+
/* 1500 - 40 - 8 = Ethernet packet - IPv6 header - UDP header */
/* #define BUFF_SIZE 1452 */
# endif
#endif /* !IP_ADD_MEMBERSHIP */
-#define BUFF_SIZE 4096
-
-extern int operating_mode;
+#define BUFF_SIZE 1024
+/*
+ * Private data types
+ */
typedef struct sockent
{
int fd;
- int mode;
struct sockaddr_storage *addr;
socklen_t addrlen;
struct sockent *next;
} sockent_t;
-static sockent_t *socklist_head = NULL;
+/* 1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 3 3
+ * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+ * +-------+-----------------------+-------------------------------+
+ * ! Ver. ! ! Length !
+ * +-------+-----------------------+-------------------------------+
+ */
+struct part_header_s
+{
+ uint16_t type;
+ uint16_t length;
+};
+typedef struct part_header_s part_header_t;
+
+/* 1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 3 3
+ * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+ * +-------------------------------+-------------------------------+
+ * ! Type ! Length !
+ * +-------------------------------+-------------------------------+
+ * : (Length - 4) Bytes :
+ * +---------------------------------------------------------------+
+ */
+struct part_string_s
+{
+ part_header_t *head;
+ char *value;
+};
+typedef struct part_string_s part_string_t;
+
+/* 1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 3 3
+ * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+ * +-------------------------------+-------------------------------+
+ * ! Type ! Length !
+ * +-------------------------------+-------------------------------+
+ * : (Length - 4 == 2 || 4 || 8) Bytes :
+ * +---------------------------------------------------------------+
+ */
+struct part_number_s
+{
+ part_header_t *head;
+ uint64_t *value;
+};
+typedef struct part_number_s part_number_t;
+
+/* 1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 3 3
+ * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+ * +-------------------------------+-------------------------------+
+ * ! Type ! Length !
+ * +-------------------------------+---------------+---------------+
+ * ! Num of values ! Type0 ! Type1 !
+ * +-------------------------------+---------------+---------------+
+ * ! Value0 !
+ * ! !
+ * +---------------------------------------------------------------+
+ * ! Value1 !
+ * ! !
+ * +---------------------------------------------------------------+
+ */
+struct part_values_s
+{
+ part_header_t *head;
+ uint16_t *num_values;
+ uint8_t *values_types;
+ value_t *values;
+};
+typedef struct part_values_s part_values_t;
+
+/*
+ * Private variables
+ */
+static const char *config_keys[] =
+{
+ "Listen",
+ "Server",
+ "TimeToLive",
+ NULL
+};
+static int config_keys_num = 3;
+
+static int network_config_ttl = 0;
+
+static sockent_t *sending_sockets = NULL;
+
+static struct pollfd *listen_sockets = NULL;
+static int listen_sockets_num = 0;
+static pthread_t listen_thread = 0;
+static int listen_loop = 0;
+
+static char send_buffer[BUFF_SIZE];
+static char *send_buffer_ptr;
+static int send_buffer_fill;
+static value_list_t send_buffer_vl = VALUE_LIST_INIT;
+static char send_buffer_type[DATA_MAX_NAME_LEN];
+
+/*
+ * Private functions
+ */
+static int write_part_values (char **ret_buffer, int *ret_buffer_len,
+ const data_set_t *ds, const value_list_t *vl)
+{
+ part_values_t pv;
+ int i;
+
+ i = 6 + (9 * vl->values_len);
+ if (*ret_buffer_len < i)
+ return (-1);
+ *ret_buffer_len -= i;
+
+ pv.head = (part_header_t *) *ret_buffer;
+ pv.num_values = (uint16_t *) (pv.head + 1);
+ pv.values_types = (uint8_t *) (pv.num_values + 1);
+ pv.values = (value_t *) (pv.values_types + vl->values_len);
+ *ret_buffer = (void *) (pv.values + vl->values_len);
+
+ pv.head->type = htons (TYPE_VALUES);
+ pv.head->length = htons (6 + (9 * vl->values_len));
+ *pv.num_values = htons ((uint16_t) vl->values_len);
+
+ for (i = 0; i < vl->values_len; i++)
+ {
+ if (ds->ds[i].type == DS_TYPE_COUNTER)
+ {
+ pv.values_types[i] = DS_TYPE_COUNTER;
+ pv.values[i].counter = htonll (vl->values[i].counter);
+ }
+ else
+ {
+ pv.values_types[i] = DS_TYPE_GAUGE;
+ pv.values[i].gauge = vl->values[i].gauge;
+ }
+ } /* for (values) */
-static int network_set_ttl (const sockent_t *se, const struct addrinfo *ai)
+ return (0);
+} /* int write_part_values */
+
+static int write_part_number (char **ret_buffer, int *ret_buffer_len,
+ int type, uint64_t value)
{
- char *ttl_str;
- int ttl_int;
+ part_number_t pn;
- ttl_str = cf_get_option ("TimeToLive", NULL);
- if (ttl_str == NULL)
+ if (*ret_buffer_len < 12)
return (-1);
- ttl_int = atoi (ttl_str);
- if ((ttl_int < 1) || (ttl_int > 255))
+ pn.head = (part_header_t *) *ret_buffer;
+ pn.value = (uint64_t *) (pn.head + 1);
+
+ pn.head->type = htons (type);
+ pn.head->length = htons (12);
+ *pn.value = htonll (value);
+
+ *ret_buffer = (char *) (pn.value + 1);
+ *ret_buffer_len -= 12;
+
+ return (0);
+} /* int write_part_number */
+
+static int write_part_string (char **ret_buffer, int *ret_buffer_len,
+ int type, const char *str, int str_len)
+{
+ part_string_t ps;
+ int len;
+
+ len = 4 + str_len + 1;
+ if (*ret_buffer_len < len)
+ return (-1);
+ *ret_buffer_len -= len;
+
+ ps.head = (part_header_t *) *ret_buffer;
+ ps.value = (char *) (ps.head + 1);
+
+ ps.head->type = htons ((uint16_t) type);
+ ps.head->length = htons ((uint16_t) str_len + 5);
+ if (str_len > 0)
+ memcpy (ps.value, str, str_len);
+ ps.value[str_len] = '\0';
+ *ret_buffer = (void *) (ps.value + (str_len + 1));
+
+ return (0);
+} /* int write_part_string */
+
+static int parse_part_values (void **ret_buffer, int *ret_buffer_len,
+ value_t **ret_values, int *ret_num_values)
+{
+ char *buffer = *ret_buffer;
+ int buffer_len = *ret_buffer_len;
+ part_values_t pv;
+ int i;
+
+ uint16_t h_length;
+ uint16_t h_type;
+ uint16_t h_num;
+
+ if (buffer_len < (15))
{
- syslog (LOG_WARNING, "A TTL value of %i is invalid.", ttl_int);
+ DBG ("packet is too short: buffer_len = %i", buffer_len);
return (-1);
}
- DBG ("ttl = %i", ttl_int);
+ pv.head = (part_header_t *) buffer;
+ h_length = ntohs (pv.head->length);
+ h_type = ntohs (pv.head->type);
+
+ assert (h_type == TYPE_VALUES);
+
+ pv.num_values = (uint16_t *) (pv.head + 1);
+ h_num = ntohs (*pv.num_values);
+
+ if (h_num != ((h_length - 6) / 9))
+ {
+ DBG ("`length' and `num of values' don't match");
+ return (-1);
+ }
+
+ pv.values_types = (uint8_t *) (pv.num_values + 1);
+ pv.values = (value_t *) (pv.values_types + h_num);
+
+ for (i = 0; i < h_num; i++)
+ if (pv.values_types[i] == DS_TYPE_COUNTER)
+ pv.values[i].counter = ntohll (pv.values[i].counter);
+
+ *ret_buffer = (void *) (pv.values + h_num);
+ *ret_buffer_len = buffer_len - h_length;
+ *ret_num_values = h_num;
+ *ret_values = pv.values;
+
+ return (0);
+} /* int parse_part_values */
+
+static int parse_part_number (void **ret_buffer, int *ret_buffer_len,
+ uint64_t *value)
+{
+ part_number_t pn;
+ uint16_t len;
+
+ pn.head = (part_header_t *) *ret_buffer;
+ pn.value = (uint64_t *) (pn.head + 1);
+
+ len = ntohs (pn.head->length);
+ if (len != 12)
+ return (-1);
+ if (len > *ret_buffer_len)
+ return (-1);
+ *value = ntohll (*pn.value);
+
+ *ret_buffer = (void *) (pn.value + 1);
+ *ret_buffer_len -= len;
+
+ return (0);
+} /* int parse_part_number */
+
+static int parse_part_string (void **ret_buffer, int *ret_buffer_len,
+ char *output, int output_len)
+{
+ char *buffer = *ret_buffer;
+ int buffer_len = *ret_buffer_len;
+ part_string_t ps;
+
+ uint16_t h_length;
+ uint16_t h_type;
+
+ DBG ("ret_buffer = %p; ret_buffer_len = %i; output = %p; output_len = %i;",
+ *ret_buffer, *ret_buffer_len,
+ (void *) output, output_len);
+
+ ps.head = (part_header_t *) buffer;
+
+ h_length = ntohs (ps.head->length);
+ h_type = ntohs (ps.head->type);
+
+ DBG ("length = %hu; type = %hu;", h_length, h_type);
+
+ if (buffer_len < h_length)
+ {
+ DBG ("packet is too short");
+ return (-1);
+ }
+ assert ((h_type == TYPE_HOST)
+ || (h_type == TYPE_PLUGIN)
+ || (h_type == TYPE_PLUGIN_INSTANCE)
+ || (h_type == TYPE_TYPE)
+ || (h_type == TYPE_TYPE_INSTANCE));
+
+ ps.value = buffer + 4;
+ if (ps.value[h_length - 5] != '\0')
+ {
+ DBG ("String does not end with a nullbyte");
+ return (-1);
+ }
+
+ if (output_len < (h_length - 4))
+ {
+ DBG ("output buffer is too small");
+ return (-1);
+ }
+ strcpy (output, ps.value);
+
+ DBG ("output = %s", output);
+
+ *ret_buffer = (void *) (buffer + h_length);
+ *ret_buffer_len = buffer_len - h_length;
+
+ return (0);
+} /* int parse_part_string */
+
+static int parse_packet (void *buffer, int buffer_len)
+{
+ part_header_t *header;
+ int status;
+
+ value_list_t vl = VALUE_LIST_INIT;
+ char type[DATA_MAX_NAME_LEN];
+
+ DBG ("buffer = %p; buffer_len = %i;", buffer, buffer_len);
+
+ memset (&vl, '\0', sizeof (vl));
+ memset (&type, '\0', sizeof (type));
+ status = 0;
+
+ while ((status == 0) && (buffer_len > sizeof (part_header_t)))
+ {
+ header = (part_header_t *) buffer;
+
+ if (ntohs (header->length) > buffer_len)
+ break;
+
+ if (header->type == htons (TYPE_VALUES))
+ {
+ status = parse_part_values (&buffer, &buffer_len,
+ &vl.values, &vl.values_len);
+
+ if (status != 0)
+ {
+ DBG ("parse_part_values failed.");
+ break;
+ }
+
+ if ((vl.time > 0)
+ && (strlen (vl.host) > 0)
+ && (strlen (vl.plugin) > 0)
+ && (strlen (type) > 0))
+ {
+ DBG ("dispatching values");
+ plugin_dispatch_values (type, &vl);
+ }
+ else
+ {
+ DBG ("NOT dispatching values");
+ }
+ }
+ else if (header->type == ntohs (TYPE_TIME))
+ {
+ uint64_t tmp = 0;
+ status = parse_part_number (&buffer, &buffer_len, &tmp);
+ if (status == 0)
+ vl.time = (time_t) tmp;
+ }
+ else if (header->type == ntohs (TYPE_HOST))
+ {
+ status = parse_part_string (&buffer, &buffer_len,
+ vl.host, sizeof (vl.host));
+ }
+ else if (header->type == ntohs (TYPE_PLUGIN))
+ {
+ status = parse_part_string (&buffer, &buffer_len,
+ vl.plugin, sizeof (vl.plugin));
+ }
+ else if (header->type == ntohs (TYPE_PLUGIN_INSTANCE))
+ {
+ status = parse_part_string (&buffer, &buffer_len,
+ vl.plugin_instance, sizeof (vl.plugin_instance));
+ }
+ else if (header->type == ntohs (TYPE_TYPE))
+ {
+ status = parse_part_string (&buffer, &buffer_len,
+ type, sizeof (type));
+ }
+ else if (header->type == ntohs (TYPE_TYPE_INSTANCE))
+ {
+ status = parse_part_string (&buffer, &buffer_len,
+ vl.type_instance, sizeof (vl.type_instance));
+ }
+ else
+ {
+ DBG ("Unknown part type: 0x%0hx", header->type);
+ buffer = ((char *) buffer) + header->length;
+ }
+ } /* while (buffer_len > sizeof (part_header_t)) */
+
+ return (0);
+} /* int parse_packet */
+
+static void free_sockent (sockent_t *se)
+{
+ sockent_t *next;
+ while (se != NULL)
+ {
+ next = se->next;
+ free (se->addr);
+ free (se);
+ se = next;
+ }
+} /* void free_sockent */
+
+/*
+ * int network_set_ttl
+ *
+ * Set the `IP_MULTICAST_TTL', `IP_TTL', `IPV6_MULTICAST_HOPS' or
+ * `IPV6_UNICAST_HOPS', depending on which option is applicable.
+ *
+ * The `struct addrinfo' is used to destinguish between unicast and multicast
+ * sockets.
+ */
+static int network_set_ttl (const sockent_t *se, const struct addrinfo *ai)
+{
+ if ((network_config_ttl < 1) || (network_config_ttl > 255))
+ return (-1);
+
+ DBG ("ttl = %i", network_config_ttl);
if (ai->ai_family == AF_INET)
{
optname = IP_TTL;
if (setsockopt (se->fd, IPPROTO_IP, optname,
- &ttl_int, sizeof (ttl_int)) == -1)
+ &network_config_ttl,
+ sizeof (network_config_ttl)) == -1)
{
syslog (LOG_ERR, "setsockopt: %s", strerror (errno));
return (-1);
optname = IPV6_UNICAST_HOPS;
if (setsockopt (se->fd, IPPROTO_IPV6, optname,
- &ttl_int, sizeof (ttl_int)) == -1)
+ &network_config_ttl,
+ sizeof (network_config_ttl)) == -1)
{
syslog (LOG_ERR, "setsockopt: %s", strerror (errno));
return (-1);
}
return (0);
-}
+} /* int network_set_ttl */
static int network_bind_socket (const sockent_t *se, const struct addrinfo *ai)
{
}
return (0);
-}
+} /* int network_bind_socket */
-int network_create_socket (const char *node, const char *service)
+static sockent_t *network_create_socket (const char *node,
+ const char *service,
+ int listen)
{
- sockent_t *socklist_tail;
-
struct addrinfo ai_hints;
struct addrinfo *ai_list, *ai_ptr;
int ai_return;
- int num_added = 0;
+ sockent_t *se_head = NULL;
+ sockent_t *se_tail = NULL;
DBG ("node = %s, service = %s", node, service);
- if (operating_mode == MODE_LOCAL || operating_mode == MODE_LOG)
- {
- syslog (LOG_WARNING, "network_create_socket: There is no point opening a socket when you are in mode `%s'.",
- operating_mode == MODE_LOCAL ? "Local" : "Log");
- return (-1);
- }
-
- socklist_tail = socklist_head;
- while ((socklist_tail != NULL) && (socklist_tail->next != NULL))
- socklist_tail = socklist_tail->next;
-
memset (&ai_hints, '\0', sizeof (ai_hints));
ai_hints.ai_flags = 0;
#ifdef AI_PASSIVE
#ifdef AI_ADDRCONFIG
ai_hints.ai_flags |= AI_ADDRCONFIG;
#endif
- ai_hints.ai_family = PF_UNSPEC;
+ ai_hints.ai_family = AF_UNSPEC;
ai_hints.ai_socktype = SOCK_DGRAM;
ai_hints.ai_protocol = IPPROTO_UDP;
- if ((ai_return = getaddrinfo (node, service, &ai_hints, &ai_list)) != 0)
+ ai_return = getaddrinfo (node, service, &ai_hints, &ai_list);
+ if (ai_return != 0)
{
syslog (LOG_ERR, "getaddrinfo (%s, %s): %s",
- node == NULL ? "(null)" : node,
- service == NULL ? "(null)" : service,
- ai_return == EAI_SYSTEM ? strerror (errno) : gai_strerror (ai_return));
- return (-1);
+ (node == NULL) ? "(null)" : node,
+ (service == NULL) ? "(null)" : service,
+ (ai_return == EAI_SYSTEM)
+ ? strerror (errno)
+ : gai_strerror (ai_return));
+ return (NULL);
}
for (ai_ptr = ai_list; ai_ptr != NULL; ai_ptr = ai_ptr->ai_next)
memcpy (se->addr, ai_ptr->ai_addr, ai_ptr->ai_addrlen);
se->addrlen = ai_ptr->ai_addrlen;
- se->mode = operating_mode;
- se->fd = socket (ai_ptr->ai_family, ai_ptr->ai_socktype, ai_ptr->ai_protocol);
+ se->fd = socket (ai_ptr->ai_family,
+ ai_ptr->ai_socktype,
+ ai_ptr->ai_protocol);
se->next = NULL;
if (se->fd == -1)
continue;
}
- if (operating_mode == MODE_SERVER)
+ if (listen != 0)
{
if (network_bind_socket (se, ai_ptr) != 0)
{
continue;
}
}
- else if (operating_mode == MODE_CLIENT)
+ else /* listen == 0 */
{
network_set_ttl (se, ai_ptr);
}
- if (socklist_tail == NULL)
+ if (se_tail == NULL)
{
- socklist_head = se;
- socklist_tail = se;
+ se_head = se;
+ se_tail = se;
}
else
{
- socklist_tail->next = se;
- socklist_tail = se;
+ se_tail->next = se;
+ se_tail = se;
}
- num_added++;
-
/* We don't open more than one write-socket per node/service pair.. */
- if (operating_mode == MODE_CLIENT)
+ if (listen == 0)
break;
}
freeaddrinfo (ai_list);
- return (num_added);
-}
+ return (se_head);
+} /* sockent_t *network_create_socket */
-static int network_connect_default (void)
+static sockent_t *network_create_default_socket (int listen)
{
- int ret;
+ sockent_t *se_ptr = NULL;
+ sockent_t *se_head = NULL;
+ sockent_t *se_tail = NULL;
- if (socklist_head != NULL)
- return (0);
+ se_ptr = network_create_socket (NET_DEFAULT_V6_ADDR,
+ NET_DEFAULT_PORT, listen);
- DBG ("socklist_head is NULL");
+ /* Don't send to the same machine in IPv6 and IPv4 if both are available. */
+ if ((listen == 0) && (se_ptr != NULL))
+ return (se_ptr);
+
+ if (se_ptr != NULL)
+ {
+ se_head = se_ptr;
+ se_tail = se_ptr;
+ while (se_tail->next != NULL)
+ se_tail = se_tail->next;
+ }
- ret = 0;
+ se_ptr = network_create_socket (NET_DEFAULT_V4_ADDR, NET_DEFAULT_PORT, listen);
- if (network_create_socket (NET_DEFAULT_V6_ADDR, NET_DEFAULT_PORT) > 0)
- ret++;
+ if (se_tail == NULL)
+ return (se_ptr);
- /* Don't use IPv4 and IPv6 in parallel by default.. */
- if ((operating_mode == MODE_CLIENT) && (ret != 0))
- return (ret);
+ se_tail->next = se_ptr;
+ return (se_head);
+} /* sockent_t *network_create_default_socket */
- if (network_create_socket (NET_DEFAULT_V4_ADDR, NET_DEFAULT_PORT) > 0)
- ret++;
+static int network_add_listen_socket (const char *node, const char *service)
+{
+ sockent_t *se;
+ sockent_t *se_ptr;
+ int se_num = 0;
- if (ret == 0)
- ret = -1;
+ if (service == NULL)
+ service = NET_DEFAULT_PORT;
- return (ret);
-}
+ if (node == NULL)
+ se = network_create_default_socket (1 /* listen == true */);
+ else
+ se = network_create_socket (node, service, 1 /* listen == true */);
-static int network_get_listen_socket (void)
-{
- int fd;
- int max_fd;
- int status;
+ if (se == NULL)
+ return (-1);
- fd_set readfds;
- sockent_t *se;
+ for (se_ptr = se; se_ptr != NULL; se_ptr = se_ptr->next)
+ se_num++;
- if (socklist_head == NULL)
- network_connect_default ();
+ listen_sockets = (struct pollfd *) realloc (listen_sockets,
+ (listen_sockets_num + se_num)
+ * sizeof (struct pollfd));
- FD_ZERO (&readfds);
- max_fd = -1;
- for (se = socklist_head; se != NULL; se = se->next)
+ for (se_ptr = se; se_ptr != NULL; se_ptr = se_ptr->next)
{
- if (se->mode != operating_mode)
- continue;
+ listen_sockets[listen_sockets_num].fd = se_ptr->fd;
+ listen_sockets[listen_sockets_num].events = POLLIN | POLLPRI;
+ listen_sockets[listen_sockets_num].revents = 0;
+ listen_sockets_num++;
+ } /* for (se) */
- FD_SET (se->fd, &readfds);
- if (se->fd >= max_fd)
- max_fd = se->fd + 1;
- }
+ free_sockent (se);
+ return (0);
+} /* int network_add_listen_socket */
- if (max_fd == -1)
- {
- syslog (LOG_WARNING, "No listen sockets found!");
+static int network_add_sending_socket (const char *node, const char *service)
+{
+ sockent_t *se;
+ sockent_t *se_ptr;
+
+ if (service == NULL)
+ service = NET_DEFAULT_PORT;
+
+ if (node == NULL)
+ se = network_create_default_socket (0 /* listen == false */);
+ else
+ se = network_create_socket (node, service, 0 /* listen == false */);
+
+ if (se == NULL)
return (-1);
+
+ if (sending_sockets == NULL)
+ {
+ sending_sockets = se;
+ return (0);
}
- status = select (max_fd, &readfds, NULL, NULL, NULL);
+ for (se_ptr = sending_sockets; se_ptr->next != NULL; se_ptr = se_ptr->next)
+ /* seek end */;
+
+ se_ptr->next = se;
+ return (0);
+} /* int network_get_listen_socket */
- if (status == -1)
+int network_receive (void)
+{
+ char buffer[BUFF_SIZE];
+ int buffer_len;
+
+ int i;
+ int status;
+
+ if (listen_sockets_num == 0)
+ network_add_listen_socket (NULL, NULL);
+
+ if (listen_sockets_num == 0)
{
- if (errno != EINTR)
- syslog (LOG_ERR, "select: %s", strerror (errno));
+ syslog (LOG_ERR, "network: Failed to open a listening socket.");
return (-1);
}
- fd = -1;
- for (se = socklist_head; se != NULL; se = se->next)
+ while (listen_loop == 0)
{
- if (se->mode != operating_mode)
- continue;
+ status = poll (listen_sockets, listen_sockets_num, -1);
- if (FD_ISSET (se->fd, &readfds))
+ if (status <= 0)
{
- fd = se->fd;
- break;
+ if (errno == EINTR)
+ continue;
+ syslog (LOG_ERR, "poll failed: %s",
+ strerror (errno));
+ return (-1);
}
- }
- if (fd == -1)
- syslog (LOG_WARNING, "No socket ready..?");
+ for (i = 0; (i < listen_sockets_num) && (status > 0); i++)
+ {
+ if ((listen_sockets[i].revents & (POLLIN | POLLPRI)) == 0)
+ continue;
+ status--;
+
+ buffer_len = recv (listen_sockets[i].fd,
+ buffer, sizeof (buffer),
+ 0 /* no flags */);
+ if (buffer_len < 0)
+ {
+ syslog (LOG_ERR, "recv failed: %s", strerror (errno));
+ return (-1);
+ }
+
+ parse_packet (buffer, buffer_len);
+ } /* for (listen_sockets) */
+ } /* while (listen_loop == 0) */
- DBG ("fd = %i", fd);
- return (fd);
+ return (0);
}
-int network_receive (char **host, char **type, char **inst, char **value)
+static void *receive_thread (void *arg)
{
- int fd;
- char buffer[BUFF_SIZE];
+ return (network_receive () ? (void *) 1 : (void *) 0);
+} /* void *receive_thread */
- struct sockaddr_storage addr;
- socklen_t addrlen;
+static void network_send_buffer (const char *buffer, int buffer_len)
+{
+ sockent_t *se;
int status;
- char *fields[4];
+ DBG ("buffer_len = %i", buffer_len);
- assert (operating_mode == MODE_SERVER);
-
- *host = NULL;
- *type = NULL;
- *inst = NULL;
- *value = NULL;
+ for (se = sending_sockets; se != NULL; se = se->next)
+ {
+ while (42)
+ {
+ status = sendto (se->fd, buffer, buffer_len, 0 /* no flags */,
+ (struct sockaddr *) se->addr, se->addrlen);
+ if (status < 0)
+ {
+ if (errno == EINTR)
+ continue;
+ syslog (LOG_ERR, "network plugin: sendto failed: %s",
+ strerror (errno));
+ break;
+ }
- if ((fd = network_get_listen_socket ()) < 0)
- return (-1);
+ break;
+ } /* while (42) */
+ } /* for (sending_sockets) */
+} /* void network_send_buffer */
- addrlen = sizeof (addr);
- if (recvfrom (fd, buffer, BUFF_SIZE, 0, (struct sockaddr *) &addr, &addrlen) == -1)
+static int add_to_buffer (char *buffer, int buffer_size,
+ value_list_t *vl_def, char *type_def,
+ const data_set_t *ds, const value_list_t *vl)
+{
+ if (strcmp (vl_def->host, vl->host) != 0)
{
- syslog (LOG_ERR, "recvfrom: %s", strerror (errno));
- return (-1);
+ if (write_part_string (&buffer, &buffer_size, TYPE_HOST,
+ vl->host, strlen (vl->host)) != 0)
+ return (-1);
+ strcpy (vl_def->host, vl->host);
+ DBG ("host = %s", vl->host);
}
- if ((*host = (char *) malloc (BUFF_SIZE)) == NULL)
+ if (vl_def->time != vl->time)
{
- syslog (LOG_EMERG, "malloc: %s", strerror (errno));
- return (-1);
+ if (write_part_number (&buffer, &buffer_size, TYPE_TIME,
+ (uint64_t) vl->time))
+ return (-1);
+ vl_def->time = vl->time;
+ DBG ("time = %u", (unsigned int) vl->time);
}
- status = getnameinfo ((struct sockaddr *) &addr, addrlen,
- *host, BUFF_SIZE, NULL, 0, 0);
- if (status != 0)
+ if (strcmp (vl_def->plugin, vl->plugin) != 0)
{
- free (*host); *host = NULL;
- syslog (LOG_ERR, "getnameinfo: %s",
- status == EAI_SYSTEM ? strerror (errno) : gai_strerror (status));
- return (-1);
+ if (write_part_string (&buffer, &buffer_size, TYPE_PLUGIN,
+ vl->plugin, strlen (vl->plugin)) != 0)
+ return (-1);
+ strcpy (vl_def->plugin, vl->plugin);
+ DBG ("plugin = %s", vl->plugin);
}
- if (strsplit (buffer, fields, 4) != 3)
+ if (strcmp (vl_def->plugin_instance, vl->plugin_instance) != 0)
{
- syslog (LOG_WARNING, "Invalid message from `%s'", *host);
- free (*host); *host = NULL;
- return (1);
+ if (write_part_string (&buffer, &buffer_size, TYPE_PLUGIN_INSTANCE,
+ vl->plugin_instance,
+ strlen (vl->plugin_instance)) != 0)
+ return (-1);
+ strcpy (vl_def->plugin_instance, vl->plugin_instance);
+ DBG ("plugin_instance = %s", vl->plugin_instance);
}
- if ((*type = strdup (fields[0])) == NULL)
+ if (strcmp (type_def, ds->type) != 0)
{
- syslog (LOG_EMERG, "strdup: %s", strerror (errno));
- free (*host); *host = NULL;
- return (-1);
+ if (write_part_string (&buffer, &buffer_size, TYPE_TYPE,
+ ds->type, strlen (ds->type)) != 0)
+ return (-1);
+ strcpy (type_def, ds->type);
+ DBG ("type = %s", ds->type);
}
- if ((*inst = strdup (fields[1])) == NULL)
+ if (strcmp (vl_def->type_instance, vl->type_instance) != 0)
{
- syslog (LOG_EMERG, "strdup: %s", strerror (errno));
- free (*host); *host = NULL;
- free (*type); *type = NULL;
+ if (write_part_string (&buffer, &buffer_size, TYPE_PLUGIN_INSTANCE,
+ vl->type_instance,
+ strlen (vl->type_instance)) != 0)
+ return (-1);
+ strcpy (vl_def->type_instance, vl->type_instance);
+ DBG ("type_instance = %s", vl->type_instance);
+ }
+
+ if (write_part_values (&buffer, &buffer_size, ds, vl) != 0)
return (-1);
+
+ return (buffer_size);
+} /* int add_to_buffer */
+
+static void flush_buffer (void)
+{
+ network_send_buffer (send_buffer, send_buffer_fill);
+ send_buffer_ptr = send_buffer;
+ send_buffer_fill = 0;
+ memset (&send_buffer_vl, '\0', sizeof (send_buffer_vl));
+ memset (send_buffer_type, '\0', sizeof (send_buffer_type));
+}
+
+static int network_write (const data_set_t *ds, const value_list_t *vl)
+{
+ int status;
+ /* TODO: lock buffer */
+ status = add_to_buffer (send_buffer_ptr,
+ sizeof (send_buffer) - send_buffer_fill,
+ &send_buffer_vl, send_buffer_type,
+ ds, vl);
+ if (status >= 0)
+ {
+ send_buffer_fill += status;
+ send_buffer_ptr += status;
+ }
+ else
+ {
+ flush_buffer ();
+
+ status = add_to_buffer (send_buffer_ptr,
+ sizeof (send_buffer) - send_buffer_fill,
+ &send_buffer_vl, send_buffer_type,
+ ds, vl);
+
+ if (status >= 0)
+ {
+ send_buffer_fill += status;
+ send_buffer_ptr += status;
+ }
}
- if ((*value = strdup (fields[2])) == NULL)
+ if (status < 0)
{
- syslog (LOG_EMERG, "strdup: %s", strerror (errno));
- free (*host); *host = NULL;
- free (*type); *type = NULL;
- free (*inst); *inst = NULL;
- return (-1);
+ syslog (LOG_ERR, "network plugin: Unable to append to the "
+ "buffer for some weird reason");
+ }
+ else if ((sizeof (send_buffer) - send_buffer_fill) < 15)
+ {
+ flush_buffer ();
}
+ /* TODO: unlock buffer */
- DBG ("host = %s, type = %s, inst = %s, value = %s",
- *host, *type, *inst, *value);
+ return ((status < 0) ? -1 : 0);
+} /* int network_write */
+static int network_config (const char *key, const char *val)
+{
+ char *node;
+ char *service;
+
+ char *fields[3];
+ int fields_num;
+
+ if ((strcasecmp ("Listen", key) == 0)
+ || (strcasecmp ("Server", key) == 0))
+ {
+ char *val_cpy = strdup (val);
+ if (val_cpy == NULL)
+ return (1);
+
+ service = NET_DEFAULT_PORT;
+ fields_num = strsplit (val_cpy, fields, 3);
+ if ((fields_num != 1)
+ && (fields_num != 2))
+ return (1);
+ else if (fields_num == 2)
+ service = fields[1];
+ node = fields[0];
+
+ if (strcasecmp ("Listen", key) == 0)
+ network_add_listen_socket (node, service);
+ else
+ network_add_sending_socket (node, service);
+ }
+ else if (strcasecmp ("TimeToLive", key) == 0)
+ {
+ int tmp = atoi (val);
+ if ((tmp > 0) && (tmp < 256))
+ network_config_ttl = tmp;
+ else
+ return (1);
+ }
+ else
+ {
+ return (-1);
+ }
return (0);
}
-int network_send (char *type, char *inst, char *value)
+static int network_shutdown (void)
{
- char buf[BUFF_SIZE];
- int buflen;
+ DBG ("Shutting down.");
- sockent_t *se;
+ listen_loop++;
- int ret;
- int status;
+ pthread_kill (listen_thread, SIGTERM);
+ pthread_join (listen_thread, NULL /* no return value */);
- DBG ("type = %s, inst = %s, value = %s", type, inst, value);
+ listen_thread = 0;
- assert (operating_mode == MODE_CLIENT);
+ return (0);
+}
- buflen = snprintf (buf, BUFF_SIZE, "%s %s %s", type, inst, value);
- if ((buflen >= BUFF_SIZE) || (buflen < 1))
- {
- syslog (LOG_WARNING, "network_send: snprintf failed..");
- return (-1);
- }
- buf[buflen] = '\0';
- buflen++;
+static int network_init (void)
+{
+ plugin_register_shutdown ("network", network_shutdown);
+
+ send_buffer_ptr = send_buffer;
+ send_buffer_fill = 0;
+ memset (&send_buffer_vl, '\0', sizeof (send_buffer_vl));
+ memset (send_buffer_type, '\0', sizeof (send_buffer_type));
- if (socklist_head == NULL)
- network_connect_default ();
+ /* setup socket(s) and so on */
+ if (sending_sockets != NULL)
+ plugin_register_write ("network", network_write);
- ret = 0;
- for (se = socklist_head; se != NULL; se = se->next)
+ if ((listen_sockets_num != 0) && (listen_thread == 0))
{
- if (se->mode != operating_mode)
- continue;
+ int status;
- while (1)
- {
- status = sendto (se->fd, buf, buflen, 0,
- (struct sockaddr *) se->addr, se->addrlen);
+ status = pthread_create (&listen_thread, NULL /* no attributes */,
+ receive_thread, NULL /* no argument */);
- if (status == -1)
- {
- if (errno == EINTR)
- {
- DBG ("sendto was interrupted");
- continue;
- }
- else
- {
- syslog (LOG_ERR, "sendto: %s", strerror (errno));
- ret = -1;
- break;
- }
- }
- else if (ret >= 0)
- ret++;
- break;
- }
+ if (status != 0)
+ syslog (LOG_ERR, "network: pthread_create failed: %s",
+ strerror (errno));
}
+ return (0);
+} /* int network_init */
- if (ret == 0)
- syslog (LOG_WARNING, "Message wasn't sent to anybody..");
-
- return (ret);
+void module_register (void)
+{
+ plugin_register_config ("network", network_config,
+ config_keys, config_keys_num);
+ plugin_register_init ("network", network_init);
}
*
* 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; either version 2 of the License, or (at your
- * option) any later version.
+ * 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
#define NET_DEFAULT_V6_ADDR "ff18::efc0:4a42"
#define NET_DEFAULT_PORT "25826"
-int network_create_socket (const char *node, const char *service);
-int network_receive (char **host, char **type, char **instance, char **value);
-int network_send (char *type, char *instance, char *value);
+#define TYPE_HOST 0x0000
+#define TYPE_TIME 0x0001
+#define TYPE_PLUGIN 0x0002
+#define TYPE_PLUGIN_INSTANCE 0x0003
+#define TYPE_TYPE 0x0004
+#define TYPE_TYPE_INSTANCE 0x0005
+#define TYPE_VALUES 0x0006
#endif /* NETWORK_H */
*
* 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; either version 2 of the License, or (at your
- * option) any later version.
+ * 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
#include "collectd.h"
#include "common.h"
#include "plugin.h"
+#include "utils_debug.h"
#define MODULE_NAME "nfs"
# define NFS_HAVE_READ 0
#endif
-static char *nfs2_procedures_file = "nfs2_procedures-%s.rrd";
-static char *nfs3_procedures_file = "nfs3_procedures-%s.rrd";
-
/*
see /proc/net/rpc/nfs
see http://www.missioncriticallinux.com/orph/NFS-Statistics
21 commit
*/
-static char *nfs2_procedures_ds_def[] =
+static data_source_t procedure_dsrc[1] =
+{
+ {"value", DS_TYPE_COUNTER, 0, 4294967295.0}
+};
+
+static data_set_t procedure_ds =
{
- "DS:null:COUNTER:"COLLECTD_HEARTBEAT":0:U",
- "DS:getattr:COUNTER:"COLLECTD_HEARTBEAT":0:U",
- "DS:setattr:COUNTER:"COLLECTD_HEARTBEAT":0:U",
- "DS:root:COUNTER:"COLLECTD_HEARTBEAT":0:U",
- "DS:lookup:COUNTER:"COLLECTD_HEARTBEAT":0:U",
- "DS:readlink:COUNTER:"COLLECTD_HEARTBEAT":0:U",
- "DS:read:COUNTER:"COLLECTD_HEARTBEAT":0:U",
- "DS:wrcache:COUNTER:"COLLECTD_HEARTBEAT":0:U",
- "DS:write:COUNTER:"COLLECTD_HEARTBEAT":0:U",
- "DS:create:COUNTER:"COLLECTD_HEARTBEAT":0:U",
- "DS:remove:COUNTER:"COLLECTD_HEARTBEAT":0:U",
- "DS:rename:COUNTER:"COLLECTD_HEARTBEAT":0:U",
- "DS:link:COUNTER:"COLLECTD_HEARTBEAT":0:U",
- "DS:symlink:COUNTER:"COLLECTD_HEARTBEAT":0:U",
- "DS:mkdir:COUNTER:"COLLECTD_HEARTBEAT":0:U",
- "DS:rmdir:COUNTER:"COLLECTD_HEARTBEAT":0:U",
- "DS:readdir:COUNTER:"COLLECTD_HEARTBEAT":0:U",
- "DS:fsstat:COUNTER:"COLLECTD_HEARTBEAT":0:U",
+ "nfs_procedure", 1, procedure_dsrc
+};
+
+#if NFS_HAVE_READ
+static const char *nfs2_procedures_names[] =
+{
+ "null",
+ "getattr",
+ "setattr",
+ "root",
+ "lookup",
+ "readlink",
+ "read",
+ "wrcache",
+ "write",
+ "create",
+ "remove",
+ "rename",
+ "link",
+ "symlink",
+ "mkdir",
+ "rmdir",
+ "readdir",
+ "fsstat",
NULL
};
-static int nfs2_procedures_ds_num = 18;
+static int nfs2_procedures_names_num = 18;
-static char *nfs3_procedures_ds_def[] =
+static const char *nfs3_procedures_names[] =
{
- "DS:null:COUNTER:"COLLECTD_HEARTBEAT":0:U",
- "DS:getattr:COUNTER:"COLLECTD_HEARTBEAT":0:U",
- "DS:setattr:COUNTER:"COLLECTD_HEARTBEAT":0:U",
- "DS:lookup:COUNTER:"COLLECTD_HEARTBEAT":0:U",
- "DS:access:COUNTER:"COLLECTD_HEARTBEAT":0:U",
- "DS:readlink:COUNTER:"COLLECTD_HEARTBEAT":0:U",
- "DS:read:COUNTER:"COLLECTD_HEARTBEAT":0:U",
- "DS:write:COUNTER:"COLLECTD_HEARTBEAT":0:U",
- "DS:create:COUNTER:"COLLECTD_HEARTBEAT":0:U",
- "DS:mkdir:COUNTER:"COLLECTD_HEARTBEAT":0:U",
- "DS:symlink:COUNTER:"COLLECTD_HEARTBEAT":0:U",
- "DS:mknod:COUNTER:"COLLECTD_HEARTBEAT":0:U",
- "DS:remove:COUNTER:"COLLECTD_HEARTBEAT":0:U",
- "DS:rmdir:COUNTER:"COLLECTD_HEARTBEAT":0:U",
- "DS:rename:COUNTER:"COLLECTD_HEARTBEAT":0:U",
- "DS:link:COUNTER:"COLLECTD_HEARTBEAT":0:U",
- "DS:readdir:COUNTER:"COLLECTD_HEARTBEAT":0:U",
- "DS:readdirplus:COUNTER:"COLLECTD_HEARTBEAT":0:U",
- "DS:fsstat:COUNTER:"COLLECTD_HEARTBEAT":0:U",
- "DS:fsinfo:COUNTER:"COLLECTD_HEARTBEAT":0:U",
- "DS:pathconf:COUNTER:"COLLECTD_HEARTBEAT":0:U",
- "DS:commit:COUNTER:"COLLECTD_HEARTBEAT":0:U",
+ "null",
+ "getattr",
+ "setattr",
+ "lookup",
+ "access",
+ "readlink",
+ "read",
+ "write",
+ "create",
+ "mkdir",
+ "symlink",
+ "mknod",
+ "remove",
+ "rmdir",
+ "rename",
+ "link",
+ "readdir",
+ "readdirplus",
+ "fsstat",
+ "fsinfo",
+ "pathconf",
+ "commit",
NULL
};
-static int nfs3_procedures_ds_num = 22;
+static int nfs3_procedures_names_num = 22;
#if HAVE_LIBKSTAT && 0
extern kstat_ctl_t *kc;
/* Possibly TODO: NFSv4 statistics */
-static void nfs_init (void)
+#if 0
+static int nfs_init (void)
{
#if HAVE_LIBKSTAT && 0
kstat_t *ksp_chain;
}
#endif
- return;
-}
+ return (0);
+} /* int nfs_init */
+#endif
#define BUFSIZE 1024
-static void nfs2_procedures_write (char *host, char *inst, char *val)
-{
- char filename[BUFSIZE];
-
- if (snprintf (filename, BUFSIZE, nfs2_procedures_file, inst) > BUFSIZE)
- return;
-
- rrd_update_file (host, filename, val, nfs2_procedures_ds_def,
- nfs2_procedures_ds_num);
-}
-
-static void nfs3_procedures_write (char *host, char *inst, char *val)
-{
- char filename[BUFSIZE];
-
- if (snprintf (filename, BUFSIZE, nfs3_procedures_file, inst) > BUFSIZE)
- return;
-
- rrd_update_file (host, filename, val, nfs3_procedures_ds_def,
- nfs3_procedures_ds_num);
-}
-
-#if NFS_HAVE_READ
-static void nfs2_procedures_submit (unsigned long long *val, char *inst)
-{
- char buf[BUFSIZE];
- int retval = 0;
-
- retval = snprintf (buf, BUFSIZE, "%u:%llu:%llu:%llu:%llu:%llu:%llu:"
- "%llu:%llu:%llu:%llu:%llu:%llu:%llu:%llu:%llu:"
- "%llu:%llu:%llu", /* 18x %llu */
- (unsigned int) curtime,
- val[0], val[1], val[2], val[3], val[4], val[5], val[6],
- val[7], val[8], val[9], val[10], val[11], val[12],
- val[13], val[14], val[15], val[16], val[17]);
-
-
- if (retval >= BUFSIZE)
- return;
- else if (retval < 0)
- {
- syslog (LOG_ERR, "nfs: snprintf's format failed: %s", strerror (errno));
- return;
- }
-
- plugin_submit ("nfs2_procedures", inst, buf);
-}
-
-static void nfs3_procedures_submit (unsigned long long *val, char *inst)
+static void nfs_procedures_submit (const char *plugin_instance,
+ unsigned long long *val, const char **names, int len)
{
- char buf[BUFSIZE];
- int retval = 0;
-
- retval = snprintf(buf, BUFSIZE, "%u:%llu:%llu:%llu:%llu:%llu:%llu:"
- "%llu:%llu:%llu:%llu:%llu:%llu:%llu:%llu:%llu:"
- "%llu:%llu:%llu:%llu:%llu:%llu:%llu", /* 22x %llu */
- (unsigned int) curtime,
- val[0], val[1], val[2], val[3], val[4], val[5], val[6],
- val[7], val[8], val[9], val[10], val[11], val[12],
- val[13], val[14], val[15], val[16], val[17], val[18],
- val[19], val[20], val[21]);
-
- if (retval >= BUFSIZE)
- return;
- else if (retval < 0)
+ value_t values[1];
+ value_list_t vl = VALUE_LIST_INIT;
+ int i;
+
+ vl.values = values;
+ vl.values_len = 1;
+ vl.time = time (NULL);
+ strcpy (vl.host, hostname);
+ strcpy (vl.plugin, "nfs");
+ strncpy (vl.plugin_instance, plugin_instance,
+ sizeof (vl.plugin_instance));
+
+ for (i = 0; i < len; i++)
{
- syslog (LOG_ERR, "nfs: snprintf's format failed: %s", strerror (errno));
- return;
+ values[0].counter = val[i];
+ strncpy (vl.type_instance, names[i],
+ sizeof (vl.type_instance));
+ DBG ("%s-%s/nfs_procedure-%s = %llu",
+ vl.plugin, vl.plugin_instance,
+ vl.type_instance, val[i]);
+ plugin_dispatch_values ("nfs_procedure", &vl);
}
-
- plugin_submit("nfs3_procedures", inst, buf);
-}
-#endif /* NFS_HAVE_READ */
+} /* void nfs_procedures_submit */
#if KERNEL_LINUX
static void nfs_read_stats_file (FILE *fh, char *inst)
{
char buffer[BUFSIZE];
+ char plugin_instance[DATA_MAX_NAME_LEN];
+
char *fields[48];
int numfields = 0;
{
numfields = strsplit (buffer, fields, 48);
- if (numfields < 2)
+ if (((numfields - 2) != nfs2_procedures_names_num)
+ && ((numfields - 2)
+ != nfs3_procedures_names_num))
continue;
- if (strncmp (fields[0], "proc2", 5) == 0)
+ if (strcmp (fields[0], "proc2") == 0)
{
int i;
unsigned long long *values;
- if (numfields - 2 != nfs2_procedures_ds_num)
+ if ((numfields - 2) != nfs2_procedures_names_num)
{
- syslog (LOG_WARNING, "nfs: Wrong number of fields (= %i) for NFS2 statistics.", numfields - 2);
+ syslog (LOG_WARNING, "nfs plugin: Wrong "
+ "number of fields (= %i) "
+ "for NFSv2 statistics.",
+ numfields - 2);
continue;
}
- if ((values = (unsigned long long *) malloc (nfs2_procedures_ds_num * sizeof (unsigned long long))) == NULL)
+ snprintf (plugin_instance, sizeof (plugin_instance),
+ "v2%s", inst);
+ plugin_instance[DATA_MAX_NAME_LEN - 1] = '\0';
+
+ values = (unsigned long long *) malloc (nfs2_procedures_names_num * sizeof (unsigned long long));
+ if (values == NULL)
{
- syslog (LOG_ERR, "nfs: malloc: %s", strerror (errno));
+ syslog (LOG_ERR, "nfs plugin: malloc "
+ "failed: %s",
+ strerror (errno));
continue;
}
- for (i = 0; i < nfs2_procedures_ds_num; i++)
+ for (i = 0; i < nfs2_procedures_names_num; i++)
values[i] = atoll (fields[i + 2]);
- nfs2_procedures_submit (values, inst);
+ nfs_procedures_submit (plugin_instance, values,
+ nfs2_procedures_names,
+ nfs2_procedures_names_num);
free (values);
}
int i;
unsigned long long *values;
- if (numfields - 2 != nfs3_procedures_ds_num)
+ if ((numfields - 2) != nfs3_procedures_names_num)
{
- syslog (LOG_WARNING, "nfs: Wrong number of fields (= %i) for NFS3 statistics.", numfields - 2);
+ syslog (LOG_WARNING, "nfs plugin: Wrong "
+ "number of fields (= %i) "
+ "for NFSv3 statistics.",
+ numfields - 2);
continue;
}
- if ((values = (unsigned long long *) malloc (nfs3_procedures_ds_num * sizeof (unsigned long long))) == NULL)
+ snprintf (plugin_instance, sizeof (plugin_instance),
+ "v3%s", inst);
+ plugin_instance[DATA_MAX_NAME_LEN - 1] = '\0';
+
+ values = (unsigned long long *) malloc (nfs3_procedures_names_num * sizeof (unsigned long long));
+ if (values == NULL)
{
- syslog (LOG_ERR, "nfs: malloc: %s", strerror (errno));
+ syslog (LOG_ERR, "nfs plugin: malloc "
+ "failed: %s",
+ strerror (errno));
continue;
}
- for (i = 0; i < nfs3_procedures_ds_num; i++)
+ for (i = 0; i < nfs3_procedures_names_num; i++)
values[i] = atoll (fields[i + 2]);
- nfs3_procedures_submit (values, inst);
+ nfs_procedures_submit (plugin_instance, values,
+ nfs3_procedures_names,
+ nfs3_procedures_names_num);
free (values);
}
- }
-}
+ } /* while (fgets (buffer, BUFSIZE, fh) != NULL) */
+} /* void nfs_read_stats_file */
#endif /* defined(KERNEL_LINUX) */
#undef BUFSIZE
}
#endif
-#if NFS_HAVE_READ
-static void nfs_read (void)
+static int nfs_read (void)
{
#if KERNEL_LINUX
FILE *fh;
if (nfs2_ksp_server != NULL)
nfs2_read_kstat (nfs2_ksp_server, "server");
#endif /* defined(HAVE_LIBKSTAT) */
+
+ return (0);
}
-#else
-# define nfs_read NULL
#endif /* NFS_HAVE_READ */
void module_register (void)
{
- plugin_register (MODULE_NAME, nfs_init, nfs_read, NULL);
- plugin_register ("nfs2_procedures", NULL, NULL, nfs2_procedures_write);
- plugin_register ("nfs3_procedures", NULL, NULL, nfs3_procedures_write);
+ plugin_register_data_set (&procedure_ds);
+
+#if NFS_HAVE_READ
+ plugin_register_read ("nfs", nfs_read);
+#endif
}
#undef MODULE_NAME
/**
* collectd - src/ntpd.c
- * Copyright (C) 2006 Florian octo Forster
+ * Copyright (C) 2006-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
#include "configfile.h"
#include "utils_debug.h"
-#define MODULE_NAME "ntpd"
-
#if HAVE_SYS_SOCKET_H
# define NTPD_HAVE_READ 1
#else
#if HAVE_NETINET_TCP_H
# include <netinet/tcp.h>
#endif
-#if HAVE_SYS_POLL_H
-# include <sys/poll.h>
+#if HAVE_POLL_H
+# include <poll.h>
#endif
-static char *config_keys[] =
+static data_source_t seconds_dsrc[1] =
{
- "Host",
- "Port",
- NULL
+ {"seconds", DS_TYPE_GAUGE, -1000000.0, 1000000.0}
+};
+
+static data_set_t time_offset_ds =
+{
+ "time_offset", 1, seconds_dsrc
};
-static int config_keys_num = 2;
-/* drift */
-static char *time_offset_file = "ntpd/time_offset-%s.rrd";
-static char *time_dispersion_file = "ntpd/time_dispersion-%s.rrd";
-static char *time_delay_file = "ntpd/delay-%s.rrd";
+static data_set_t time_dispersion_ds =
+{
+ "time_dispersion", 1, seconds_dsrc
+};
-/* used for `time_offset', `time_dispersion', and `delay' */
-static char *sec_ds_def[] =
+static data_set_t delay_ds =
{
- "DS:seconds:GAUGE:"COLLECTD_HEARTBEAT":-1000000:1000000",
- NULL
+ "delay", 1, seconds_dsrc
+};
+
+static data_source_t ppm_dsrc[1] =
+{
+ {"ppm", DS_TYPE_GAUGE, -1000000.0, 1000000.0}
};
-static int sec_ds_num = 1;
-static char *frequency_offset_file = "ntpd/frequency_offset-%s.rrd";
-static char *frequency_offset_ds_def[] =
+static data_set_t frequency_offset_ds =
{
- "DS:ppm:GAUGE:"COLLECTD_HEARTBEAT":-1000000:1000000",
+ "frequency_offset", 1, ppm_dsrc
+};
+
+static const char *config_keys[] =
+{
+ "Host",
+ "Port",
NULL
};
-static int frequency_offset_ds_num = 1;
+static int config_keys_num = 2;
#if NTPD_HAVE_READ
# define NTPD_DEFAULT_HOST "localhost"
static int sock_descr = -1;
static char *ntpd_host = NULL;
static char *ntpd_port = NULL;
-#endif
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* The following definitions were copied from the NTPd distribution *
* End of the copied stuff.. *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
-static int ntpd_config (char *key, char *value)
+static int ntpd_config (const char *key, const char *value)
{
if (strcasecmp (key, "host") == 0)
{
return (0);
}
-static void ntpd_init (void)
+static void ntpd_submit (char *type, char *type_inst, double value)
{
- return;
-}
+ value_t values[1];
+ value_list_t vl = VALUE_LIST_INIT;
-static void ntpd_write_sec (char *host, char *inst, char *val, char *file)
-{
- char buf[256];
- int status;
+ values[0].gauge = value;
- status = snprintf (buf, 256, file, inst);
- if ((status < 1) || (status >= 256))
- return;
+ vl.values = values;
+ vl.values_len = 1;
+ vl.time = time (NULL);
+ strcpy (vl.host, hostname);
+ strcpy (vl.plugin, "ntpd");
+ strcpy (vl.plugin_instance, "");
+ strncpy (vl.type_instance, type_inst, sizeof (vl.type_instance));
- rrd_update_file (host, buf, val,
- sec_ds_def, sec_ds_num);
-}
-
-static void ntpd_write_time_offset (char *host, char *inst, char *val)
-{
- ntpd_write_sec (host, inst, val, time_offset_file);
-}
-
-static void ntpd_write_time_dispersion (char *host, char *inst, char *val)
-{
- ntpd_write_sec (host, inst, val, time_dispersion_file);
-}
-
-static void ntpd_write_delay (char *host, char *inst, char *val)
-{
- ntpd_write_sec (host, inst, val, time_delay_file);
-}
-
-static void ntpd_write_frequency_offset (char *host, char *inst, char *val)
-{
- char buf[256];
- int status;
-
- status = snprintf (buf, 256, frequency_offset_file, inst);
- if ((status < 1) || (status >= 256))
- return;
-
- rrd_update_file (host, buf, val,
- frequency_offset_ds_def, frequency_offset_ds_num);
-}
-
-#if NTPD_HAVE_READ
-static void ntpd_submit (char *type, char *inst, double value)
-{
- char buf[256];
-
- if (snprintf (buf, 256, "%u:%.8f", (unsigned int) curtime, value) >= 256)
- return;
-
- DBG ("type = %s; inst = %s; value = %s;",
- type, inst, buf);
-
- plugin_submit (type, inst, buf);
+ plugin_dispatch_values (type, &vl);
}
/* returns `tv0 - tv1' in milliseconds or 0 if `tv1 > tv0' */
return (val_double);
}
-static void ntpd_read (void)
+static int ntpd_read (void)
{
struct info_kernel *ik;
int ik_num;
if (status != 0)
{
DBG ("ntpd_do_query failed with status %i", status);
- return;
+ return (-1);
}
if ((ik == NULL) || (ik_num == 0) || (ik_size == 0))
{
DBG ("ntpd_do_query returned: ik = %p; ik_num = %i; ik_size = %i;",
(void *) ik, ik_num, ik_size);
- return;
+ return (-1);
}
/* kerninfo -> estimated error */
ntpd_read_fp (ik->freq),
ntpd_read_fp (ik->esterror));
- ntpd_submit ("ntpd_frequency_offset", "loop", ntpd_read_fp (ik->freq));
- ntpd_submit ("ntpd_time_offset", "loop", ntpd_read_fp (ik->offset));
- ntpd_submit ("ntpd_time_offset", "error", ntpd_read_fp (ik->esterror));
+ ntpd_submit ("frequency_offset", "loop", ntpd_read_fp (ik->freq));
+ ntpd_submit ("time_offset", "loop", ntpd_read_fp (ik->offset));
+ ntpd_submit ("time_offset", "error", ntpd_read_fp (ik->esterror));
free (ik);
ik = NULL;
if (status != 0)
{
DBG ("ntpd_do_query failed with status %i", status);
- return;
+ return (-1);
}
if ((ps == NULL) || (ps_num == 0) || (ps_size == 0))
{
DBG ("ntpd_do_query returned: ps = %p; ps_num = %i; ps_size = %i;",
(void *) ps, ps_num, ps_size);
- return;
+ return (-1);
}
for (i = 0; i < ps_num; i++)
ntpd_read_fp (ptr->dispersion));
if (refclock_id != 1) /* not the system clock (offset will always be zero.. */
- ntpd_submit ("ntpd_time_offset", peername, offset);
- ntpd_submit ("ntpd_time_dispersion", peername, ntpd_read_fp (ptr->dispersion));
+ ntpd_submit ("time_offset", peername, offset);
+ ntpd_submit ("time_dispersion", peername, ntpd_read_fp (ptr->dispersion));
if (refclock_id == 0) /* not a reference clock */
- ntpd_submit ("ntpd_delay", peername, ntpd_read_fp (ptr->delay));
+ ntpd_submit ("delay", peername, ntpd_read_fp (ptr->delay));
}
free (ps);
ps = NULL;
- return;
-}
-#else
-# define ntpd_read NULL
+ return (0);
+} /* int ntpd_read */
#endif /* NTPD_HAVE_READ */
void module_register (void)
{
- plugin_register (MODULE_NAME, ntpd_init, ntpd_read, NULL);
- plugin_register ("ntpd_time_offset", NULL, NULL, ntpd_write_time_offset);
- plugin_register ("ntpd_time_dispersion", NULL, NULL, ntpd_write_time_dispersion);
- plugin_register ("ntpd_delay", NULL, NULL, ntpd_write_delay);
- plugin_register ("ntpd_frequency_offset", NULL, NULL, ntpd_write_frequency_offset);
- cf_register (MODULE_NAME, ntpd_config, config_keys, config_keys_num);
-}
+ plugin_register_data_set (&time_offset_ds);
+ plugin_register_data_set (&time_dispersion_ds);
+ plugin_register_data_set (&delay_ds);
+ plugin_register_data_set (&frequency_offset_ds);
-#undef MODULE_NAME
+#if NTPD_HAVE_READ
+ plugin_register_config ("ntpd", ntpd_config, config_keys, config_keys_num);
+ plugin_register_read ("ntpd", ntpd_read);
+#endif /* NTPD_HAVE_READ */
+}
*
* 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; either version 2 of the License, or (at your
- * option) any later version.
+ * 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
#include "configfile.h"
#include "utils_debug.h"
-#define MODULE_NAME "ping"
-
#include <netinet/in.h>
#include "liboping/oping.h"
+/*
+ * Private data types
+ */
struct hostlist_s
{
char *host;
};
typedef struct hostlist_s hostlist_t;
+/*
+ * Private variables
+ */
static pingobj_t *pingobj = NULL;
static hostlist_t *hosts = NULL;
-static char *file_template = "ping-%s.rrd";
+static data_source_t dsrc[1] =
+{
+ {"ping", DS_TYPE_GAUGE, 0, 65535.0},
+};
-static char *ds_def[] =
+static data_set_t ds =
{
- "DS:ping:GAUGE:"COLLECTD_HEARTBEAT":0:65535",
- NULL
+ "ping", 1, dsrc
};
-static int ds_num = 1;
-static char *config_keys[] =
+static const char *config_keys[] =
{
"Host",
"TTL",
};
static int config_keys_num = 2;
+/*
+ * Private functions
+ */
static void add_hosts (void)
{
hostlist_t *hl_this;
}
}
-static void ping_init (void)
+static int ping_init (void)
{
if (hosts != NULL)
add_hosts ();
+
+ return (0);
}
-static int ping_config (char *key, char *value)
+static int ping_config (const char *key, const char *value)
{
if (pingobj == NULL)
{
return (0);
}
-static void ping_write (char *host, char *inst, char *val)
-{
- char file[512];
- int status;
-
- status = snprintf (file, 512, file_template, inst);
- if (status < 1)
- return;
- else if (status >= 512)
- return;
-
- rrd_update_file (host, file, val, ds_def, ds_num);
-}
-
-#define BUFSIZE 256
static void ping_submit (char *host, double latency)
{
- char buf[BUFSIZE];
+ value_t values[1];
+ value_list_t vl = VALUE_LIST_INIT;
+
+ values[0].gauge = latency;
- if (snprintf (buf, BUFSIZE, "%u:%f", (unsigned int) curtime, latency) >= BUFSIZE)
- return;
+ vl.values = values;
+ vl.values_len = 1;
+ vl.time = time (NULL);
+ strcpy (vl.host, hostname);
+ strcpy (vl.plugin, "ping");
+ strcpy (vl.plugin_instance, "");
+ strncpy (vl.type_instance, host, sizeof (vl.type_instance));
- plugin_submit (MODULE_NAME, host, buf);
+ plugin_dispatch_values ("ping", &vl);
}
-#undef BUFSIZE
-static void ping_read (void)
+static int ping_read (void)
{
pingobj_iter_t *iter;
size_t buf_len;
if (pingobj == NULL)
- return;
+ return (-1);
if (hosts != NULL)
add_hosts ();
{
syslog (LOG_ERR, "ping: `ping_send' failed: %s",
ping_get_error (pingobj));
- return;
+ return (-1);
}
for (iter = ping_iterator_get (pingobj);
DBG ("host = %s, latency = %f", host, latency);
ping_submit (host, latency);
}
-}
+
+ return (0);
+} /* int ping_read */
void module_register (void)
{
- plugin_register (MODULE_NAME, ping_init, ping_read, ping_write);
- cf_register (MODULE_NAME, ping_config, config_keys, config_keys_num);
-}
-
-#undef MODULE_NAME
+ plugin_register_data_set (&ds);
+ plugin_register_init ("ping", ping_init);
+ plugin_register_read ("ping", ping_read);
+ plugin_register_config ("ping", ping_config, config_keys, config_keys_num);
+} /* void module_register */
*
* 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; either version 2 of the License, or (at your
- * option) any later version.
+ * 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
#include <ltdl.h>
#include "plugin.h"
-#include "network.h"
+#include "configfile.h"
+#include "utils_llist.h"
#include "utils_debug.h"
-typedef struct plugin
+/*
+ * Private structures
+ */
+struct read_func_s
{
- char *type;
- void (*init) (void);
- void (*read) (void);
- void (*write) (char *host, char *inst, char *val);
- void (*shutdown) (void);
- struct plugin *next;
-} plugin_t;
-
-static plugin_t *first_plugin = NULL;
+ int wait_time;
+ int wait_left;
+ int (*callback) (void);
+};
+typedef struct read_func_s read_func_t;
-extern int operating_mode;
+/*
+ * Private variables
+ */
+static llist_t *list_init;
+static llist_t *list_read;
+static llist_t *list_write;
+static llist_t *list_shutdown;
+static llist_t *list_data_set;
static char *plugindir = NULL;
-char *plugin_get_dir (void)
+char hostname[DATA_MAX_NAME_LEN] = "localhost";
+
+/*
+ * Static functions
+ */
+static const char *plugin_get_dir (void)
{
if (plugindir == NULL)
return (PLUGINDIR);
return (plugindir);
}
-void plugin_set_dir (const char *dir)
+static int register_callback (llist_t **list, const char *name, void *callback)
{
- if (plugindir != NULL)
- free (plugindir);
+ llentry_t *le;
- if (dir == NULL)
- plugindir = NULL;
- else if ((plugindir = strdup (dir)) == NULL)
- syslog (LOG_ERR, "strdup: %s", strerror (errno));
-}
+ if ((*list == NULL)
+ && ((*list = llist_create ()) == NULL))
+ return (-1);
-/*
- * Returns the number of plugins registered
- */
-int plugin_count (void)
-{
- int i;
- plugin_t *p;
+ le = llist_search (*list, name);
+ if (le == NULL)
+ {
+ le = llentry_create (name, callback);
+ if (le == NULL)
+ return (-1);
- for (i = 0, p = first_plugin; p != NULL; p = p->next)
- i++;
+ llist_append (*list, le);
+ }
+ else
+ {
+ le->value = callback;
+ }
- return (i);
-}
+ return (0);
+} /* int register_callback */
-/*
- * Returns the plugins with the type `type' or NULL if it's not found.
- */
-plugin_t *plugin_search (const char *type)
+static int plugin_unregister (llist_t *list, const char *name)
{
- plugin_t *ret;
+ llentry_t *e;
- if (type == NULL)
- return (NULL);
+ e = llist_search (list, name);
- for (ret = first_plugin; ret != NULL; ret = ret->next)
- if (strcmp (ret->type, type) == 0)
- break;
+ if (e == NULL)
+ return (-1);
- return (ret);
-}
+ llist_remove (list, e);
+ llentry_destroy (e);
-/*
- * Returns true if the plugin is loaded (i.e. `exists') and false otherwise.
- * This is used in `configfile.c' to skip sections that are not needed..
- */
-int plugin_exists (char *type)
-{
- if (plugin_search (type) == NULL)
- return (0);
- else
- return (1);
-}
+ return (0);
+} /* int plugin_unregister */
/*
* (Try to) load the shared object `file'. Won't complain if it isn't a shared
* object, but it will bitch about a shared object not having a
* ``module_register'' symbol..
*/
-int plugin_load_file (char *file)
+static int plugin_load_file (char *file)
{
lt_dlhandle dlh;
void (*reg_handle) (void);
return (0);
}
+/*
+ * Public functions
+ */
+void plugin_set_dir (const char *dir)
+{
+ if (plugindir != NULL)
+ free (plugindir);
+
+ if (dir == NULL)
+ plugindir = NULL;
+ else if ((plugindir = strdup (dir)) == NULL)
+ syslog (LOG_ERR, "strdup failed: %s", strerror (errno));
+}
+
#define BUFSIZE 512
int plugin_load (const char *type)
{
DIR *dh;
- char *dir;
+ const char *dir;
char filename[BUFSIZE];
char typename[BUFSIZE];
int typename_len;
dir = plugin_get_dir ();
ret = 1;
- /* don't load twice */
- if (plugin_search (type) != NULL)
- return (0);
-
/* `cpu' should not match `cpufreq'. To solve this we add `.so' to the
* type when matching the filename */
if (snprintf (typename, BUFSIZE, "%s.so", type) >= BUFSIZE)
}
/*
- * (Try to) load all plugins in `dir'. Returns the number of loaded plugins..
+ * The `register_*' functions follow
*/
-int plugin_load_all (char *dir)
+int plugin_register_config (const char *name,
+ int (*callback) (const char *key, const char *val),
+ const char **keys, int keys_num)
{
- DIR *dh;
- struct dirent *de;
- char filename[BUFSIZE];
- struct stat statbuf;
+ cf_register (name, callback, keys, keys_num);
+ return (0);
+} /* int plugin_register_config */
- if (dir == NULL)
- dir = plugin_get_dir ();
- else
- plugin_set_dir (dir);
+int plugin_register_init (const char *name,
+ int (*callback) (void))
+{
+ return (register_callback (&list_init, name, (void *) callback));
+} /* plugin_register_init */
- if ((dh = opendir (dir)) == NULL)
- {
- syslog (LOG_ERR, "opendir (%s): %s", dir, strerror (errno));
- return (0);
- }
+int plugin_register_read (const char *name,
+ int (*callback) (void))
+{
+ read_func_t *rf;
- while ((de = readdir (dh)) != NULL)
+ rf = (read_func_t *) malloc (sizeof (read_func_t));
+ if (rf == NULL)
{
- if (snprintf (filename, BUFSIZE, "%s/%s", dir, de->d_name) >= BUFSIZE)
- {
- syslog (LOG_WARNING, "snprintf: truncated: %s/%s", dir, de->d_name);
- continue;
- }
+ syslog (LOG_ERR, "plugin_register_read: malloc failed: %s",
+ strerror (errno));
+ return (-1);
+ }
- if (lstat (filename, &statbuf) == -1)
- {
- syslog (LOG_WARNING, "stat %s: %s", filename, strerror (errno));
- continue;
- }
- else if (!S_ISREG (statbuf.st_mode))
- {
- continue;
- }
+ memset (rf, '\0', sizeof (read_func_t));
+ rf->wait_time = atoi (COLLECTD_STEP);
+ rf->wait_left = 0;
+ rf->callback = callback;
- plugin_load_file (filename);
- }
+ return (register_callback (&list_read, name, (void *) rf));
+} /* int plugin_register_read */
- closedir (dh);
+int plugin_register_write (const char *name,
+ int (*callback) (const data_set_t *ds, const value_list_t *vl))
+{
+ return (register_callback (&list_write, name, (void *) callback));
+} /* int plugin_register_write */
- return (plugin_count ());
-}
-#undef BUFSIZE
+int plugin_register_shutdown (char *name,
+ int (*callback) (void))
+{
+ return (register_callback (&list_shutdown, name, (void *) callback));
+} /* int plugin_register_shutdown */
-/*
- * Call `init' on all plugins (if given)
- */
-void plugin_init_all (void)
+int plugin_register_data_set (const data_set_t *ds)
{
- plugin_t *p;
+ return (register_callback (&list_data_set, ds->type, (void *) ds));
+} /* int plugin_register_data_set */
- for (p = first_plugin; p != NULL; p = p->next)
- if (p->init != NULL)
- (*p->init) ();
+int plugin_unregister_init (const char *name)
+{
+ return (plugin_unregister (list_init, name));
}
-/*
- * Call `read' on all plugins (if given)
- */
-void plugin_read_all (const int *loop)
+int plugin_unregister_read (const char *name)
{
- plugin_t *p;
+ return (plugin_unregister (list_read, name));
+ llentry_t *e;
+
+ e = llist_search (list_read, name);
+
+ if (e == NULL)
+ return (-1);
+
+ llist_remove (list_read, e);
+ free (e->value);
+ llentry_destroy (e);
- for (p = first_plugin; (*loop == 0) && (p != NULL); p = p->next)
- if (p->read != NULL)
- (*p->read) ();
+ return (0);
}
-/*
- * Call `shutdown' on all plugins (if given)
- */
-void plugin_shutdown_all (void)
+int plugin_unregister_write (const char *name)
{
- plugin_t *p;
+ return (plugin_unregister (list_write, name));
+}
- for (p = first_plugin; NULL != p; p = p->next)
- if (NULL != p->shutdown)
- (*p->shutdown) ();
- return;
+int plugin_unregister_shutdown (const char *name)
+{
+ return (plugin_unregister (list_shutdown, name));
}
-/*
- * Add plugin to the linked list of registered plugins.
- */
-void plugin_register (char *type,
- void (*init) (void),
- void (*read) (void),
- void (*write) (char *, char *, char *))
+int plugin_unregister_data_set (const char *name)
{
- plugin_t *p;
+ return (plugin_unregister (list_data_set, name));
+}
- if (plugin_search (type) != NULL)
- return;
+void plugin_init_all (void)
+{
+ int (*callback) (void);
+ llentry_t *le;
+ int status;
-#ifdef HAVE_LIBRRD
- if (operating_mode != MODE_SERVER)
-#endif
- if ((init != NULL) && (read == NULL))
- syslog (LOG_NOTICE, "Plugin `%s' doesn't provide a read function.", type);
+ gethostname (hostname, sizeof (hostname));
- if ((p = (plugin_t *) malloc (sizeof (plugin_t))) == NULL)
+ if (list_init == NULL)
return;
- if ((p->type = strdup (type)) == NULL)
+ le = llist_head (list_init);
+ while (le != NULL)
{
- free (p);
- return;
+ callback = le->value;
+ status = (*callback) ();
+
+ if (status != 0)
+ {
+ syslog (LOG_ERR, "Initialization of plugin `%s' "
+ "failed with status %i. "
+ "Plugin will be unloaded. TODO!",
+ le->key, status);
+ plugin_unregister_read (le->key);
+ }
+
+ le = le->next;
}
+} /* void plugin_init_all */
- p->init = init;
- p->read = read;
- p->write = write;
+void plugin_read_all (const int *loop)
+{
+ llentry_t *le;
+ read_func_t *rf;
+ int status;
+ int step;
- p->shutdown = NULL;
+ if (list_read == NULL)
+ return;
- p->next = first_plugin;
- first_plugin = p;
-}
+ step = atoi (COLLECTD_STEP);
-/*
- * Register the shutdown function (optional).
- */
-int plugin_register_shutdown (char *type, void (*shutdown) (void))
-{
- plugin_t *p = plugin_search (type);
+ le = llist_head (list_read);
+ while ((*loop == 0) && (le != NULL))
+ {
+ rf = (read_func_t *) le->value;
- if (NULL == p)
- return -1;
+ if (rf->wait_left > 0)
+ rf->wait_left -= step;
+ if (rf->wait_left > 0)
+ {
+ le = le->next;
+ continue;
+ }
- p->shutdown = shutdown;
- return 0;
-}
+ status = rf->callback ();
+ if (status != 0)
+ {
+ rf->wait_left = rf->wait_time;
+ rf->wait_time = rf->wait_time * 2;
+ if (rf->wait_time > 86400)
+ rf->wait_time = 86400;
+
+ syslog (LOG_NOTICE, "read-function of plugin `%s' "
+ "failed. Will syspend it for %i "
+ "seconds.", le->key, rf->wait_left);
+ }
+ else
+ {
+ rf->wait_left = 0;
+ rf->wait_time = step;
+ }
-/*
- * Send received data back to the plugin/module which will append DS
- * definitions and pass it on to ``rrd_update_file''.
- */
-void plugin_write (char *host, char *type, char *inst, char *val)
+ le = le->next;
+ } /* while ((*loop == 0) && (le != NULL)) */
+} /* void plugin_read_all */
+
+void plugin_shutdown_all (void)
{
- plugin_t *p;
+ int (*callback) (void);
+ llentry_t *le;
- if ((p = plugin_search (type)) == NULL)
+ if (list_shutdown == NULL)
return;
- if (p->write == NULL)
- return;
+ le = llist_head (list_shutdown);
+ while (le != NULL)
+ {
+ callback = le->value;
+ (*callback) ();
- (*p->write) (host, inst, val);
-}
+ le = le->next;
+ }
+} /* void plugin_shutdown_all */
-/*
- * Receive data from the plugin/module and get it somehow to ``plugin_write'':
- * Either using ``network_send'' (when in network/client mode) or call it
- * directly (in local mode).
- */
-void plugin_submit (char *type, char *inst, char *val)
+int plugin_dispatch_values (const char *name, const value_list_t *vl)
{
- if (inst == NULL)
- inst = "-";
+ int (*callback) (const data_set_t *, const value_list_t *);
+ data_set_t *ds;
+ llentry_t *le;
+
+ if (list_write == NULL)
+ return (-1);
- if ((type == NULL) || (val == NULL))
+ le = llist_search (list_data_set, name);
+ if (le == NULL)
{
- DBG ("Help! NULL-pointer! type = %s; inst = %s; val = %s;",
- (type == NULL) ? "(null)" : type,
- inst,
- (val == NULL) ? "(null)" : val);
- return;
+ DBG ("No such dataset registered: %s", name);
+ return (-1);
}
- if (operating_mode == MODE_CLIENT)
- network_send (type, inst, val);
- else
- plugin_write (NULL, type, inst, val);
+ ds = (data_set_t *) le->value;
+
+ DBG ("time = %u; host = %s; "
+ "plugin = %s; plugin_instance = %s; "
+ "type = %s; type_instance = %s;",
+ (unsigned int) vl->time, vl->host,
+ vl->plugin, vl->plugin_instance,
+ ds->type, vl->type_instance);
+
+ le = llist_head (list_write);
+ while (le != NULL)
+ {
+ callback = le->value;
+ (*callback) (ds, vl);
+
+ le = le->next;
+ }
+
+ return (0);
}
void plugin_complain (int level, complain_t *c, const char *format, ...)
*
* 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; either version 2 of the License, or (at your
- * option) any later version.
+ * 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
* Florian octo Forster <octo at verplant.org>
**/
+#define DATA_MAX_NAME_LEN 64
+
+#define DS_TYPE_COUNTER 0
+#define DS_TYPE_GAUGE 1
+
/*
- *
+ * Public data types
*/
+typedef unsigned long long counter_t;
+typedef double gauge_t;
+
+union value_u
+{
+ counter_t counter;
+ gauge_t gauge;
+};
+typedef union value_u value_t;
+
+struct value_list_s
+{
+ value_t *values;
+ int values_len;
+ time_t time;
+ char host[DATA_MAX_NAME_LEN];
+ char plugin[DATA_MAX_NAME_LEN];
+ char plugin_instance[DATA_MAX_NAME_LEN];
+ char type_instance[DATA_MAX_NAME_LEN];
+};
+typedef struct value_list_s value_list_t;
+
+#define VALUE_LIST_INIT { NULL, 0, 0, "localhost", "", "", "" }
+
+struct data_source_s
+{
+ char name[DATA_MAX_NAME_LEN];
+ int type;
+ double min;
+ double max;
+};
+typedef struct data_source_s data_source_t;
+
+struct data_set_s
+{
+ char type[DATA_MAX_NAME_LEN];
+ int ds_num;
+ data_source_t *ds;
+};
+typedef struct data_set_s data_set_t;
+
typedef struct complain_s
{
unsigned int interval; /* how long we wait for reporting this error again */
unsigned int delay; /* how many more iterations we still need to wait */
} complain_t;
+extern char hostname[DATA_MAX_NAME_LEN];
+
/*
* NAME
* plugin_set_dir
/*
* NAME
- * plugin_count
- *
- * DESCRIPTION
- * trivial
- *
- * RETURN VALUE
- * The number of currently loaded plugins
- */
-int plugin_count (void);
-
-/*
- * NAME
- * plugin_exists
- *
- * DESCRIPTION
- * trivial
- *
- * ARGUMENTS
- * `type' Name of the plugin.
- *
- * RETURN VALUE
- * Returns non-zero if a plugin with the name $type is found and zero
- * otherwise.
- */
-int plugin_exists (char *type);
-
-/*
- * NAME
* plugin_load
*
* DESCRIPTION
* NOTES
* No attempt is made to re-load an already loaded module.
*/
-int plugin_load (const char *type);
+int plugin_load (const char *name);
-int plugin_load_all (char *dir);
void plugin_init_all (void);
void plugin_read_all (const int *loop);
-
void plugin_shutdown_all (void);
-void plugin_register (char *type,
- void (*init) (void),
- void (*read) (void),
- void (*write) (char *, char *, char *));
+/*
+ * The `plugin_register_*' functions are used to make `config', `init',
+ * `read', `write' and `shutdown' functions known to the plugin
+ * infrastructure. Also, the data-formats are made public like this.
+ */
+int plugin_register_config (const char *name,
+ int (*callback) (const char *key, const char *val),
+ const char **keys, int keys_num);
+int plugin_register_init (const char *name,
+ int (*callback) (void));
+int plugin_register_read (const char *name,
+ int (*callback) (void));
+int plugin_register_write (const char *name,
+ int (*callback) (const data_set_t *ds, const value_list_t *vl));
+int plugin_register_shutdown (char *name,
+ int (*callback) (void));
+int plugin_register_data_set (const data_set_t *ds);
-int plugin_register_shutdown (char *, void (*) (void));
+int plugin_unregister_init (const char *name);
+int plugin_unregister_read (const char *name);
+int plugin_unregister_write (const char *name);
+int plugin_unregister_shutdown (const char *name);
+int plugin_unregister_data_set (const char *name);
/*
* NAME
- * plugin_write
+ * plugin_dispatch_values
*
* DESCRIPTION
- * Searches the plugin for `type' in the plugin-list. If found, and a `write'
- * function is registered, it's called. If either the plugin is not found or
- * the plugin doesn't provide a `write' function this function will return
- * without further notice.
+ * This function is called by reading processes with the values they've
+ * aquired. The function fetches the data-set definition (that has been
+ * registered using `plugin_register_data_set') and calls _all_ registered
+ * write-functions.
*
* ARGUMENTS
- * `host' Host(name) from which the data originates.
- * `type' Name of the plugin.
- * `inst' Instance (passed to the plugin's `write' function.
- * `val' Values for the RRD files. Also passed to the plugin.
+ * `name' Name/type of the data-set that describe the values in `vl'.
+ * `vl' Value list of the values that have been read by a `read'
+ * function.
*/
-void plugin_write (char *host, char *type, char *inst, char *val);
-
-void plugin_submit (char *type, char *inst, char *val);
-
+int plugin_dispatch_values (const char *name, const value_list_t *vl);
+/* TODO: Move plugin_{complain,relief} into `utils_complain.[ch]'. -octo */
void plugin_complain (int level, complain_t *c, const char *format, ...);
void plugin_relief (int level, complain_t *c, const char *format, ...);
/**
* collectd - src/processes.c
* Copyright (C) 2005 Lyonel Vincent
- * Copyright (C) 2006 Florian Forster (Mach code)
+ * Copyright (C) 2006-2007 Florian Forster (Mach code)
*
* 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
#define BUFSIZE 256
-static char *processes_file = "processes.rrd";
-static char *processes_ds_def[] =
+static data_source_t state_dsrc[1] =
{
- "DS:running:GAUGE:"COLLECTD_HEARTBEAT":0:65535",
- "DS:sleeping:GAUGE:"COLLECTD_HEARTBEAT":0:65535",
- "DS:zombies:GAUGE:"COLLECTD_HEARTBEAT":0:65535",
- "DS:stopped:GAUGE:"COLLECTD_HEARTBEAT":0:65535",
- "DS:paging:GAUGE:"COLLECTD_HEARTBEAT":0:65535",
- "DS:blocked:GAUGE:"COLLECTD_HEARTBEAT":0:65535",
- NULL
+ {"value", DS_TYPE_GAUGE, 0.0, 65535.0}
};
-static int processes_ds_num = 6;
-static char *ps_rss_file = "processes/ps_rss-%s.rrd";
-static char *ps_rss_ds_def[] =
+static data_set_t state_ds =
+{
+ "ps_state", 1, state_dsrc
+};
+
+static data_source_t rss_dsrc[1] =
{
/* max = 2^63 - 1 */
- "DS:byte:GAUGE:"COLLECTD_HEARTBEAT":0:9223372036854775807",
- NULL
+ {"value", DS_TYPE_GAUGE, 0.0, 9223372036854775807.0}
};
-static int ps_rss_ds_num = 1;
-static char *ps_cputime_file = "processes/ps_cputime-%s.rrd";
-static char *ps_cputime_ds_def[] =
+static data_set_t rss_ds =
+{
+ "ps_rss", 1, rss_dsrc
+};
+
+static data_source_t time_dsrc[2] =
{
/* 1 second in user-mode per second ought to be enough.. */
- "DS:user:COUNTER:"COLLECTD_HEARTBEAT":0:1000000",
- "DS:syst:COUNTER:"COLLECTD_HEARTBEAT":0:1000000",
- NULL
+ {"user", DS_TYPE_COUNTER, 0.0, 1000000.0},
+ {"syst", DS_TYPE_COUNTER, 0.0, 1000000.0}
};
-static int ps_cputime_ds_num = 2;
-static char *ps_count_file = "processes/ps_count-%s.rrd";
-static char *ps_count_ds_def[] =
+static data_set_t time_ds =
{
- "DS:processes:GAUGE:"COLLECTD_HEARTBEAT":0:65535",
- "DS:threads:GAUGE:"COLLECTD_HEARTBEAT":0:65535",
- NULL
+ "ps_cputime", 2, time_dsrc
+};
+
+static data_source_t count_dsrc[2] =
+{
+ /* 1 second in user-mode per second ought to be enough.. */
+ {"processes", DS_TYPE_GAUGE, 0.0, 1000000.0},
+ {"threads", DS_TYPE_GAUGE, 0.0, 1000000.0}
};
-static int ps_count_ds_num = 2;
-static char *ps_pagefaults_file = "processes/ps_pagefaults-%s.rrd";
-static char *ps_pagefaults_ds_def[] =
+static data_set_t count_ds =
+{
+ "ps_count", 2, count_dsrc
+};
+
+static data_source_t pagefaults_dsrc[2] =
{
/* max = 2^63 - 1 */
- "DS:minflt:COUNTER:"COLLECTD_HEARTBEAT":0:9223372036854775807",
- "DS:majflt:COUNTER:"COLLECTD_HEARTBEAT":0:9223372036854775807",
- NULL
+ {"minflt", DS_TYPE_COUNTER, 0.0, 9223372036854775807.0},
+ {"majflt", DS_TYPE_COUNTER, 0.0, 9223372036854775807.0}
};
-static int ps_pagefaults_ds_num = 2;
+static data_set_t pagefaults_ds =
+{
+ "ps_pagefaults", 2, pagefaults_dsrc
+};
+
+#if PROCESSES_HAVE_READ
#if HAVE_THREAD_INFO | KERNEL_LINUX
-static char *config_keys[] =
+static const char *config_keys[] =
{
"Process",
NULL
} /* for (ps = list_head_g; ps != NULL; ps = ps->next) */
}
-static int ps_config (char *key, char *value)
+static int ps_config (const char *key, const char *value)
{
if (strcasecmp (key, "Process") == 0)
{
}
#endif /* HAVE_THREAD_INFO | KERNEL_LINUX */
-static void ps_init (void)
+static int ps_init (void)
{
#if HAVE_THREAD_INFO
kern_return_t status;
mach_error_string (status));
pset_list = NULL;
pset_list_len = 0;
- return;
+ return (-1);
}
/* #endif HAVE_THREAD_INFO */
pagesize_g, CONFIG_HZ);
#endif /* KERNEL_LINUX */
- return;
-}
-
-static void ps_write (char *host, char *inst, char *val)
-{
- rrd_update_file (host, processes_file, val,
- processes_ds_def, processes_ds_num);
-}
-
-static void ps_rss_write (char *host, char *inst, char *val)
-{
- char filename[256];
- int status;
-
- status = snprintf (filename, 256, ps_rss_file, inst);
- if ((status < 1) || (status >= 256))
- return;
-
- rrd_update_file (host, filename, val, ps_rss_ds_def, ps_rss_ds_num);
-}
-
-static void ps_cputime_write (char *host, char *inst, char *val)
-{
- char filename[256];
- int status;
-
- status = snprintf (filename, 256, ps_cputime_file, inst);
- if ((status < 1) || (status >= 256))
- return;
-
- DBG ("host = %s; filename = %s; val = %s;",
- host, filename, val);
- rrd_update_file (host, filename, val,
- ps_cputime_ds_def, ps_cputime_ds_num);
-}
-
-static void ps_count_write (char *host, char *inst, char *val)
-{
- char filename[256];
- int status;
-
- status = snprintf (filename, 256, ps_count_file, inst);
- if ((status < 1) || (status >= 256))
- return;
-
- DBG ("host = %s; filename = %s; val = %s;",
- host, filename, val);
- rrd_update_file (host, filename, val,
- ps_count_ds_def, ps_count_ds_num);
-}
-
-static void ps_pagefaults_write (char *host, char *inst, char *val)
-{
- char filename[256];
- int status;
-
- status = snprintf (filename, 256, ps_pagefaults_file, inst);
- if ((status < 1) || (status >= 256))
- return;
-
- DBG ("host = %s; filename = %s; val = %s;",
- host, filename, val);
- rrd_update_file (host, filename, val,
- ps_pagefaults_ds_def, ps_pagefaults_ds_num);
-}
+ return (0);
+} /* int ps_init */
-#if PROCESSES_HAVE_READ
-static void ps_submit (int running,
- int sleeping,
- int zombies,
- int stopped,
- int paging,
- int blocked)
+static void ps_submit_state (const char *state, double value)
{
- char buf[BUFSIZE];
+ value_t values[1];
+ value_list_t vl = VALUE_LIST_INIT;
- if (snprintf (buf, BUFSIZE, "%u:%i:%i:%i:%i:%i:%i",
- (unsigned int) curtime,
- running, sleeping, zombies, stopped, paging,
- blocked) >= BUFSIZE)
- return;
+ values[0].gauge = value;
- DBG ("running = %i; sleeping = %i; zombies = %i; stopped = %i; paging = %i; blocked = %i;",
- running, sleeping, zombies, stopped, paging, blocked);
+ vl.values = values;
+ vl.values_len = 1;
+ vl.time = time (NULL);
+ strcpy (vl.host, hostname);
+ strcpy (vl.plugin, "processes");
+ strcpy (vl.plugin_instance, "");
+ strncpy (vl.type_instance, state, sizeof (vl.type_instance));
- plugin_submit (MODULE_NAME, "-", buf);
+ plugin_dispatch_values ("ps_state", &vl);
}
static void ps_submit_proc_list (procstat_t *ps)
{
- char buffer[64];
-
- if (ps == NULL)
- return;
-
- snprintf (buffer, 64, "%u:%lu",
- (unsigned int) curtime,
- ps->vmem_rss);
- buffer[63] = '\0';
- plugin_submit ("ps_rss", ps->name, buffer);
-
- snprintf (buffer, 64, "%u:%u:%u",
- (unsigned int) curtime,
- /* Make the counter overflow */
- (unsigned int) (ps->cpu_user_counter & 0xFFFFFFFF),
- (unsigned int) (ps->cpu_system_counter & 0xFFFFFFFF));
- buffer[63] = '\0';
- plugin_submit ("ps_cputime", ps->name, buffer);
-
- snprintf (buffer, 64, "%u:%lu:%lu",
- (unsigned int) curtime,
- ps->num_proc, ps->num_lwp);
- buffer[63] = '\0';
- plugin_submit ("ps_count", ps->name, buffer);
-
- snprintf (buffer, 64, "%u:%lu:%lu",
- (unsigned int) curtime,
- ps->vmem_minflt_counter, ps->vmem_majflt_counter);
- buffer[63] = '\0';
- plugin_submit ("ps_pagefaults", ps->name, buffer);
+ value_t values[2];
+ value_list_t vl = VALUE_LIST_INIT;
+
+ vl.values = values;
+ vl.values_len = 2;
+ vl.time = time (NULL);
+ strcpy (vl.host, hostname);
+ strcpy (vl.plugin, "processes");
+ strncpy (vl.plugin_instance, ps->name, sizeof (vl.plugin_instance));
+
+ vl.values[0].gauge = ps->vmem_rss;
+ vl.values_len = 1;
+ plugin_dispatch_values ("ps_rss", &vl);
+
+ vl.values[0].counter = ps->cpu_user_counter;
+ vl.values[1].counter = ps->cpu_system_counter;
+ vl.values_len = 2;
+ plugin_dispatch_values ("ps_cputime", &vl);
+
+ vl.values[0].gauge = ps->num_proc;
+ vl.values[1].gauge = ps->num_lwp;
+ vl.values_len = 2;
+ plugin_dispatch_values ("ps_count", &vl);
+
+ vl.values[0].counter = ps->vmem_minflt_counter;
+ vl.values[1].counter = ps->vmem_majflt_counter;
+ vl.values_len = 2;
+ plugin_dispatch_values ("ps_pagefaults", &vl);
DBG ("name = %s; num_proc = %lu; num_lwp = %lu; vmem_rss = %lu; "
"vmem_minflt_counter = %lu; vmem_majflt_counter = %lu; "
"cpu_user_counter = %lu; cpu_system_counter = %lu;",
ps->name, ps->num_proc, ps->num_lwp, ps->vmem_rss,
- ps->vmem_minflt_counter, ps->vmem_majflt_counter, ps->cpu_user_counter,
- ps->cpu_system_counter);
-
-}
+ ps->vmem_minflt_counter, ps->vmem_majflt_counter,
+ ps->cpu_user_counter, ps->cpu_system_counter);
+} /* void ps_submit_proc_list */
#if KERNEL_LINUX
static int *ps_read_tasks (int pid)
}
#endif /* HAVE_THREAD_INFO */
-static void ps_read (void)
+static int ps_read (void)
{
#if HAVE_THREAD_INFO
kern_return_t status;
}
} /* for (pset_list) */
- ps_submit (running, sleeping, zombies, stopped, -1, blocked);
+ ps_submit_state ("running", running);
+ ps_submit_state ("sleeping", sleeping);
+ ps_submit_state ("zombies", zombies);
+ ps_submit_state ("stopped", stopped);
+ ps_submit_state ("blocked", blocked);
for (ps = list_head_g; ps != NULL; ps = ps->next)
ps_submit_proc_list (ps);
if ((proc = opendir ("/proc")) == NULL)
{
syslog (LOG_ERR, "Cannot open `/proc': %s", strerror (errno));
- return;
+ return (-1);
}
while ((ent = readdir (proc)) != NULL)
closedir (proc);
- ps_submit (running, sleeping, zombies, stopped, paging, blocked);
+ ps_submit_state ("running", running);
+ ps_submit_state ("sleeping", sleeping);
+ ps_submit_state ("zombies", zombies);
+ ps_submit_state ("stopped", stopped);
+ ps_submit_state ("paging", paging);
+ ps_submit_state ("blocked", blocked);
for (ps_ptr = list_head_g; ps_ptr != NULL; ps_ptr = ps_ptr->next)
ps_submit_proc_list (ps_ptr);
#endif /* KERNEL_LINUX */
-}
-#else
-# define ps_read NULL
+
+ return (0);
+} /* int ps_read */
#endif /* PROCESSES_HAVE_READ */
void module_register (void)
{
- plugin_register (MODULE_NAME, ps_init, ps_read, ps_write);
- plugin_register ("ps_rss", NULL, NULL, ps_rss_write);
- plugin_register ("ps_cputime", NULL, NULL, ps_cputime_write);
- plugin_register ("ps_count", NULL, NULL, ps_count_write);
- plugin_register ("ps_pagefaults", NULL, NULL, ps_pagefaults_write);
+ plugin_register_data_set (&state_ds);
+ plugin_register_data_set (&rss_ds);
+ plugin_register_data_set (&time_ds);
+ plugin_register_data_set (&count_ds );
+ plugin_register_data_set (&pagefaults_ds );
+
+#if PROCESSES_HAVE_READ
#if HAVE_THREAD_INFO | KERNEL_LINUX
- cf_register (MODULE_NAME, ps_config, config_keys, config_keys_num);
+ plugin_register_config ("processes", ps_config,
+ config_keys, config_keys_num);
#endif
+ plugin_register_init ("processes", ps_init);
+ plugin_register_read ("processes", ps_read);
+#endif /* PROCESSES_HAVE_READ */
}
-#undef BUFSIZE
-#undef MODULE_NAME
--- /dev/null
+/**
+ * collectd - src/rrdtool.c
+ * Copyright (C) 2006 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 <octo at verplant.org>
+ **/
+
+#include "collectd.h"
+#include "plugin.h"
+#include "common.h"
+#include "utils_llist.h"
+#include "utils_debug.h"
+
+/*
+ * This weird macro cascade forces the glibc to define `NAN'. I don't know
+ * another way to solve this, so more intelligent solutions are welcome. -octo
+ */
+#ifndef __USE_ISOC99
+# define DISABLE__USE_ISOC99 1
+# define __USE_ISOC99 1
+#endif
+#include <math.h>
+#ifdef DISABLE__USE_ISOC99
+# undef DISABLE__USE_ISOC99
+# undef __USE_ISOC99
+#endif
+
+/*
+ * Private types
+ */
+struct rrd_cache_s
+{
+ int values_num;
+ char **values;
+ time_t first_value;
+};
+typedef struct rrd_cache_s rrd_cache_t;
+
+/*
+ * Private variables
+ */
+static int rra_timespans[] =
+{
+ 3600,
+ 86400,
+ 604800,
+ 2678400,
+ 31622400,
+ 0
+};
+static int rra_timespans_num = 5;
+
+static char *rra_types[] =
+{
+ "AVERAGE",
+ "MIN",
+ "MAX",
+ NULL
+};
+static int rra_types_num = 3;
+
+static const char *config_keys[] =
+{
+ "CacheTimeout",
+ NULL
+};
+static int config_keys_num = 1;
+
+static int cache_timeout = 0;
+static time_t cache_flush;
+static llist_t *cache = NULL;
+
+/* * * * * * * * * *
+ * WARNING: Magic *
+ * * * * * * * * * */
+static int rra_get (char ***ret)
+{
+ static char **rra_def = NULL;
+ static int rra_num = 0;
+
+ int rra_max = rra_timespans_num * rra_types_num;
+
+ int step;
+ int rows;
+ int span;
+
+ int cdp_num;
+ int cdp_len;
+ int i, j;
+
+ char buffer[64];
+
+ if ((rra_num != 0) && (rra_def != NULL))
+ {
+ *ret = rra_def;
+ return (rra_num);
+ }
+
+ if ((rra_def = (char **) malloc ((rra_max + 1) * sizeof (char *))) == NULL)
+ return (-1);
+ memset (rra_def, '\0', (rra_max + 1) * sizeof (char *));
+
+ step = atoi (COLLECTD_STEP);
+ rows = atoi (COLLECTD_ROWS);
+
+ if ((step <= 0) || (rows <= 0))
+ {
+ *ret = NULL;
+ return (-1);
+ }
+
+ cdp_len = 0;
+ for (i = 0; i < rra_timespans_num; i++)
+ {
+ span = rra_timespans[i];
+
+ if ((span / step) < rows)
+ continue;
+
+ if (cdp_len == 0)
+ cdp_len = 1;
+ else
+ cdp_len = (int) floor (((double) span) / ((double) (rows * step)));
+
+ cdp_num = (int) ceil (((double) span) / ((double) (cdp_len * step)));
+
+ for (j = 0; j < rra_types_num; j++)
+ {
+ if (rra_num >= rra_max)
+ break;
+
+ if (snprintf (buffer, sizeof(buffer), "RRA:%s:%3.1f:%u:%u",
+ rra_types[j], COLLECTD_XFF,
+ cdp_len, cdp_num) >= sizeof (buffer))
+ {
+ syslog (LOG_ERR, "rra_get: Buffer would have been truncated.");
+ continue;
+ }
+
+ rra_def[rra_num++] = sstrdup (buffer);
+ }
+ }
+
+#if COLLECT_DEBUG
+ DBG ("rra_num = %i", rra_num);
+ for (i = 0; i < rra_num; i++)
+ DBG (" %s", rra_def[i]);
+#endif
+
+ *ret = rra_def;
+ return (rra_num);
+}
+
+static void ds_free (int ds_num, char **ds_def)
+{
+ int i;
+
+ for (i = 0; i < ds_num; i++)
+ if (ds_def[i] != NULL)
+ free (ds_def[i]);
+ free (ds_def);
+}
+
+static int ds_get (char ***ret, const data_set_t *ds)
+{
+ char **ds_def;
+ int ds_num;
+
+ char min[32];
+ char max[32];
+ char buffer[128];
+
+ DBG ("ds->ds_num = %i", ds->ds_num);
+
+ ds_def = (char **) malloc (ds->ds_num * sizeof (char *));
+ if (ds_def == NULL)
+ {
+ syslog (LOG_ERR, "rrdtool plugin: malloc failed: %s",
+ strerror (errno));
+ return (-1);
+ }
+ memset (ds_def, '\0', ds->ds_num * sizeof (char *));
+
+ for (ds_num = 0; ds_num < ds->ds_num; ds_num++)
+ {
+ data_source_t *d = ds->ds + ds_num;
+ char *type;
+ int status;
+
+ ds_def[ds_num] = NULL;
+
+ if (d->type == DS_TYPE_COUNTER)
+ type = "COUNTER";
+ else if (d->type == DS_TYPE_GAUGE)
+ type = "GAUGE";
+ else
+ {
+ syslog (LOG_ERR, "rrdtool plugin: Unknown DS type: %i",
+ d->type);
+ break;
+ }
+
+ if (d->min == NAN)
+ {
+ strcpy (min, "U");
+ }
+ else
+ {
+ snprintf (min, sizeof (min), "%lf", d->min);
+ min[sizeof (min) - 1] = '\0';
+ }
+
+ if (d->max == NAN)
+ {
+ strcpy (max, "U");
+ }
+ else
+ {
+ snprintf (max, sizeof (max), "%lf", d->max);
+ max[sizeof (max) - 1] = '\0';
+ }
+
+ status = snprintf (buffer, sizeof (buffer),
+ "DS:%s:%s:%s:%s:%s",
+ d->name, type, COLLECTD_HEARTBEAT,
+ min, max);
+ if ((status < 1) || (status >= sizeof (buffer)))
+ break;
+
+ ds_def[ds_num] = sstrdup (buffer);
+ } /* for ds_num = 0 .. ds->ds_num */
+
+#if COLLECT_DEBUG
+{
+ int i;
+ DBG ("ds_num = %i", ds_num);
+ for (i = 0; i < ds_num; i++)
+ DBG (" %s", ds_def[i]);
+}
+#endif
+
+ if (ds_num != ds->ds_num)
+ {
+ ds_free (ds_num, ds_def);
+ return (-1);
+ }
+
+ *ret = ds_def;
+ return (ds_num);
+}
+
+static int rrd_create_file (char *filename, const data_set_t *ds)
+{
+ char **argv;
+ int argc;
+ char **rra_def;
+ int rra_num;
+ char **ds_def;
+ int ds_num;
+ int i, j;
+ int status = 0;
+
+ if (check_create_dir (filename))
+ return (-1);
+
+ if ((rra_num = rra_get (&rra_def)) < 1)
+ {
+ syslog (LOG_ERR, "rrd_create_file failed: Could not calculate RRAs");
+ return (-1);
+ }
+
+ if ((ds_num = ds_get (&ds_def, ds)) < 1)
+ {
+ syslog (LOG_ERR, "rrd_create_file failed: Could not calculate DSes");
+ return (-1);
+ }
+
+ argc = ds_num + rra_num + 4;
+
+ if ((argv = (char **) malloc (sizeof (char *) * (argc + 1))) == NULL)
+ {
+ syslog (LOG_ERR, "rrd_create failed: %s", strerror (errno));
+ return (-1);
+ }
+
+ argv[0] = "create";
+ argv[1] = filename;
+ argv[2] = "-s";
+ argv[3] = COLLECTD_STEP;
+
+ j = 4;
+ 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)
+ {
+ syslog (LOG_ERR, "rrd_create failed: %s: %s", filename, rrd_get_error ());
+ status = -1;
+ }
+
+ free (argv);
+ ds_free (ds_num, ds_def);
+
+ return (status);
+}
+
+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.rrd", ds->type, vl->type_instance);
+ else
+ status = snprintf (buffer + offset, buffer_len - offset,
+ "%s.rrd", ds->type);
+ if ((status < 1) || (status >= buffer_len - offset))
+ return (-1);
+ offset += status;
+
+ return (0);
+} /* int value_list_to_filename */
+
+static rrd_cache_t *rrd_cache_insert (const char *filename,
+ const char *value)
+{
+ rrd_cache_t *rc = NULL;
+ llentry_t *le = NULL;
+
+ if (cache != NULL)
+ {
+ le = llist_search (cache, filename);
+ if (le != NULL)
+ rc = (rrd_cache_t *) le->value;
+ }
+
+ if (rc == NULL)
+ {
+ rc = (rrd_cache_t *) malloc (sizeof (rrd_cache_t));
+ if (rc == NULL)
+ return (NULL);
+ rc->values_num = 0;
+ rc->values = NULL;
+ rc->first_value = 0;
+ }
+
+ rc->values = (char **) realloc ((void *) rc->values,
+ (rc->values_num + 1) * sizeof (char *));
+ if (rc->values == NULL)
+ {
+ syslog (LOG_ERR, "rrdtool plugin: realloc failed: %s",
+ strerror (errno));
+ free (rc);
+ if (le != NULL)
+ {
+ llist_remove (cache, le);
+ llentry_destroy (le);
+ }
+ return (NULL);
+ }
+
+ rc->values[rc->values_num] = strdup (value);
+ if (rc->values[rc->values_num] != NULL)
+ rc->values_num++;
+
+ if (rc->values_num == 1)
+ rc->first_value = time (NULL);
+
+ if ((cache != NULL) && (le == NULL))
+ {
+ le = llentry_create (filename, (void *) rc);
+ if (le != NULL)
+ llist_prepend (cache, le);
+ }
+
+ DBG ("rrd_cache_insert (%s, %s) = %p", filename, value, (void *) rc);
+
+ return (rc);
+} /* rrd_cache_t *rrd_cache_insert */
+
+static int rrd_write_cache_entry (const char *filename, rrd_cache_t *rc)
+{
+ char **argv;
+ int argc;
+
+ char *fn;
+ int status;
+
+ argc = rc->values_num + 2;
+ argv = (char **) malloc ((argc + 1) * sizeof (char *));
+ if (argv == NULL)
+ return (-1);
+
+ fn = strdup (filename);
+ if (fn == NULL)
+ {
+ free (argv);
+ return (-1);
+ }
+
+ argv[0] = "update";
+ argv[1] = fn;
+ memcpy (argv + 2, rc->values, rc->values_num * sizeof (char *));
+ argv[argc] = NULL;
+
+ DBG ("rrd_update (argc = %i, argv = %p)", argc, (void *) argv);
+
+ optind = 0; /* bug in librrd? */
+ rrd_clear_error ();
+ status = rrd_update (argc, argv);
+
+ free (argv);
+ free (fn);
+
+ free (rc->values);
+ rc->values = NULL;
+ rc->values_num = 0;
+
+ if (status != 0)
+ {
+ syslog (LOG_WARNING, "rrd_update failed: %s: %s",
+ filename, rrd_get_error ());
+ return (-1);
+ }
+
+ return (0);
+} /* int rrd_update_file */
+
+static void rrd_cache_flush (int timeout)
+{
+ llentry_t *le;
+ rrd_cache_t *rc;
+ time_t now;
+
+ if (cache == NULL)
+ return;
+
+ DBG ("Flushing cache, timeout = %i", timeout);
+
+ now = time (NULL);
+
+ /* Remove empty entries */
+ le = llist_head (cache);
+ while (le != NULL)
+ {
+ llentry_t *next = le->next;
+ rc = (rrd_cache_t *) le->value;
+ if (rc->values_num == 0)
+ {
+ DBG ("Removing cache entry for `%s'", le->key);
+ free (rc->values);
+ free (rc);
+ llist_remove (cache, le);
+ }
+ le = next;
+ }
+
+ /* Write timed out entries */
+ le = llist_head (cache);
+ while (le != NULL)
+ {
+ rc = (rrd_cache_t *) le->value;
+ if ((now - rc->first_value) >= timeout)
+ rrd_write_cache_entry (le->key, rc);
+
+ le = le->next;
+ }
+
+ cache_flush = now;
+} /* void rrd_cache_flush */
+
+static int rrd_write (const data_set_t *ds, const value_list_t *vl)
+{
+ struct stat statbuf;
+ char filename[512];
+ char values[512];
+ rrd_cache_t *rc;
+ time_t now;
+
+ 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 (rrd_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);
+ }
+
+ rc = rrd_cache_insert (filename, values);
+ if (rc == NULL)
+ return (-1);
+
+ if (cache == NULL)
+ {
+ rrd_write_cache_entry (filename, rc);
+ free (rc->values);
+ free (rc);
+ return (0);
+ }
+
+ now = time (NULL);
+
+ DBG ("age (%s) = %i", filename, now - rc->first_value);
+
+ if ((now - rc->first_value) >= cache_timeout)
+ rrd_write_cache_entry (filename, rc);
+
+ if ((time (NULL) - cache_flush) >= cache_timeout)
+ {
+ rrd_cache_flush (cache_timeout);
+ }
+
+ return (0);
+} /* int rrd_dispatch */
+
+static int rrd_config (const char *key, const char *val)
+{
+ if (strcasecmp ("CacheTimeout", key) == 0)
+ {
+ int tmp = atoi (val);
+ if (tmp < 0)
+ {
+ fprintf (stderr, "rrdtool: `CacheTimeout' must "
+ "be greater than 0.\n");
+ return (1);
+ }
+ cache_timeout = tmp;
+ }
+ else
+ {
+ return (-1);
+ }
+ return (0);
+} /* int rrd_config */
+
+static int rrd_shutdown (void)
+{
+ rrd_cache_flush (-1);
+
+ return (0);
+} /* int rrd_shutdown */
+
+static int rrd_init (void)
+{
+ if (cache_timeout < 2)
+ {
+ cache_timeout = 0;
+ }
+ else
+ {
+ cache = llist_create ();
+ cache_flush = time (NULL);
+ plugin_register_shutdown ("rrdtool", rrd_shutdown);
+ }
+ return (0);
+} /* int rrd_init */
+
+void module_register (void)
+{
+ plugin_register_config ("rrdtool", rrd_config,
+ config_keys, config_keys_num);
+ plugin_register_init ("rrdtool", rrd_init);
+ plugin_register_write ("rrdtool", rrd_write);
+}
/**
* collectd - src/sensors.c
- * Copyright (C) 2005,2006 Florian octo Forster
+ * Copyright (C) 2005-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; either version 2 of the License, or (at your
- * option) any later version.
+ * 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
#include "utils_ignorelist.h"
#include "utils_debug.h"
-#define MODULE_NAME "sensors"
-#define MODULE_NAME_VOLTAGE MODULE_NAME"_voltage"
-
#if defined(HAVE_SENSORS_SENSORS_H)
# include <sensors/sensors.h>
#else
# define SENSORS_HAVE_READ 0
#endif
-#define BUFSIZE 512
+static data_source_t data_source_fanspeed[1] =
+{
+ {"value", DS_TYPE_GAUGE, 0, NAN}
+};
-/* temperature and fan sensors */
-static char *ds_def[] =
+static data_set_t fanspeed_ds =
{
- "DS:value:GAUGE:"COLLECTD_HEARTBEAT":U:U",
- NULL
+ "fanspeed", 1, data_source_fanspeed
};
-static int ds_num = 1;
-/* voltage sensors */
-static char *sensor_voltage_ds_def[] =
+static data_source_t data_source_temperature[1] =
{
- "DS:voltage:GAUGE:"COLLECTD_HEARTBEAT":U:U",
- NULL
+ {"value", DS_TYPE_GAUGE, -273.15, NAN}
};
-static int sensor_voltage_ds_num = 1;
-/* old naming */
-static char *old_filename_format = "sensors-%s.rrd";
-/* end old naming */
+static data_set_t temperature_ds =
+{
+ "temperature", 1, data_source_temperature
+};
-/* new naming <chip-bus-address/type-feature */
-static char *extended_filename_format = "lm_sensors-%s.rrd";
+static data_source_t data_source_voltage[1] =
+{
+ {"value", DS_TYPE_GAUGE, NAN, NAN}
+};
-#define SENSOR_TYPE_UNKNOWN 0
-#define SENSOR_TYPE_VOLTAGE 1
-#define SENSOR_TYPE_FANSPEED 2
-#define SENSOR_TYPE_TEMPERATURE 3
+static data_set_t voltage_ds =
+{
+ "voltage", 1, data_source_voltage
+};
#if SENSORS_HAVE_READ
-static char *sensor_type_prefix[] =
+#define SENSOR_TYPE_VOLTAGE 0
+#define SENSOR_TYPE_FANSPEED 1
+#define SENSOR_TYPE_TEMPERATURE 2
+#define SENSOR_TYPE_UNKNOWN 3
+
+static char *sensor_to_type[] =
{
- "unknown",
"voltage",
"fanspeed",
"temperature",
NULL
};
-#endif
-typedef struct sensors_labeltypes {
+struct sensors_labeltypes_s
+{
char *label;
int type;
-} sensors_labeltypes;
+};
+typedef struct sensors_labeltypes_s sensors_labeltypes_t;
/*
* finite list of known labels extracted from lm_sensors
*/
-#if SENSORS_HAVE_READ
-static sensors_labeltypes known_features[] =
+static sensors_labeltypes_t known_features[] =
{
{ "fan1", SENSOR_TYPE_FANSPEED },
{ "fan2", SENSOR_TYPE_FANSPEED },
{ "2.5V", SENSOR_TYPE_VOLTAGE },
{ "2.0V", SENSOR_TYPE_VOLTAGE },
{ "12V", SENSOR_TYPE_VOLTAGE },
- { 0, -1 }
+ { (char *) 0, SENSOR_TYPE_UNKNOWN }
};
-#endif
/* end new naming */
-static char *config_keys[] =
+static const char *config_keys[] =
{
"Sensor",
"IgnoreSelected",
- "ExtendedSensorNaming",
NULL
};
-static int config_keys_num = 3;
+static int config_keys_num = 2;
static ignorelist_t *sensor_list;
-/*
- * sensor_extended_naming:
- * 0 => default is to create chip-feature
- * 1 => use new naming scheme chip-bus-address/type-feature
- */
-static int sensor_extended_naming = 0;
-
-#if SENSORS_HAVE_READ
-# ifndef SENSORS_CONF_PATH
-# define SENSORS_CONF_PATH "/etc/sensors.conf"
-# endif
+#ifndef SENSORS_CONF_PATH
+# define SENSORS_CONF_PATH "/etc/sensors.conf"
+#endif
static const char *conffile = SENSORS_CONF_PATH;
/* SENSORS_CONF_PATH */
} featurelist_t;
featurelist_t *first_feature = NULL;
-#endif /* if SENSORS_HAVE_READ */
-static int sensors_config (char *key, char *value)
+static int sensors_config (const char *key, const char *value)
{
if (sensor_list == NULL)
sensor_list = ignorelist_create (1);
{
if (ignorelist_add (sensor_list, value))
{
- syslog (LOG_EMERG, MODULE_NAME": Cannot add value to ignorelist.");
+ syslog (LOG_ERR, "sensors plugin: "
+ "Cannot add value to ignorelist.");
return (1);
}
}
|| (strcasecmp (value, "On") == 0))
ignorelist_set_invert (sensor_list, 0);
}
- else if (strcasecmp (key, "ExtendedSensorNaming") == 0)
- {
- if ((strcasecmp (value, "True") == 0)
- || (strcasecmp (value, "Yes") == 0)
- || (strcasecmp (value, "On") == 0))
- sensor_extended_naming = 1;
- else
- sensor_extended_naming = 0;
- }
else
{
return (-1);
return (0);
}
-#if SENSORS_HAVE_READ
void sensors_free_features (void)
{
featurelist_t *thisft;
status = stat (conffile, &statbuf);
if (status != 0)
{
- syslog (LOG_ERR, MODULE_NAME": stat(%s) failed: %s",
+ syslog (LOG_ERR, "sensors plugin: stat (%s) failed: %s",
conffile, strerror (errno));
sensors_config_mtime = 0;
}
if (sensors_config_mtime != 0)
{
- syslog (LOG_NOTICE, MODULE_NAME": Reloading config from %s",
+ syslog (LOG_NOTICE, "sensors plugin: Reloading config from %s",
conffile);
sensors_free_features ();
sensors_config_mtime = 0;
fh = fopen (conffile, "r");
if (fh == NULL)
{
- syslog (LOG_ERR, MODULE_NAME": fopen(%s) failed: %s",
+ syslog (LOG_ERR, "sensors plugin: fopen(%s) failed: %s",
conffile, strerror(errno));
return;
}
fclose (fh);
if (status != 0)
{
- syslog (LOG_ERR, MODULE_NAME": Cannot initialize sensors. "
+ syslog (LOG_ERR, "sensors plugin: Cannot initialize sensors. "
"Data will not be collected.");
return;
}
DBG ("Adding feature: %s-%s-%s",
chip->prefix,
- sensor_type_prefix[known_features[i].type],
+ sensor_to_type[known_features[i].type],
data->name);
if ((new_feature = (featurelist_t *) malloc (sizeof (featurelist_t))) == NULL)
{
DBG ("malloc: %s", strerror (errno));
- syslog (LOG_ERR, MODULE_NAME": malloc: %s",
+ syslog (LOG_ERR, "sensors plugin: malloc: %s",
strerror (errno));
break;
}
if (first_feature == NULL)
{
sensors_cleanup ();
- syslog (LOG_INFO, MODULE_NAME": lm_sensors reports no features. "
- "Data will not be collected.");
+ syslog (LOG_INFO, "sensors plugin: lm_sensors reports no "
+ "features. Data will not be collected.");
}
} /* void sensors_load_conf */
-#endif /* if SENSORS_HAVE_READ */
-static void collectd_sensors_init (void)
+static int sensors_shutdown (void)
{
- return;
-}
-
-static void sensors_shutdown (void)
-{
-#if SENSORS_HAVE_READ
sensors_free_features ();
-#endif /* if SENSORS_HAVE_READ */
-
- if (NULL != sensor_list)
- ignorelist_free (sensor_list);
-}
-
-static void sensors_voltage_write (char *host, char *inst, char *val)
-{
- char file[BUFSIZE];
- int status;
-
- /* skip ignored in our config */
- if ((NULL != sensor_list) && ignorelist_match (sensor_list, inst))
- return;
-
- /* extended sensor naming */
- if(sensor_extended_naming)
- status = snprintf (file, BUFSIZE, extended_filename_format, inst);
- else
- status = snprintf (file, BUFSIZE, old_filename_format, inst);
-
- if ((status < 1) || (status >= BUFSIZE))
- return;
+ ignorelist_free (sensor_list);
- rrd_update_file (host, file, val, sensor_voltage_ds_def, sensor_voltage_ds_num);
-}
-
-static void sensors_write (char *host, char *inst, char *val)
-{
- char file[BUFSIZE];
- int status;
-
- /* skip ignored in our config */
- if ((NULL != sensor_list) && ignorelist_match (sensor_list, inst))
- return;
-
- /* extended sensor naming */
- if (sensor_extended_naming)
- status = snprintf (file, BUFSIZE, extended_filename_format, inst);
- else
- status = snprintf (file, BUFSIZE, old_filename_format, inst);
-
- if ((status < 1) || (status >= BUFSIZE))
- return;
-
- rrd_update_file (host, file, val, ds_def, ds_num);
-}
+ return (0);
+} /* int sensors_shutdown */
-#if SENSORS_HAVE_READ
-static void sensors_submit (const char *feat_name,
- const char *chip_prefix, double value, int type)
+static void sensors_submit (const char *plugin_instance,
+ const char *type, const char *type_instance,
+ double val)
{
- char buf[BUFSIZE];
- char inst[BUFSIZE];
+ value_t values[1];
+ value_list_t vl = VALUE_LIST_INIT;
- if (snprintf (inst, BUFSIZE, "%s-%s", chip_prefix, feat_name)
- >= BUFSIZE)
+ if (ignorelist_match (sensor_list, type_instance))
return;
- /* skip ignored in our config */
- if ((NULL != sensor_list) && ignorelist_match (sensor_list, inst))
- return;
+ values[0].gauge = val;
- if (snprintf (buf, BUFSIZE, "%u:%.3f", (unsigned int) curtime,
- value) >= BUFSIZE)
- return;
+ vl.values = values;
+ vl.values_len = 1;
+ vl.time = time (NULL);
+ strcpy (vl.host, hostname);
+ strcpy (vl.plugin, "sensors");
+ strcpy (vl.plugin_instance, plugin_instance);
+ strcpy (vl.type_instance, type_instance);
- if (type == SENSOR_TYPE_VOLTAGE)
- {
- DBG ("%s: %s/%s, %s", MODULE_NAME_VOLTAGE,
- sensor_type_prefix[type], inst, buf);
- plugin_submit (MODULE_NAME_VOLTAGE, inst, buf);
- }
- else
- {
- DBG ("%s: %s/%s, %s", MODULE_NAME,
- sensor_type_prefix[type], inst, buf);
- plugin_submit (MODULE_NAME, inst, buf);
- }
-}
+ plugin_dispatch_values (type, &vl);
+} /* void sensors_submit */
-static void sensors_read (void)
+static int sensors_read (void)
{
featurelist_t *feature;
double value;
- char chip_fullprefix[BUFSIZE];
+
+ char plugin_instance[DATA_MAX_NAME_LEN];
+ char type_instance[DATA_MAX_NAME_LEN];
sensors_load_conf ();
if (sensors_get_feature (*feature->chip, feature->data->number, &value) < 0)
continue;
- if (sensor_extended_naming)
+ /* full chip name logic borrowed from lm_sensors */
+ if (feature->chip->bus == SENSORS_CHIP_NAME_BUS_ISA)
{
- /* full chip name logic borrowed from lm_sensors */
- if (feature->chip->bus == SENSORS_CHIP_NAME_BUS_ISA)
- {
- if (snprintf (chip_fullprefix, BUFSIZE, "%s-isa-%04x/%s",
- feature->chip->prefix,
- feature->chip->addr,
- sensor_type_prefix[feature->type])
- >= BUFSIZE)
- continue;
- }
- else if (feature->chip->bus == SENSORS_CHIP_NAME_BUS_DUMMY)
- {
- if (snprintf (chip_fullprefix, BUFSIZE, "%s-%s-%04x/%s",
- feature->chip->prefix,
- feature->chip->busname,
- feature->chip->addr,
- sensor_type_prefix[feature->type])
- >= BUFSIZE)
- continue;
- }
- else
- {
- if (snprintf (chip_fullprefix, BUFSIZE, "%s-i2c-%d-%02x/%s",
- feature->chip->prefix,
- feature->chip->bus,
- feature->chip->addr,
- sensor_type_prefix[feature->type])
- >= BUFSIZE)
- continue;
- }
-
- sensors_submit (feature->data->name,
- chip_fullprefix,
- value, feature->type);
+ if (snprintf (plugin_instance, DATA_MAX_NAME_LEN, "%s-isa-%04x",
+ feature->chip->prefix,
+ feature->chip->addr)
+ >= 512)
+ continue;
+ }
+ else if (feature->chip->bus == SENSORS_CHIP_NAME_BUS_DUMMY)
+ {
+ if (snprintf (plugin_instance, 512, "%s-%s-%04x",
+ feature->chip->prefix,
+ feature->chip->busname,
+ feature->chip->addr)
+ >= 512)
+ continue;
}
else
{
- sensors_submit (feature->data->name,
- feature->chip->prefix,
- value, feature->type);
+ if (snprintf (plugin_instance, 512, "%s-i2c-%d-%02x",
+ feature->chip->prefix,
+ feature->chip->bus,
+ feature->chip->addr)
+ >= 512)
+ continue;
}
+
+ strncpy (type_instance, feature->data->name, DATA_MAX_NAME_LEN);
+
+ sensors_submit (plugin_instance,
+ sensor_to_type[feature->type],
+ type_instance,
+ value);
} /* for feature = first_feature .. NULL */
-} /* void sensors_read */
-#else
-# define sensors_read NULL
+
+ return (0);
+} /* int sensors_read */
#endif /* SENSORS_HAVE_READ */
void module_register (void)
{
- plugin_register (MODULE_NAME, collectd_sensors_init, sensors_read, sensors_write);
- plugin_register (MODULE_NAME_VOLTAGE, NULL, NULL, sensors_voltage_write);
- plugin_register_shutdown (MODULE_NAME, sensors_shutdown);
- cf_register (MODULE_NAME, sensors_config, config_keys, config_keys_num);
-}
+ plugin_register_data_set (&fanspeed_ds);
+ plugin_register_data_set (&temperature_ds);
+ plugin_register_data_set (&voltage_ds);
-#undef BUFSIZE
-#undef MODULE_NAME
+#if SENSORS_HAVE_READ
+ plugin_register_config ("sensors", sensors_config,
+ config_keys, config_keys_num);
+ plugin_register_read ("sensors", sensors_read);
+ plugin_register_shutdown ("sensors", sensors_shutdown);
+#endif
+} /* void module_register */
#include "common.h"
#include "plugin.h"
-#define MODULE_NAME "serial"
-
#if defined(KERNEL_LINUX)
# define SERIAL_HAVE_READ 1
#else
# define SERIAL_HAVE_READ 0
#endif
-static char *serial_filename_template = "serial-%s.rrd";
-
-static char *ds_def[] =
+static data_source_t octets_dsrc[2] =
{
- "DS:incoming:COUNTER:"COLLECTD_HEARTBEAT":0:U",
- "DS:outgoing:COUNTER:"COLLECTD_HEARTBEAT":0:U",
- NULL
+ {"rx", DS_TYPE_COUNTER, 0, 4294967295.0},
+ {"tx", DS_TYPE_COUNTER, 0, 4294967295.0}
};
-static int ds_num = 2;
-static void serial_init (void)
+static data_set_t octets_ds =
{
- return;
-}
+ "serial_octets", 2, octets_dsrc
+};
-static void serial_write (char *host, char *inst, char *val)
+#if SERIAL_HAVE_READ
+static void serial_submit (const char *type_instance,
+ counter_t rx, counter_t tx)
{
- char file[512];
- int status;
+ value_t values[2];
+ value_list_t vl = VALUE_LIST_INIT;
- status = snprintf (file, 512, serial_filename_template, inst);
- if (status < 1)
- return;
- else if (status >= 512)
- return;
+ values[0].counter = rx;
+ values[1].counter = tx;
- rrd_update_file (host, file, val, ds_def, ds_num);
-}
+ vl.values = values;
+ vl.values_len = 2;
+ vl.time = time (NULL);
+ strcpy (vl.host, hostname);
+ strcpy (vl.plugin, "serial");
+ strncpy (vl.type_instance, type_instance,
+ sizeof (vl.type_instance));
-#if SERIAL_HAVE_READ
-#define BUFSIZE 512
-static void serial_submit (char *device,
- unsigned long long incoming,
- unsigned long long outgoing)
-{
- char buf[BUFSIZE];
-
- if (snprintf (buf, BUFSIZE, "%u:%llu:%llu", (unsigned int) curtime,
- incoming, outgoing) >= BUFSIZE)
- return;
-
- plugin_submit (MODULE_NAME, device, buf);
+ plugin_dispatch_values ("serial_octets", &vl);
}
-#undef BUFSIZE
-static void serial_read (void)
+static int serial_read (void)
{
#ifdef KERNEL_LINUX
-
FILE *fh;
char buffer[1024];
- unsigned long long incoming, outgoing;
+
+ counter_t rx = 0;
+ counter_t tx = 0;
char *fields[16];
int i, numfields;
(fh = fopen ("/proc/tty/driver/ttyS", "r")) == NULL)
{
syslog (LOG_WARNING, "serial: fopen: %s", strerror (errno));
- return;
+ return (-1);
}
- while (fgets (buffer, 1024, fh) != NULL)
+ while (fgets (buffer, sizeof (buffer), fh) != NULL)
{
int have_rx = 0, have_tx = 0;
- /* stupid compiler:
- * serial.c:87: warning: 'incoming' may be used uninitialized in this function
- * serial.c:87: warning: 'outgoing' may be used uninitialized in this function
- */
- incoming = 0ULL;
- outgoing = 0ULL;
-
numfields = strsplit (buffer, fields, 16);
if (numfields < 6)
if (strncmp (fields[i], "tx:", 3) == 0)
{
- outgoing = atoll (fields[i] + 3);
+ tx = atoll (fields[i] + 3);
have_tx++;
}
else if (strncmp (fields[i], "rx:", 3) == 0)
{
- incoming = atoll (fields[i] + 3);
+ rx = atoll (fields[i] + 3);
have_rx++;
}
}
if ((have_rx == 0) || (have_tx == 0))
continue;
- serial_submit (fields[0], incoming, outgoing);
+ serial_submit (fields[0], rx, tx);
}
fclose (fh);
+ return (0);
#endif /* KERNEL_LINUX */
-}
-#else
-# define serial_read NULL
+} /* int serial_read */
#endif /* SERIAL_HAVE_READ */
void module_register (void)
{
- plugin_register (MODULE_NAME, serial_init, serial_read, serial_write);
-}
+ plugin_register_data_set (&octets_ds);
-#undef MODULE_NAME
+#if SERIAL_HAVE_READ
+ plugin_register_read ("serial", serial_read);
+#endif /* SERIAL_HAVE_READ */
+}
/**
* collectd - src/swap.c
- * Copyright (C) 2005,2006 Florian octo Forster
+ * Copyright (C) 2005-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; either version 2 of the License, or (at your
- * option) any later version.
+ * 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
# include <kvm.h>
#endif
-#define MODULE_NAME "swap"
-
#if KERNEL_LINUX || HAVE_LIBKSTAT || defined(VM_SWAPUSAGE) || HAVE_LIBKVM || HAVE_LIBSTATGRAB
# define SWAP_HAVE_READ 1
#else
#undef MAX
#define MAX(x,y) ((x) > (y) ? (x) : (y))
-static char *swap_file = "swap.rrd";
+static data_source_t data_source[1] =
+{
+ {"value", DS_TYPE_GAUGE, 0, 1099511627776.0}
+};
-/* 1099511627776 == 1TB ought to be enough for anyone ;) */
-static char *ds_def[] =
+static data_set_t data_set =
{
- "DS:used:GAUGE:"COLLECTD_HEARTBEAT":0:1099511627776",
- "DS:free:GAUGE:"COLLECTD_HEARTBEAT":0:1099511627776",
- "DS:cached:GAUGE:"COLLECTD_HEARTBEAT":0:1099511627776",
- "DS:resv:GAUGE:"COLLECTD_HEARTBEAT":0:1099511627776",
- NULL
+ "swap", 1, data_source
};
-static int ds_num = 4;
+#if SWAP_HAVE_READ
#if KERNEL_LINUX
/* No global variables */
/* #endif KERNEL_LINUX */
/* No global variables */
#endif /* HAVE_LIBSTATGRAB */
-static void swap_init (void)
+static int swap_init (void)
{
#if KERNEL_LINUX
/* No init stuff */
== NULL)
{
syslog (LOG_ERR, "swap plugin: kvm_open failed.");
- return;
+ return (-1);
}
/* #endif HAVE_LIBKVM */
/* No init stuff */
#endif /* HAVE_LIBSTATGRAB */
- return;
+ return (0);
}
-static void swap_write (char *host, char *inst, char *val)
+static void swap_submit (const char *type_instance, double value)
{
- rrd_update_file (host, swap_file, val, ds_def, ds_num);
-}
+ value_t values[1];
+ value_list_t vl = VALUE_LIST_INIT;
-#if SWAP_HAVE_READ
-static void swap_submit (unsigned long long swap_used,
- unsigned long long swap_free,
- unsigned long long swap_cached,
- unsigned long long swap_resv)
-{
- char buffer[512];
+ values[0].gauge = value;
- if (snprintf (buffer, 512, "%u:%llu:%llu:%llu:%llu", (unsigned int) curtime,
- swap_used, swap_free, swap_cached, swap_resv) >= 512)
- return;
+ vl.values = values;
+ vl.values_len = 1;
+ vl.time = time (NULL);
+ strcpy (vl.host, hostname);
+ strcpy (vl.plugin, "swap");
+ strncpy (vl.type_instance, type_instance, sizeof (vl.type_instance));
- plugin_submit (MODULE_NAME, "-", buffer);
-}
+ plugin_dispatch_values ("swap", &vl);
+} /* void swap_submit */
-static void swap_read (void)
+static int swap_read (void)
{
#if KERNEL_LINUX
FILE *fh;
if ((fh = fopen ("/proc/meminfo", "r")) == NULL)
{
syslog (LOG_WARNING, "memory: fopen: %s", strerror (errno));
- return;
+ return (-1);
}
while (fgets (buffer, 1024, fh) != NULL)
syslog (LOG_WARNING, "memory: fclose: %s", strerror (errno));
if ((swap_total == 0LL) || ((swap_free + swap_cached) > swap_total))
- return;
+ return (-1);
swap_used = swap_total - (swap_free + swap_cached);
- swap_submit (swap_used, swap_free, swap_cached, -1LL);
+ swap_submit ("used", swap_used);
+ swap_submit ("free", swap_free);
+ swap_submit ("cached", swap_cached);
/* #endif KERNEL_LINUX */
#elif HAVE_LIBKSTAT
{
syslog (LOG_ERR, "swap plugin: swapctl failed: %s",
strerror (errno));
- return;
+ return (-1);
}
/*
swap_avail = ai.ani_max - ai.ani_resv;
swap_avail *= pagesize;
- swap_submit (swap_alloc, swap_avail, -1LL, swap_resv - swap_alloc);
+ swap_submit ("used", swap_alloc);
+ swap_submit ("free", swap_avail);
+ swap_submit ("reserved", swap_resv - swap_alloc);
/* #endif HAVE_LIBKSTAT */
#elif defined(VM_SWAPUSAGE)
sw_usage_len = sizeof (struct xsw_usage);
if (sysctl (mib, mib_len, &sw_usage, &sw_usage_len, NULL, 0) != 0)
- return;
+ return (-1);
/* The returned values are bytes. */
- swap_submit (sw_usage.xsu_used, sw_usage.xsu_avail, -1LL, -1LL);
+ swap_submit ("used", sw_usage.xsu_used);
+ swap_submit ("free", sw_usage.xsu_avail);
/* #endif VM_SWAPUSAGE */
#elif HAVE_LIBKVM
unsigned long long total;
if (kvm_obj == NULL)
- return;
+ return (-1);
/* only one structure => only get the grand total, no details */
status = kvm_getswapinfo (kvm_obj, &data_s, 1, 0);
if (status == -1)
- return;
+ return (-1);
total = (unsigned long long) data_s.ksw_total;
used = (unsigned long long) data_s.ksw_used;
free = total - used;
- swap_submit (used, free, -1LL, -1LL);
+ swap_submit ("used", used);
+ swap_submit ("free", free);
/* #endif HAVE_LIBKVM */
#elif HAVE_LIBSTATGRAB
sg_swap_stats *swap;
- if ((swap = sg_get_swap_stats ()) != NULL)
- swap_submit (swap->used, swap->free, -1LL, -1LL);
+ swap = sg_get_swap_stats ();
+
+ if (swap == NULL)
+ return (-1);
+
+ swap_submit ("used", swap->used);
+ swap_submit ("free", swap->free);
#endif /* HAVE_LIBSTATGRAB */
-}
-#else
-# define swap_read NULL
+
+ return (0);
+} /* int swap_read */
#endif /* SWAP_HAVE_READ */
void module_register (void)
{
- plugin_register (MODULE_NAME, swap_init, swap_read, swap_write);
-}
+ plugin_register_data_set (&data_set);
-#undef MODULE_NAME
+#if SWAP_HAVE_READ
+ plugin_register_init ("swap", swap_init);
+ plugin_register_read ("swap", swap_read);
+#endif /* SWAP_HAVE_READ */
+}
#include "common.h"
#include "plugin.h"
-#define MODULE_NAME "tape"
-
#if defined(HAVE_LIBKSTAT)
# define TAPE_HAVE_READ 1
#else
# define TAPE_HAVE_READ 0
#endif
-static char *tape_filename_template = "tape-%s.rrd";
+/* 2^34 = 17179869184 = ~17.2GByte/s */
+static data_source_t octets_dsrc[2] =
+{
+ {"read", DS_TYPE_COUNTER, 0, 17179869183.0},
+ {"write", DS_TYPE_COUNTER, 0, 17179869183.0}
+};
+
+static data_set_t octets_ds =
+{
+ "tape_octets", 2, octets_dsrc
+};
+
+static data_source_t operations_dsrc[2] =
+{
+ {"read", DS_TYPE_COUNTER, 0, 4294967295.0},
+ {"write", DS_TYPE_COUNTER, 0, 4294967295.0}
+};
+
+static data_set_t operations_ds =
+{
+ "tape_ops", 2, operations_dsrc
+};
+
+static data_source_t merged_dsrc[2] =
+{
+ {"read", DS_TYPE_COUNTER, 0, 4294967295.0},
+ {"write", DS_TYPE_COUNTER, 0, 4294967295.0}
+};
+
+static data_set_t merged_ds =
+{
+ "tape_merged", 2, merged_dsrc
+};
+
+/* max is 1000000us per second. */
+static data_source_t time_dsrc[2] =
+{
+ {"read", DS_TYPE_COUNTER, 0, 1000000.0},
+ {"write", DS_TYPE_COUNTER, 0, 1000000.0}
+};
-/* 104857600 == 100 MB */
-static char *tape_ds_def[] =
+static data_set_t time_ds =
{
- "DS:rcount:COUNTER:"COLLECTD_HEARTBEAT":0:U",
- "DS:rmerged:COUNTER:"COLLECTD_HEARTBEAT":0:U",
- "DS:rbytes:COUNTER:"COLLECTD_HEARTBEAT":0:U",
- "DS:rtime:COUNTER:"COLLECTD_HEARTBEAT":0:U",
- "DS:wcount:COUNTER:"COLLECTD_HEARTBEAT":0:U",
- "DS:wmerged:COUNTER:"COLLECTD_HEARTBEAT":0:U",
- "DS:wbytes:COUNTER:"COLLECTD_HEARTBEAT":0:U",
- "DS:wtime:COUNTER:"COLLECTD_HEARTBEAT":0:U",
- NULL
+ "tape_time", 2, time_dsrc
};
-static int tape_ds_num = 8;
+#if TAPE_HAVE_READ
#if defined(HAVE_LIBKSTAT)
#define MAX_NUMTAPE 256
extern kstat_ctl_t *kc;
static int numtape = 0;
#endif /* HAVE_LIBKSTAT */
-static void tape_init (void)
+static int tape_init (void)
{
#ifdef HAVE_LIBKSTAT
kstat_t *ksp_chain;
numtape = 0;
if (kc == NULL)
- return;
+ return (-1);
for (numtape = 0, ksp_chain = kc->kc_chain;
(numtape < MAX_NUMTAPE) && (ksp_chain != NULL);
}
#endif
- return;
+ return (0);
}
-static void tape_write (char *host, char *inst, char *val)
+static void tape_submit (const char *plugin_instance,
+ const char *type,
+ counter_t read, counter_t write)
{
- char file[512];
- int status;
+ value_t values[2];
+ value_list_t vl = VALUE_LIST_INIT;
- status = snprintf (file, 512, tape_filename_template, inst);
- if (status < 1)
- return;
- else if (status >= 512)
- return;
-
- rrd_update_file (host, file, val, tape_ds_def, tape_ds_num);
-}
+ values[0].counter = read;
+ values[1].counter = write;
+ vl.values = values;
+ vl.values_len = 2;
+ vl.time = time (NULL);
+ strcpy (vl.host, hostname);
+ strcpy (vl.plugin, "tape");
+ strncpy (vl.plugin_instance, plugin_instance,
+ sizeof (vl.plugin_instance));
-#if TAPE_HAVE_READ
-#define BUFSIZE 512
-static void tape_submit (char *tape_name,
- unsigned long long read_count,
- unsigned long long read_merged,
- unsigned long long read_bytes,
- unsigned long long read_time,
- unsigned long long write_count,
- unsigned long long write_merged,
- unsigned long long write_bytes,
- unsigned long long write_time)
+ plugin_dispatch_values (type, &vl);
+} /* void tape_submit */
-{
- char buf[BUFSIZE];
-
- if (snprintf (buf, BUFSIZE, "%u:%llu:%llu:%llu:%llu:%llu:%llu:%llu:%llu",
- (unsigned int) curtime,
- read_count, read_merged, read_bytes, read_time,
- write_count, write_merged, write_bytes,
- write_time) >= BUFSIZE)
- return;
-
- plugin_submit (MODULE_NAME, tape_name, buf);
-}
-
-#undef BUFSIZE
-
-static void tape_read (void)
+static int tape_read (void)
{
#if defined(HAVE_LIBKSTAT)
int i;
if (kc == NULL)
- return;
+ return (-1);
+
+ if (numtape <= 0)
+ return (-1);
for (i = 0; i < numtape; i++)
{
continue;
if (strncmp (ksp[i]->ks_class, "tape", 4) == 0)
- tape_submit (ksp[i]->ks_name,
- kio.reads, 0LL, kio.nread, kio.rtime,
- kio.writes, 0LL, kio.nwritten, kio.wtime);
+ {
+ tape_submit (ksp[i]->ks_name, "tape_octets", kio.reads, kio.writes);
+ tape_submit (ksp[i]->ks_name, "tape_ops", kio.nreads, kio.nwrites);
+ /* FIXME: Convert this to microseconds if necessary */
+ tape_submit (ksp[i]->ks_name, "tape_time", kio.rtime, kio.wtime);
+ }
}
#endif /* defined(HAVE_LIBKSTAT) */
+
+ return (0);
}
-#else
-# define tape_read NULL
#endif /* TAPE_HAVE_READ */
void module_register (void)
{
- plugin_register (MODULE_NAME, tape_init, tape_read, tape_write);
-}
+ plugin_register_data_set (&octets_ds);
+ plugin_register_data_set (&operations_ds);
+ plugin_register_data_set (&merged_ds);
+ plugin_register_data_set (&time_ds);
-#undef MODULE_NAME
+#if TAPE_HAVE_READ
+ plugin_register_init ("tape", tape_init);
+ plugin_register_read ("tape", tape_read);
+#endif /* TAPE_HAVE_READ */
+}
/**
* collectd - src/traffic.c
- * Copyright (C) 2005,2006 Florian octo Forster
+ * Copyright (C) 2005-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; either version 2 of the License, or (at your
- * option) any later version.
+ * 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
# include <ifaddrs.h>
#endif
-#define MODULE_NAME "traffic"
-
/*
* Various people have reported problems with `getifaddrs' and varying versions
* of `glibc'. That's why it's disabled by default. Since more statistics are
# define TRAFFIC_HAVE_READ 0
#endif
-#define BUFSIZE 512
-
/*
* (Module-)Global variables
*/
-/* TODO: Move this to `interface-%s/<blah>.rrd' in version 4. */
-static char *bytes_file = "traffic-%s.rrd";
-static char *packets_file = "interface-%s/if_packets.rrd";
-static char *errors_file = "interface-%s/if_errors.rrd";
-/* TODO: Maybe implement multicast and broadcast counters */
+/* 2^32 = 4294967296 = ~4.2GByte/s = ~34GBit/s */
+static data_source_t octets_dsrc[2] =
+{
+ {"rx", DS_TYPE_COUNTER, 0, 4294967295.0},
+ {"tx", DS_TYPE_COUNTER, 0, 4294967295.0}
+};
-static char *config_keys[] =
+static data_set_t octets_ds =
{
- "Interface",
- "IgnoreSelected",
- NULL
+ "if_octets", 2, octets_dsrc
};
-static int config_keys_num = 2;
-static char *bytes_ds_def[] =
+static data_source_t packets_dsrc[2] =
{
- "DS:incoming:COUNTER:"COLLECTD_HEARTBEAT":0:U",
- "DS:outgoing:COUNTER:"COLLECTD_HEARTBEAT":0:U",
- NULL
+ {"rx", DS_TYPE_COUNTER, 0, 4294967295.0},
+ {"tx", DS_TYPE_COUNTER, 0, 4294967295.0}
};
-static int bytes_ds_num = 2;
-static char *packets_ds_def[] =
+static data_set_t packets_ds =
{
- "DS:rx:COUNTER:"COLLECTD_HEARTBEAT":0:U",
- "DS:tx:COUNTER:"COLLECTD_HEARTBEAT":0:U",
- NULL
+ "if_packets", 2, packets_dsrc
};
-static int packets_ds_num = 2;
-static char *errors_ds_def[] =
+static data_source_t errors_dsrc[2] =
{
- "DS:rx:COUNTER:"COLLECTD_HEARTBEAT":0:U",
- "DS:tx:COUNTER:"COLLECTD_HEARTBEAT":0:U",
+ {"rx", DS_TYPE_COUNTER, 0, 4294967295.0},
+ {"tx", DS_TYPE_COUNTER, 0, 4294967295.0}
+};
+
+static data_set_t errors_ds =
+{
+ "if_errors", 2, errors_dsrc
+};
+
+static const char *config_keys[] =
+{
+ "Interface",
+ "IgnoreSelected",
NULL
};
-static int errors_ds_num = 2;
+static int config_keys_num = 2;
static char **if_list = NULL;
static int if_list_num = 0;
static int numif = 0;
#endif /* HAVE_LIBKSTAT */
-static int traffic_config (char *key, char *value)
+static int interface_config (const char *key, const char *value)
{
char **temp;
return (0);
}
-static void traffic_init (void)
+#if HAVE_LIBKSTAT
+static int traffic_init (void)
{
-#if HAVE_GETIFADDRS
- /* nothing */
-/* #endif HAVE_GETIFADDRS */
-
-#elif KERNEL_LINUX
- /* nothing */
-/* #endif KERNEL_LINUX */
-
-#elif HAVE_LIBKSTAT
+#if HAVE_LIBKSTAT
kstat_t *ksp_chain;
unsigned long long val;
numif = 0;
if (kc == NULL)
- return;
+ return (-1);
for (numif = 0, ksp_chain = kc->kc_chain;
(numif < MAX_NUMIF) && (ksp_chain != NULL);
continue;
ksp[numif++] = ksp_chain;
}
-/* #endif HAVE_LIBKSTAT */
-
-#elif HAVE_LIBSTATG
- /* nothing */
-#endif /* HAVE_LIBSTATG */
+#endif /* HAVE_LIBKSTAT */
- return;
-}
+ return (0);
+} /* int traffic_init */
+#endif /* HAVE_LIBKSTAT */
/*
* Check if this interface/instance should be ignored. This is called from
if (strcasecmp (interface, if_list[i]) == 0)
return (if_list_action);
return (1 - if_list_action);
-}
-
-static void generic_write (char *host, char *inst, char *val,
- char *file_template,
- char **ds_def, int ds_num)
-{
- char file[512];
- int status;
-
- if (check_ignore_if (inst))
- return;
-
- status = snprintf (file, BUFSIZE, file_template, inst);
- if (status < 1)
- return;
- else if (status >= 512)
- return;
-
- rrd_update_file (host, file, val, ds_def, ds_num);
-}
-
-static void bytes_write (char *host, char *inst, char *val)
-{
- generic_write (host, inst, val, bytes_file, bytes_ds_def, bytes_ds_num);
-}
-
-static void packets_write (char *host, char *inst, char *val)
-{
- generic_write (host, inst, val, packets_file, packets_ds_def, packets_ds_num);
-}
-
-static void errors_write (char *host, char *inst, char *val)
-{
- generic_write (host, inst, val, errors_file, errors_ds_def, errors_ds_num);
-}
+} /* int check_ignore_if */
#if TRAFFIC_HAVE_READ
-static void bytes_submit (char *dev,
- unsigned long long rx,
- unsigned long long tx)
-{
- char buf[512];
- int status;
-
- if (check_ignore_if (dev))
- return;
-
- status = snprintf (buf, 512, "%u:%lld:%lld",
- (unsigned int) curtime,
- rx, tx);
- if ((status >= 512) || (status < 1))
- return;
-
- plugin_submit (MODULE_NAME, dev, buf);
-}
-
-#if HAVE_GETIFADDRS || KERNEL_LINUX || HAVE_LIBKSTAT
-static void packets_submit (char *dev,
+static void if_submit (const char *dev, const char *type,
unsigned long long rx,
unsigned long long tx)
{
- char buf[512];
- int status;
+ value_t values[2];
+ value_list_t vl = VALUE_LIST_INIT;
if (check_ignore_if (dev))
return;
- status = snprintf (buf, 512, "%u:%lld:%lld",
- (unsigned int) curtime,
- rx, tx);
- if ((status >= 512) || (status < 1))
- return;
- plugin_submit ("if_packets", dev, buf);
-}
-
-static void errors_submit (char *dev,
- unsigned long long rx,
- unsigned long long tx)
-{
- char buf[512];
- int status;
+ values[0].counter = rx;
+ values[1].counter = tx;
- if (check_ignore_if (dev))
- return;
+ vl.values = values;
+ vl.values_len = 2;
+ vl.time = time (NULL);
+ strcpy (vl.host, hostname);
+ strcpy (vl.plugin, "interface");
+ strncpy (vl.type_instance, dev, sizeof (vl.type_instance));
- status = snprintf (buf, 512, "%u:%lld:%lld",
- (unsigned int) curtime,
- rx, tx);
- if ((status >= 512) || (status < 1))
- return;
- plugin_submit ("if_errors", dev, buf);
-}
-#endif /* HAVE_GETIFADDRS || KERNEL_LINUX || HAVE_LIBKSTAT */
+ plugin_dispatch_values (type, &vl);
+} /* void if_submit */
-static void traffic_read (void)
+static int traffic_read (void)
{
#if HAVE_GETIFADDRS
struct ifaddrs *if_list;
struct IFA_DATA *if_data;
if (getifaddrs (&if_list) != 0)
- return;
+ return (-1);
for (if_ptr = if_list; if_ptr != NULL; if_ptr = if_ptr->ifa_next)
{
if ((if_data = (struct IFA_DATA *) if_ptr->ifa_data) == NULL)
continue;
- bytes_submit (if_ptr->ifa_name,
+ if_submit (if_ptr->ifa_name, "if_octets",
if_data->IFA_RX_BYTES,
if_data->IFA_TX_BYTES);
- packets_submit (if_ptr->ifa_name,
+ if_submit (if_ptr->ifa_name, "if_packets",
if_data->IFA_RX_PACKT,
if_data->IFA_TX_PACKT);
- errors_submit (if_ptr->ifa_name,
+ if_submit (if_ptr->ifa_name, "if_errors",
if_data->IFA_RX_ERROR,
if_data->IFA_TX_ERROR);
}
if ((fh = fopen ("/proc/net/dev", "r")) == NULL)
{
syslog (LOG_WARNING, "traffic: fopen: %s", strerror (errno));
- return;
+ return (-1);
}
while (fgets (buffer, 1024, fh) != NULL)
incoming = atoll (fields[0]);
outgoing = atoll (fields[8]);
- bytes_submit (device, incoming, outgoing);
+ if_submit (device, "if_octets", incoming, outgoing);
incoming = atoll (fields[1]);
outgoing = atoll (fields[9]);
- packets_submit (device, incoming, outgoing);
+ if_submit (device, "if_packets", incoming, outgoing);
incoming = atoll (fields[2]);
outgoing = atoll (fields[10]);
- errors_submit (device, incoming, outgoing);
+ if_submit (device, "if_errors", incoming, outgoing);
}
fclose (fh);
rx = get_kstat_value (ksp[i], "rbytes");
tx = get_kstat_value (ksp[i], "obytes");
if ((rx != -1LL) || (tx != -1LL))
- bytes_submit (ksp[i]->ks_name, rx, tx);
+ if_submit (ksp[i]->ks_name, "if_octets", rx, tx);
rx = get_kstat_value (ksp[i], "ipackets");
tx = get_kstat_value (ksp[i], "opackets");
if ((rx != -1LL) || (tx != -1LL))
- packets_submit (ksp[i]->ks_name, rx, tx);
+ if_submit (ksp[i]->ks_name, "if_packets", rx, tx);
rx = get_kstat_value (ksp[i], "ierrors");
tx = get_kstat_value (ksp[i], "oerrors");
if ((rx != -1LL) || (tx != -1LL))
- errors_submit (ksp[i]->ks_name, rx, tx);
+ if_submit (ksp[i]->ks_name, "if_errors", rx, tx);
}
/* #endif HAVE_LIBKSTAT */
ios = sg_get_network_io_stats (&num);
for (i = 0; i < num; i++)
- bytes_submit (ios[i].interface_name, ios[i].rx, ios[i].tx);
+ if_submit (ios[i].interface_name, "if_octets", ios[i].rx, ios[i].tx);
#endif /* HAVE_LIBSTATGRAB */
-}
-#else
-#define traffic_read NULL
+
+ return (0);
+} /* int traffic_read */
#endif /* TRAFFIC_HAVE_READ */
void module_register (void)
{
- plugin_register (MODULE_NAME, traffic_init, traffic_read, bytes_write);
- plugin_register ("if_packets", NULL, NULL, packets_write);
- plugin_register ("if_errors", NULL, NULL, errors_write);
- cf_register (MODULE_NAME, traffic_config, config_keys, config_keys_num);
-}
+ plugin_register_data_set (&octets_ds);
+ plugin_register_data_set (&packets_ds);
+ plugin_register_data_set (&errors_ds);
+
+ plugin_register_config ("interface", interface_config,
+ config_keys, config_keys_num);
-#undef BUFSIZE
-#undef MODULE_NAME
+#if HAVE_LIBKSTAT
+ plugin_register_init ("interface", traffic_init);
+#endif
+
+#if TRAFFIC_HAVE_READ
+ plugin_register_read ("interface", traffic_read);
+#endif
+}
--- /dev/null
+/**
+ * collectd - src/unixsock.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
+ *
+ * Author:
+ * Florian octo Forster <octo at verplant.org>
+ **/
+
+#include "collectd.h"
+#include "common.h"
+#include "plugin.h"
+#include "configfile.h"
+#include "utils_debug.h"
+
+/* Folks without pthread will need to disable this plugin. */
+#include <pthread.h>
+
+#include <sys/socket.h>
+#include <sys/un.h>
+#include <sys/poll.h>
+
+#include <grp.h>
+
+#ifndef UNIX_PATH_MAX
+# define UNIX_PATH_MAX sizeof (((struct sockaddr_un *)0)->sun_path)
+#endif
+
+#define US_DEFAULT_PATH PREFIX"/var/run/"PACKAGE_NAME"-unixsock"
+
+/*
+ * Private data structures
+ */
+/* linked list of cached values */
+typedef struct value_cache_s
+{
+ char name[4*DATA_MAX_NAME_LEN];
+ int values_num;
+ gauge_t *gauge;
+ counter_t *counter;
+ const data_set_t *ds;
+ time_t time;
+ struct value_cache_s *next;
+} value_cache_t;
+
+/*
+ * Private variables
+ */
+/* valid configuration file keys */
+static const char *config_keys[] =
+{
+ "SocketFile",
+ "SocketGroup",
+ "SocketPerms",
+ NULL
+};
+static int config_keys_num = 3;
+
+/* socket configuration */
+static int sock_fd = -1;
+static char *sock_file = NULL;
+static char *sock_group = NULL;
+static int sock_perms = S_IRWXU | S_IRWXG;
+
+static pthread_t listen_thread = (pthread_t) 0;
+
+/* Linked list and auxilliary variables for saving values */
+static value_cache_t *cache_head = NULL;
+static pthread_mutex_t cache_lock = PTHREAD_MUTEX_INITIALIZER;
+static unsigned int cache_oldest = UINT_MAX;
+
+/*
+ * Functions
+ */
+static value_cache_t *cache_search (const char *name)
+{
+ value_cache_t *vc;
+
+ for (vc = cache_head; vc != NULL; vc = vc->next)
+ {
+ if (strcmp (vc->name, name) == 0)
+ break;
+ } /* for vc = cache_head .. NULL */
+
+ return (vc);
+} /* value_cache_t *cache_search */
+
+static int cache_alloc_name (char *ret, int ret_len,
+ const char *hostname,
+ const char *plugin, const char *plugin_instance,
+ const char *type, const char *type_instance)
+{
+ int status;
+
+ assert (plugin != NULL);
+ assert (type != NULL);
+
+ if ((plugin_instance == NULL) || (strlen (plugin_instance) == 0))
+ {
+ if ((type_instance == NULL) || (strlen (type_instance) == 0))
+ status = snprintf (ret, ret_len, "%s/%s/%s",
+ hostname, plugin, type);
+ else
+ status = snprintf (ret, ret_len, "%s/%s/%s-%s",
+ hostname, plugin, type, type_instance);
+ }
+ else
+ {
+ if ((type_instance == NULL) || (strlen (type_instance) == 0))
+ status = snprintf (ret, ret_len, "%s/%s-%s/%s",
+ hostname, plugin, plugin_instance, type);
+ else
+ status = snprintf (ret, ret_len, "%s/%s-%s/%s-%s",
+ hostname, plugin, plugin_instance, type, type_instance);
+ }
+
+ if ((status < 1) || (status >= ret_len))
+ return (-1);
+ return (0);
+} /* int cache_alloc_name */
+
+static int cache_insert (const data_set_t *ds, const value_list_t *vl)
+{
+ /* We're called from `cache_update' so we don't need to lock the mutex */
+ value_cache_t *vc;
+ int i;
+
+ DBG ("ds->ds_num = %i; vl->values_len = %i;",
+ ds->ds_num, vl->values_len);
+ assert (ds->ds_num == vl->values_len);
+
+ vc = (value_cache_t *) malloc (sizeof (value_cache_t));
+ if (vc == NULL)
+ {
+ pthread_mutex_unlock (&cache_lock);
+ syslog (LOG_ERR, "unixsock plugin: malloc failed: %s",
+ strerror (errno));
+ return (-1);
+ }
+
+ vc->gauge = (gauge_t *) malloc (sizeof (gauge_t) * vl->values_len);
+ if (vc->gauge == NULL)
+ {
+ pthread_mutex_unlock (&cache_lock);
+ syslog (LOG_ERR, "unixsock plugin: malloc failed: %s",
+ strerror (errno));
+ free (vc);
+ return (-1);
+ }
+
+ vc->counter = (counter_t *) malloc (sizeof (counter_t) * vl->values_len);
+ if (vc->counter == NULL)
+ {
+ pthread_mutex_unlock (&cache_lock);
+ syslog (LOG_ERR, "unixsock plugin: malloc failed: %s",
+ strerror (errno));
+ free (vc->gauge);
+ free (vc);
+ return (-1);
+ }
+
+ if (cache_alloc_name (vc->name, sizeof (vc->name),
+ vl->host, vl->plugin, vl->plugin_instance,
+ ds->type, vl->type_instance) != 0)
+ {
+ pthread_mutex_unlock (&cache_lock);
+ syslog (LOG_ERR, "unixsock plugin: cache_alloc_name failed.");
+ free (vc->counter);
+ free (vc->gauge);
+ free (vc);
+ return (-1);
+ }
+
+ for (i = 0; i < ds->ds_num; i++)
+ {
+ if (ds->ds[i].type == DS_TYPE_COUNTER)
+ {
+ vc->gauge[i] = 0.0;
+ vc->counter[i] = vl->values[i].counter;
+ }
+ else if (ds->ds[i].type == DS_TYPE_GAUGE)
+ {
+ vc->gauge[i] = vl->values[i].gauge;
+ vc->counter[i] = 0;
+ }
+ else
+ {
+ vc->gauge[i] = 0.0;
+ vc->counter[i] = 0;
+ }
+ }
+ vc->values_num = ds->ds_num;
+ vc->ds = ds;
+
+ vc->next = cache_head;
+ cache_head = vc;
+
+ vc->time = vl->time;
+ if (vc->time < cache_oldest)
+ cache_oldest = vc->time;
+
+ pthread_mutex_unlock (&cache_lock);
+ return (0);
+} /* int cache_insert */
+
+static int cache_update (const data_set_t *ds, const value_list_t *vl)
+{
+ char name[4*DATA_MAX_NAME_LEN];;
+ value_cache_t *vc;
+ int i;
+
+ if (cache_alloc_name (name, sizeof (name),
+ vl->host,
+ vl->plugin, vl->plugin_instance,
+ ds->type, vl->type_instance) != 0)
+ return (-1);
+
+ pthread_mutex_lock (&cache_lock);
+
+ vc = cache_search (name);
+
+ if (vc == NULL)
+ return (cache_insert (ds, vl));
+
+ assert (vc->values_num == ds->ds_num);
+ assert (vc->values_num == vl->values_len);
+
+ /*
+ * Update the values. This is possibly a lot more that you'd expect
+ * because we honor min and max values and handle counter overflows here.
+ */
+ for (i = 0; i < ds->ds_num; i++)
+ {
+ if (ds->ds[i].type == DS_TYPE_COUNTER)
+ {
+ if (vl->values[i].counter < vc->counter[i])
+ {
+ if (vl->values[i].counter <= 4294967295U)
+ {
+ vc->gauge[i] = ((4294967295U - vl->values[i].counter)
+ + vc->counter[i]) / (vl->time - vc->time);
+ }
+ else
+ {
+ vc->gauge[i] = ((18446744073709551615ULL - vl->values[i].counter)
+ + vc->counter[i]) / (vl->time - vc->time);
+ }
+ }
+ else
+ {
+ vc->gauge[i] = (vl->values[i].counter - vc->counter[i])
+ / (vl->time - vc->time);
+ }
+
+ vc->counter[i] = vl->values[i].counter;
+ }
+ else if (ds->ds[i].type == DS_TYPE_GAUGE)
+ {
+ vc->gauge[i] = vl->values[i].gauge;
+ vc->counter[i] = 0;
+ }
+ else
+ {
+ vc->gauge[i] = NAN;
+ vc->counter[i] = 0;
+ }
+
+ if ((vc->gauge[i] == NAN)
+ || ((ds->ds[i].min != NAN) && (vc->gauge[i] < ds->ds[i].min))
+ || ((ds->ds[i].max != NAN) && (vc->gauge[i] > ds->ds[i].max)))
+ vc->gauge[i] = NAN;
+ } /* for i = 0 .. ds->ds_num */
+
+ vc->ds = ds;
+ vc->time = vl->time;
+
+ if (vc->time < cache_oldest)
+ cache_oldest = vc->time;
+
+ pthread_mutex_unlock (&cache_lock);
+ return (0);
+} /* int cache_update */
+
+static void cache_flush (int max_age)
+{
+ value_cache_t *this;
+ value_cache_t *prev;
+ time_t now;
+
+ pthread_mutex_lock (&cache_lock);
+
+ now = time (NULL);
+
+ if ((now - cache_oldest) <= max_age)
+ {
+ pthread_mutex_unlock (&cache_lock);
+ return;
+ }
+
+ cache_oldest = now;
+
+ prev = NULL;
+ this = cache_head;
+
+ while (this != NULL)
+ {
+ if ((now - this->time) <= max_age)
+ {
+ if (this->time < cache_oldest)
+ cache_oldest = this->time;
+
+ prev = this;
+ this = this->next;
+ continue;
+ }
+
+ if (prev == NULL)
+ cache_head = this->next;
+ else
+ prev->next = this->next;
+
+ free (this->gauge);
+ free (this->counter);
+ free (this);
+
+ if (prev == NULL)
+ this = cache_head;
+ else
+ this = prev->next;
+ } /* while (this != NULL) */
+
+ pthread_mutex_unlock (&cache_lock);
+} /* int cache_flush */
+
+static int us_open_socket (void)
+{
+ struct sockaddr_un sa;
+ int status;
+
+ sock_fd = socket (PF_UNIX, SOCK_STREAM, 0);
+ if (sock_fd < 0)
+ {
+ syslog (LOG_ERR, "unixsock plugin: socket failed: %s",
+ strerror (errno));
+ return (-1);
+ }
+
+ memset (&sa, '\0', sizeof (sa));
+ sa.sun_family = AF_UNIX;
+ strncpy (sa.sun_path, (sock_file != NULL) ? sock_file : US_DEFAULT_PATH,
+ sizeof (sa.sun_path) - 1);
+ /* unlink (sa.sun_path); */
+
+ status = bind (sock_fd, (struct sockaddr *) &sa, sizeof (sa));
+ if (status != 0)
+ {
+ DBG ("bind failed: %s; sa.sun_path = %s",
+ strerror (errno), sa.sun_path);
+ syslog (LOG_ERR, "unixsock plugin: bind failed: %s",
+ strerror (errno));
+ close (sock_fd);
+ sock_fd = -1;
+ return (-1);
+ }
+
+ status = listen (sock_fd, 8);
+ if (status != 0)
+ {
+ syslog (LOG_ERR, "unixsock plugin: listen failed: %s",
+ strerror (errno));
+ close (sock_fd);
+ sock_fd = -1;
+ return (-1);
+ }
+
+ do
+ {
+ struct group *g;
+
+ errno = 0;
+ g = getgrnam ((sock_group != NULL) ? sock_group : COLLECTD_GRP_NAME);
+
+ if (errno != 0)
+ {
+ syslog (LOG_WARNING, "unixsock plugin: getgrnam (%s) failed: %s",
+ (sock_group != NULL) ? sock_group : COLLECTD_GRP_NAME,
+ strerror (errno));
+ break;
+ }
+
+ if (g == NULL)
+ break;
+
+ if (chown ((sock_file != NULL) ? sock_file : US_DEFAULT_PATH,
+ (uid_t) -1, g->gr_gid) != 0)
+ {
+ syslog (LOG_WARNING, "unixsock plugin: chown (%s, -1, %i) failed: %s",
+ (sock_file != NULL) ? sock_file : US_DEFAULT_PATH,
+ (int) g->gr_gid,
+ strerror (errno));
+ }
+ } while (0);
+
+ return (0);
+} /* int us_open_socket */
+
+static int us_handle_getval (FILE *fh, char **fields, int fields_num)
+{
+ char *hostname = fields[1];
+ char *plugin;
+ char *plugin_instance;
+ char *type;
+ char *type_instance;
+ char name[4*DATA_MAX_NAME_LEN];
+ value_cache_t *vc;
+ int status;
+ int i;
+
+ if (fields_num != 2)
+ 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++;
+ }
+
+ status = cache_alloc_name (name, sizeof (name),
+ hostname, plugin, plugin_instance, type, type_instance);
+ if (status != 0)
+ return (-1);
+
+ pthread_mutex_lock (&cache_lock);
+
+ DBG ("vc = cache_search (%s)", name);
+ vc = cache_search (name);
+
+ if (vc == NULL)
+ {
+ DBG ("Did not find cache entry.");
+ fprintf (fh, "-1 No such value");
+ }
+ else
+ {
+ DBG ("Found cache entry.");
+ fprintf (fh, "%i", vc->values_num);
+ for (i = 0; i < vc->values_num; i++)
+ {
+ fprintf (fh, " %s=", vc->ds->ds[i].name);
+ if (vc->gauge[i] == NAN)
+ fprintf (fh, "NaN");
+ else
+ fprintf (fh, "%12e", vc->gauge[i]);
+ }
+ }
+
+ /* Free the mutex as soon as possible and definitely before flushing */
+ pthread_mutex_unlock (&cache_lock);
+
+ fprintf (fh, "\n");
+ fflush (fh);
+
+ return (0);
+} /* int us_handle_getval */
+
+static void *us_handle_client (void *arg)
+{
+ int fd;
+ FILE *fh;
+ char buffer[1024];
+ char *fields[128];
+ int fields_num;
+
+ fd = *((int *) arg);
+ free (arg);
+ arg = NULL;
+
+ DBG ("Reading from fd #%i", fd);
+
+ fh = fdopen (fd, "r+");
+ if (fh == NULL)
+ {
+ syslog (LOG_ERR, "unixsock plugin: fdopen failed: %s",
+ strerror (errno));
+ close (fd);
+ pthread_exit ((void *) 1);
+ }
+
+ while (fgets (buffer, sizeof (buffer), fh) != NULL)
+ {
+ int len;
+
+ len = strlen (buffer);
+ while ((len > 0)
+ && ((buffer[len - 1] == '\n') || (buffer[len - 1] == '\r')))
+ buffer[--len] = '\0';
+
+ if (len == 0)
+ continue;
+
+ DBG ("fgets -> buffer = %s; len = %i;", buffer, len);
+
+ fields_num = strsplit (buffer, fields,
+ sizeof (fields) / sizeof (fields[0]));
+
+ if (fields_num < 1)
+ {
+ close (fd);
+ break;
+ }
+
+ if (strcasecmp (fields[0], "getval") == 0)
+ {
+ us_handle_getval (fh, fields, fields_num);
+ }
+ else
+ {
+ fprintf (fh, "Unknown command: %s\n", fields[0]);
+ fflush (fh);
+ }
+ } /* while (fgets) */
+
+ DBG ("Exiting..");
+ close (fd);
+
+ pthread_exit ((void *) 0);
+} /* void *us_handle_client */
+
+static void *us_server_thread (void *arg)
+{
+ int status;
+ int *remote_fd;
+ pthread_t th;
+ pthread_attr_t th_attr;
+
+ if (us_open_socket () != 0)
+ pthread_exit ((void *) 1);
+
+ while (42)
+ {
+ DBG ("Calling accept..");
+ status = accept (sock_fd, NULL, NULL);
+ if (status < 0)
+ {
+ if (errno == EINTR)
+ continue;
+
+ syslog (LOG_ERR, "unixsock plugin: accept failed: %s",
+ strerror (errno));
+ close (sock_fd);
+ sock_fd = -1;
+ pthread_exit ((void *) 1);
+ }
+
+ remote_fd = (int *) malloc (sizeof (int));
+ if (remote_fd == NULL)
+ {
+ syslog (LOG_WARNING, "unixsock plugin: malloc failed: %s",
+ strerror (errno));
+ close (status);
+ continue;
+ }
+ *remote_fd = status;
+
+ DBG ("Spawning child to handle connection on fd #%i", *remote_fd);
+
+ pthread_attr_init (&th_attr);
+ pthread_attr_setdetachstate (&th_attr, PTHREAD_CREATE_DETACHED);
+
+ status = pthread_create (&th, &th_attr, us_handle_client, (void *) remote_fd);
+ if (status != 0)
+ {
+ syslog (LOG_WARNING, "unixsock plugin: pthread_create failed: %s",
+ strerror (status));
+ close (*remote_fd);
+ free (remote_fd);
+ continue;
+ }
+ } /* while (42) */
+
+ return ((void *) 0);
+} /* void *us_server_thread */
+
+static int us_config (const char *key, const char *val)
+{
+ if (strcasecmp (key, "SocketFile") == 0)
+ {
+ sfree (sock_file);
+ sock_file = strdup (val);
+ }
+ else if (strcasecmp (key, "SocketGroup") == 0)
+ {
+ sfree (sock_group);
+ sock_group = strdup (val);
+ }
+ else if (strcasecmp (key, "SocketPerms") == 0)
+ {
+ sock_perms = (int) strtol (val, NULL, 8);
+ }
+ else
+ {
+ return (-1);
+ }
+
+ return (0);
+} /* int us_config */
+
+static int us_init (void)
+{
+ int status;
+
+ status = pthread_create (&listen_thread, NULL, us_server_thread, NULL);
+ if (status != 0)
+ {
+ syslog (LOG_ERR, "unixsock plugin: pthread_create failed: %s",
+ strerror (status));
+ return (-1);
+ }
+
+ return (0);
+} /* int us_init */
+
+static int us_shutdown (void)
+{
+ void *ret;
+
+ if (listen_thread != (pthread_t) 0)
+ {
+ pthread_kill (listen_thread, SIGTERM);
+ pthread_join (listen_thread, &ret);
+ listen_thread = (pthread_t) 0;
+ }
+
+ plugin_unregister_init ("unixsock");
+ plugin_unregister_write ("unixsock");
+ plugin_unregister_shutdown ("unixsock");
+
+ return (0);
+} /* int us_shutdown */
+
+static int us_write (const data_set_t *ds, const value_list_t *vl)
+{
+ cache_update (ds, vl);
+ cache_flush (2 * atoi (COLLECTD_STEP));
+
+ return (0);
+}
+
+void module_register (void)
+{
+ plugin_register_config ("unixsock", us_config,
+ config_keys, config_keys_num);
+ plugin_register_init ("unixsock", us_init);
+ plugin_register_write ("unixsock", us_write);
+ plugin_register_shutdown ("unixsock", us_shutdown);
+} /* void module_register (void) */
+
+/* vim: set sw=4 ts=4 sts=4 tw=78 : */
--- /dev/null
+/**
+ * collectd - src/utils_llist.c
+ * Copyright (C) 2006 Florian Forster <octo at verplant.org>
+ *
+ * This program is free software; you can redistribute it and/
+ * or modify it under the terms of the GNU General Public Li-
+ * cence as published by the Free Software Foundation; only
+ * version 2 of the Licence is applicable.
+ *
+ * This program is distributed in the hope that it will be use-
+ * ful, but WITHOUT ANY WARRANTY; without even the implied war-
+ * ranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * See the GNU General Public Licence for more details.
+ *
+ * You should have received a copy of the GNU General Public
+ * Licence along with this program; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139,
+ * USA.
+ *
+ * Authors:
+ * Florian Forster <octo at verplant.org>
+ */
+
+#include <stdlib.h>
+#include <string.h>
+
+#include "utils_llist.h"
+
+/*
+ * Private data types
+ */
+struct llist_s
+{
+ llentry_t *head;
+ llentry_t *tail;
+};
+
+/*
+ * Public functions
+ */
+llist_t *llist_create (void)
+{
+ llist_t *ret;
+
+ ret = (llist_t *) malloc (sizeof (llist_t));
+ if (ret == NULL)
+ return (NULL);
+
+ memset (ret, '\0', sizeof (llist_t));
+
+ return (ret);
+}
+
+void llist_destroy (llist_t *l)
+{
+ llentry_t *e_this;
+ llentry_t *e_next;
+
+ for (e_this = l->head; e_this != NULL; e_this = e_next)
+ {
+ e_next = e_this->next;
+ llentry_destroy (e_this);
+ }
+
+ free (l);
+}
+
+llentry_t *llentry_create (const char *key, void *value)
+{
+ llentry_t *e;
+
+ e = (llentry_t *) malloc (sizeof (llentry_t));
+ if (e == NULL)
+ return (NULL);
+
+ e->key = strdup (key);
+ e->value = value;
+ e->next = NULL;
+
+ if (e->key == NULL)
+ {
+ free (e);
+ return (NULL);
+ }
+
+ return (e);
+}
+
+void llentry_destroy (llentry_t *e)
+{
+ free (e->key);
+ free (e);
+}
+
+void llist_append (llist_t *l, llentry_t *e)
+{
+ e->next = NULL;
+
+ if (l->tail == NULL)
+ l->head = e;
+ else
+ l->tail->next = e;
+
+ l->tail = e;
+}
+
+void llist_prepend (llist_t *l, llentry_t *e)
+{
+ e->next = l->head;
+ l->head = e;
+}
+
+void llist_remove (llist_t *l, llentry_t *e)
+{
+ llentry_t *prev;
+
+ prev = l->head;
+ while ((prev != NULL) && (prev->next != e))
+ prev = prev->next;
+
+ if (prev != NULL)
+ prev->next = e->next;
+ if (l->head == e)
+ l->head = e->next;
+ if (l->tail == e)
+ l->tail = prev;
+}
+
+llentry_t *llist_search (llist_t *l, const char *key)
+{
+ llentry_t *e;
+
+ for (e = l->head; e != NULL; e = e->next)
+ if (strcmp (key, e->key) == 0)
+ break;
+
+ return (e);
+}
+
+llentry_t *llist_head (llist_t *l)
+{
+ return (l->head);
+}
+
+llentry_t *llist_tail (llist_t *l)
+{
+ return (l->tail);
+}
--- /dev/null
+/**
+ * collectd - src/utils_llist.h
+ * Copyright (C) 2006 Florian Forster <octo at verplant.org>
+ *
+ * This program is free software; you can redistribute it and/
+ * or modify it under the terms of the GNU General Public Li-
+ * cence as published by the Free Software Foundation; only
+ * version 2 of the Licence is applicable.
+ *
+ * This program is distributed in the hope that it will be use-
+ * ful, but WITHOUT ANY WARRANTY; without even the implied war-
+ * ranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * See the GNU General Public Licence for more details.
+ *
+ * You should have received a copy of the GNU General Public
+ * Licence along with this program; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139,
+ * USA.
+ *
+ * Authors:
+ * Florian Forster <octo at verplant.org>
+ */
+
+#ifndef UTILS_LLIST_H
+#define UTILS_LLIST_H 1
+
+/*
+ * Data types
+ */
+struct llentry_s
+{
+ char *key;
+ void *value;
+ struct llentry_s *next;
+};
+typedef struct llentry_s llentry_t;
+
+struct llist_s;
+typedef struct llist_s llist_t;
+
+/*
+ * Functions
+ */
+llist_t *llist_create (void);
+void llist_destroy (llist_t *l);
+
+llentry_t *llentry_create (const char *key, void *value);
+void llentry_destroy (llentry_t *e);
+
+void llist_append (llist_t *l, llentry_t *e);
+void llist_prepend (llist_t *l, llentry_t *e);
+void llist_remove (llist_t *l, llentry_t *e);
+
+llentry_t *llist_search (llist_t *l, const char *key);
+
+llentry_t *llist_head (llist_t *l);
+llentry_t *llist_tail (llist_t *l);
+
+#endif /* UTILS_LLIST_H */
/**
* collectd - src/wireless.c
- * Copyright (C) 2006 Florian octo Forster
+ * Copyright (C) 2006,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; either version 2 of the License, or (at your
- * option) any later version.
+ * 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
#include "common.h"
#include "plugin.h"
-#define MODULE_NAME "wireless"
-#define BUFSIZE 1024
-
#if defined(KERNEL_LINUX)
# define WIRELESS_HAVE_READ 1
#else
#define WIRELESS_PROC_FILE "/proc/net/wireless"
-static char *filename_template = "wireless-%s.rrd";
-
-static char *ds_def[] =
+static data_source_t data_source_quality[1] =
{
- "DS:quality:GAUGE:"COLLECTD_HEARTBEAT":0:U",
- "DS:power:GAUGE:"COLLECTD_HEARTBEAT":U:0",
- "DS:noise:GAUGE:"COLLECTD_HEARTBEAT":U:0",
- NULL
+ {"value", DS_TYPE_GAUGE, 0, NAN}
};
-static int ds_num = 3;
-
-#if WIRELESS_HAVE_READ
-static int proc_file_found = 0;
-#endif
-static void wireless_init (void)
+static data_set_t quality_ds =
{
-#if WIRELESS_HAVE_READ
- if (access (WIRELESS_PROC_FILE, R_OK) == 0)
- proc_file_found = 1;
- else
- proc_file_found = 0;
-#endif
-
- return;
-}
+ "signal_quality", 1, data_source_quality
+};
-static void wireless_write (char *host, char *inst, char *val)
+static data_source_t data_source_signal[1] =
{
- char file[BUFSIZE];
- int status;
+ {"value", DS_TYPE_GAUGE, NAN, 0}
+};
- status = snprintf (file, BUFSIZE, filename_template, inst);
- if (status < 1)
- return;
- else if (status >= BUFSIZE)
- return;
+static data_set_t power_ds =
+{
+ "signal_power", 1, data_source_signal
+};
- rrd_update_file (host, file, val, ds_def, ds_num);
-}
+static data_set_t noise_ds =
+{
+ "signal_noise", 1, data_source_signal
+};
#if WIRELESS_HAVE_READ
#if 0
}
#endif
-static void wireless_submit (char *device,
- double quality, double power, double noise)
+static void wireless_submit (const char *plugin_instance, const char *type,
+ double value)
{
- char buf[BUFSIZE];
- int status;
+ value_t values[1];
+ value_list_t vl = VALUE_LIST_INIT;
- status = snprintf (buf, BUFSIZE, "%u:%f:%f:%f",
- (unsigned int) curtime,
- quality, power, noise);
- if ((status < 1) || (status >= BUFSIZE))
- return;
+ values[0].gauge = value;
- plugin_submit (MODULE_NAME, device, buf);
-}
+ vl.values = values;
+ vl.values_len = 1;
+ vl.time = time (NULL);
+ strcpy (vl.host, hostname);
+ strcpy (vl.plugin, "wireless");
+ strncpy (vl.plugin_instance, plugin_instance,
+ sizeof (vl.plugin_instance));
-static void wireless_read (void)
+ plugin_dispatch_values (type, &vl);
+} /* void wireless_submit */
+
+static int wireless_read (void)
{
#ifdef KERNEL_LINUX
-
FILE *fh;
- char buffer[BUFSIZE];
+ char buffer[1024];
char *device;
double quality;
char *fields[8];
int numfields;
+ int devices_found;
int len;
- if (!proc_file_found)
- return;
-
/* there are a variety of names for the wireless device */
if ((fh = fopen (WIRELESS_PROC_FILE, "r")) == NULL)
{
syslog (LOG_WARNING, "wireless: fopen: %s", strerror (errno));
- return;
+ return (-1);
}
- while (fgets (buffer, BUFSIZE, fh) != NULL)
+ devices_found = 0;
+ while (fgets (buffer, sizeof (buffer), fh) != NULL)
{
numfields = strsplit (buffer, fields, 8);
if (noise == 0.0)
noise = 1.0; /* noise <= 0 */
- wireless_submit (device, quality, power, noise);
+ wireless_submit (device, "signal_quality", quality);
+ wireless_submit (device, "signal_power", power);
+ wireless_submit (device, "signal_noise", noise);
+
+ devices_found++;
}
fclose (fh);
+
+ /* If no wireless devices are present return an error, so the plugin
+ * code delays our read function. */
+ if (devices_found == 0)
+ return (-1);
#endif /* KERNEL_LINUX */
-}
-#else
-# define wireless_read NULL
+
+ return (0);
+} /* int wireless_read */
#endif /* WIRELESS_HAVE_READ */
void module_register (void)
{
- plugin_register (MODULE_NAME, wireless_init, wireless_read, wireless_write);
-}
+ plugin_register_data_set (&quality_ds);
+ plugin_register_data_set (&power_ds);
+ plugin_register_data_set (&noise_ds);
-#undef BUFSIZE
-#undef MODULE_NAME
+#if WIRELESS_HAVE_READ
+ plugin_register_read ("wireless", wireless_read);
+#endif /* WIRELESS_HAVE_READ */
+}