From: Florian Forster Date: Wed, 17 Jun 2015 15:29:48 +0000 (+0200) Subject: Merge branch 'collectd-5.5' X-Git-Tag: collectd-5.6.0~678 X-Git-Url: https://git.verplant.org/?a=commitdiff_plain;h=38dc4293b77a5b26e9727fa5ab154fe8930a5a8c;hp=d6491cfcf52a74498e1becd7ef94fc8e0a5938b9;p=collectd.git Merge branch 'collectd-5.5' --- diff --git a/AUTHORS b/AUTHORS index 3f63c3dc..02b12568 100644 --- a/AUTHORS +++ b/AUTHORS @@ -78,6 +78,9 @@ Christophe Kalt Cyril Feraudet - ethstat plugin. +Dagobert Michelsen + - zone plugin. + Dan Berrange - uuid plugin. @@ -174,6 +177,9 @@ Marco Chiappero - ip6tables support in the iptables plugin. - openvpn plugin (support for more status file formats) +Mathijs Möhlmann + - zone plugin. + Michael Hanselmann - md plugin. diff --git a/README b/README index 3e2c0233..6ac7e2b9 100644 --- a/README +++ b/README @@ -385,6 +385,10 @@ Features - zfs_arc Statistics for ZFS' “Adaptive Replacement Cache” (ARC). + - zone + Measures the percentage of cpu load per container (zone) under Solaris 10 + and higher + - zookeeper Read data from Zookeeper's MNTR command. diff --git a/configure.ac b/configure.ac index 553aa0ab..44d10cf6 100644 --- a/configure.ac +++ b/configure.ac @@ -5243,6 +5243,7 @@ plugin_vmem="no" plugin_vserver="no" plugin_wireless="no" plugin_zfs_arc="no" +plugin_zone="no" plugin_zookeeper="no" # Linux @@ -5340,6 +5341,7 @@ then plugin_processes="yes" plugin_uptime="yes" plugin_zfs_arc="yes" + plugin_zone="yes" fi if test "x$with_devinfo$with_kstat" = "xyesyes" @@ -5705,6 +5707,7 @@ AC_PLUGIN([write_sensu], [yes], [Sensu output plugin]) AC_PLUGIN([write_tsdb], [yes], [TSDB output plugin]) AC_PLUGIN([xmms], [$with_libxmms], [XMMS statistics]) AC_PLUGIN([zfs_arc], [$plugin_zfs_arc], [ZFS ARC statistics]) +AC_PLUGIN([zone], [$plugin_zone], [Solaris container statistics]) AC_PLUGIN([zookeeper], [yes], [Zookeeper statistics]) dnl Default configuration file @@ -6082,6 +6085,7 @@ Configuration: write_tsdb . . . . . $enable_write_tsdb xmms . . . . . . . . $enable_xmms zfs_arc . . . . . . . $enable_zfs_arc + zone . . . . . . . . $enable_zone zookeeper . . . . . . $enable_zookeeper EOF diff --git a/contrib/collectd.service b/contrib/collectd.service deleted file mode 100644 index ee4d596d..00000000 --- a/contrib/collectd.service +++ /dev/null @@ -1,15 +0,0 @@ -[Unit] -Description=statistics collection daemon -Documentation=man:collectd(1) -After=local-fs.target network.target -Requires=local-fs.target network.target - -[Service] -ExecStart=/usr/sbin/collectd -C /etc/collectd/collectd.conf -f -Restart=always -RestartSec=10 -StandardOutput=syslog -StandardError=syslog - -[Install] -WantedBy=multi-user.target diff --git a/contrib/redhat/collectd.spec b/contrib/redhat/collectd.spec index 9d491ff8..5e83b0f4 100644 --- a/contrib/redhat/collectd.spec +++ b/contrib/redhat/collectd.spec @@ -214,6 +214,8 @@ %define with_write_mongodb 0%{!?_without_write_mongodb:0} # plugin xmms disabled, requires xmms %define with_xmms 0%{!?_without_xmms:0} +# plugin zone disabled, requires Solaris +%define with_zone 0%{!?_without_zone:0} Summary: statistics collection and monitoring daemon Name: collectd @@ -1571,6 +1573,12 @@ Collectd utilities %define _with_zfs_arc --disable-zfs_arc %endif +%if %{with_zone} +%define _with_zone --enable-zone +%else +%define _with_zone --disable-zone +%endif + %if %{with_zookeeper} %define _with_zookeeper --enable-zookeeper %else @@ -1672,6 +1680,7 @@ Collectd utilities %{?_with_write_redis} \ %{?_with_xmms} \ %{?_with_zfs_arc} \ + %{?_with_zone} \ %{?_with_zookeeper} \ %{?_with_irq} \ %{?_with_load} \ @@ -2335,6 +2344,10 @@ fi %doc contrib/ %changelog +#* TODO: next feature release changelog +#- New upstream version +#- New plugins disabled by default: zone +# * Wed May 27 2015 Marc Fournier 5.5.0-1 - New upstream version - New plugins enabled by default: ceph, drbd, log_logstash, write_tsdb, smart, diff --git a/src/Makefile.am b/src/Makefile.am index 9839c03a..1282f225 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -1288,6 +1288,13 @@ endif BUILT_SOURCES += $(dist_man_MANS) +if BUILD_PLUGIN_ZONE +pkglib_LTLIBRARIES += zone.la +zone_la_SOURCES = zone.c +zone_la_CFLAGS = $(AM_CFLAGS) +zone_la_LDFLAGS = $(PLUGIN_LDFLAGS) +endif + dist_man_MANS = collectd.1 \ collectd.conf.5 \ collectd-email.5 \ diff --git a/src/apache.c b/src/apache.c index 0c6318e3..82a267b5 100644 --- a/src/apache.c +++ b/src/apache.c @@ -254,7 +254,7 @@ static int config_add (oconfig_item_t *ci) status = plugin_register_complex_read (/* group = */ NULL, /* name = */ callback_name, /* callback = */ apache_read_host, - /* interval = */ NULL, + /* interval = */ 0, /* user_data = */ &ud); } diff --git a/src/apcups.c b/src/apcups.c index be7673c5..dc533f1e 100644 --- a/src/apcups.c +++ b/src/apcups.c @@ -1,6 +1,6 @@ /* * collectd - src/apcups.c - * Copyright (C) 2006-2012 Florian octo Forster + * Copyright (C) 2006-2015 Florian octo Forster * Copyright (C) 2006 Anthony Gialluca * Copyright (C) 2000-2004 Kern Sibbald * Copyright (C) 1996-1999 Andre M. Hedrick @@ -43,11 +43,13 @@ # include #endif -#define NISPORT 3551 -#define MAXSTRING 256 -#define MODULE_NAME "apcups" +#ifndef APCUPS_DEFAULT_NODE +# define APCUPS_DEFAULT_NODE "localhost" +#endif -#define APCUPS_DEFAULT_HOST "localhost" +#ifndef APCUPS_DEFAULT_SERVICE +# define APCUPS_DEFAULT_SERVICE "3551" +#endif /* * Private data types @@ -68,24 +70,16 @@ struct apc_detail_s * Private variables */ /* Default values for contacting daemon */ -static char *conf_host = NULL; -static int conf_port = NISPORT; +static char *conf_node = NULL; +static char *conf_service = NULL; /* Defaults to false for backwards compatibility. */ static _Bool conf_report_seconds = 0; +static _Bool conf_persistent_conn = 1; static int global_sockfd = -1; static int count_retries = 0; static int count_iterations = 0; -static _Bool close_socket = 0; - -static const char *config_keys[] = -{ - "Host", - "Port", - "ReportSeconds" -}; -static int config_keys_num = STATIC_ARRAY_SIZE (config_keys); static int net_shutdown (int *fd) { @@ -116,26 +110,21 @@ static int apcups_shutdown (void) * Returns -1 on error * Returns socket file descriptor otherwise */ -static int net_open (char *host, int port) +static int net_open (char const *node, char const *service) { int sd; int status; - char port_str[8]; struct addrinfo ai_hints; struct addrinfo *ai_return; struct addrinfo *ai_list; - assert ((port > 0x00000000) && (port <= 0x0000FFFF)); - - /* Convert the port to a string */ - ssnprintf (port_str, sizeof (port_str), "%i", port); - /* Resolve name */ - memset ((void *) &ai_hints, '\0', sizeof (ai_hints)); - ai_hints.ai_family = AF_INET; /* XXX: Change this to `AF_UNSPEC' if apcupsd can handle IPv6 */ + memset (&ai_hints, 0, sizeof (ai_hints)); + /* TODO: Change this to `AF_UNSPEC' if apcupsd can handle IPv6 */ + ai_hints.ai_family = AF_INET; ai_hints.ai_socktype = SOCK_STREAM; - status = getaddrinfo (host, port_str, &ai_hints, &ai_return); + status = getaddrinfo (node, service, &ai_hints, &ai_return); if (status != 0) { char errbuf[1024]; @@ -179,7 +168,7 @@ static int net_open (char *host, int port) DEBUG ("Done opening a socket %i", sd); return (sd); -} /* int net_open (char *host, char *service, int port) */ +} /* int net_open */ /* * Receive a message from the other end. Each message consists of @@ -263,7 +252,7 @@ static int net_send (int *sockfd, char *buff, int len) } /* Get and print status from apcupsd NIS server */ -static int apc_query_server (char *host, int port, +static int apc_query_server (char const *node, char const *service, struct apc_detail_s *apcups_detail) { int n; @@ -285,7 +274,7 @@ static int apc_query_server (char *host, int port, { if (global_sockfd < 0) { - global_sockfd = net_open (host, port); + global_sockfd = net_open (node, service); if (global_sockfd < 0) { ERROR ("apcups plugin: Connecting to the " @@ -325,17 +314,20 @@ static int apc_query_server (char *host, int port, "first %i iterations. Will close the socket " "in future iterations.", count_retries, count_iterations); - close_socket = 1; + conf_persistent_conn = 0; } while ((n = net_recv (&global_sockfd, recvline, sizeof (recvline) - 1)) > 0) { - assert ((unsigned int)n < sizeof (recvline)); - recvline[n] = '\0'; + assert ((size_t)n < sizeof (recvline)); + recvline[n] = 0; #if APCMAIN printf ("net_recv = `%s';\n", recvline); #endif /* if APCMAIN */ + if (strncmp ("END APC", recvline, strlen ("END APC")) == 0) + break; + toksaveptr = NULL; tokptr = strtok_r (recvline, " :\t", &toksaveptr); while (tokptr != NULL) @@ -375,7 +367,7 @@ static int apc_query_server (char *host, int port, } status = errno; /* save errno, net_shutdown() may re-set it. */ - if (close_socket) + if (!conf_persistent_conn) net_shutdown (&global_sockfd); if (n < 0) @@ -389,41 +381,28 @@ static int apc_query_server (char *host, int port, return (0); } -static int apcups_config (const char *key, const char *value) +static int apcups_config (oconfig_item_t *ci) { - if (strcasecmp (key, "host") == 0) - { - if (conf_host != NULL) - { - free (conf_host); - conf_host = NULL; - } - if ((conf_host = strdup (value)) == NULL) - return (1); - } - else if (strcasecmp (key, "Port") == 0) - { - int port_tmp = atoi (value); - if (port_tmp < 1 || port_tmp > 65535) - { - WARNING ("apcups plugin: Invalid port: %i", port_tmp); - return (1); - } - conf_port = port_tmp; - } - else if (strcasecmp (key, "ReportSeconds") == 0) + int i; + + for (i = 0; i < ci->children_num; i++) { - if (IS_TRUE (value)) - conf_report_seconds = 1; + oconfig_item_t *child = ci->children + i; + + if (strcasecmp (child->key, "Host") == 0) + cf_util_get_string (child, &conf_node); + else if (strcasecmp (child->key, "Port") == 0) + cf_util_get_service (child, &conf_service); + else if (strcasecmp (child->key, "ReportSeconds") == 0) + cf_util_get_boolean (child, &conf_report_seconds); + else if (strcasecmp (child->key, "PersistentConnection") == 0) + cf_util_get_boolean (child, &conf_persistent_conn); else - conf_report_seconds = 0; - } - else - { - return (-1); + ERROR ("apcups plugin: Unknown config option \"%s\".", child->key); } + return (0); -} +} /* int apcups_config */ static void apc_submit_generic (char *type, char *type_inst, double value) { @@ -469,10 +448,9 @@ static int apcups_read (void) apcups_detail.itemp = -300.0; apcups_detail.linefreq = -1.0; - status = apc_query_server (conf_host == NULL - ? APCUPS_DEFAULT_HOST - : conf_host, - conf_port, &apcups_detail); + status = apc_query_server ((conf_node == NULL) ? APCUPS_DEFAULT_NODE : conf_node, + (conf_service == NULL) ? APCUPS_DEFAULT_SERVICE : conf_service, + &apcups_detail); /* * if we did not connect then do not bother submitting @@ -480,11 +458,10 @@ static int apcups_read (void) */ if (status != 0) { - DEBUG ("apc_query_server (%s, %i) = %i", - conf_host == NULL - ? APCUPS_DEFAULT_HOST - : conf_host, - conf_port, status); + DEBUG ("apc_query_server (%s, %s) = %i", + (conf_node == NULL) ? APCUPS_DEFAULT_NODE : conf_node, + (conf_service == NULL) ? APCUPS_DEFAULT_SERVICE : conf_service, + status); return (-1); } @@ -495,8 +472,7 @@ static int apcups_read (void) void module_register (void) { - plugin_register_config ("apcups", apcups_config, config_keys, - config_keys_num); + plugin_register_complex_config ("apcups", apcups_config); plugin_register_read ("apcups", apcups_read); plugin_register_shutdown ("apcups", apcups_shutdown); } /* void module_register */ diff --git a/src/collectd.conf.in b/src/collectd.conf.in index 5132cb4a..5a4c4674 100644 --- a/src/collectd.conf.in +++ b/src/collectd.conf.in @@ -206,6 +206,7 @@ #@BUILD_PLUGIN_WRITE_TSDB_TRUE@LoadPlugin write_tsdb #@BUILD_PLUGIN_XMMS_TRUE@LoadPlugin xmms #@BUILD_PLUGIN_ZFS_ARC_TRUE@LoadPlugin zfs_arc +#@BUILD_PLUGIN_ZONE_TRUE@LoadPlugin zone #@BUILD_PLUGIN_ZOOKEEPER_TRUE@LoadPlugin zookeeper ############################################################################## @@ -263,6 +264,7 @@ # Host "localhost" # Port "3551" # ReportSeconds true +# PersistentConnection true # # diff --git a/src/collectd.conf.pod b/src/collectd.conf.pod index 9ec3a208..96efc73c 100644 --- a/src/collectd.conf.pod +++ b/src/collectd.conf.pod @@ -130,6 +130,15 @@ Sets a plugin-specific interval for collecting metrics. This overrides the global B setting. If a plugin provides own support for specifying an interval, that setting will take precedence. +=item B I + +Specifies the the interval, in seconds, to call the flush callback if it's +defined in this plugin. By default, this is disabled + +=item B I + +Specifies the value of the timeout argument of the flush callback. + =back =item B B|B @@ -802,12 +811,22 @@ B can handle it. TCP-Port to connect to. Defaults to B<3551>. -=item B B +=item B B|B If set to B, the time reported in the C metric will be converted to seconds. This is the recommended setting. If set to B, the default for backwards compatibility, the time will be reported in minutes. +=item B B|B + +By default, the plugin will try to keep the connection to UPS open between +reads. Since this appears to be somewhat brittle (I appears to close +the connection due to inactivity quite quickly), the plugin will try to detect +this problem and switch to an open-read-close mode in such cases. + +You can instruct the plugin to close the connection after each read by setting +this option to B. + =back =head2 Plugin C @@ -4494,6 +4513,16 @@ The following options are accepted within each B block: Sets the URL to use to connect to the I server. This option is I. +=item B I + +Name in the form of an LDAP distinguished name intended to be used for +authentication. Defaults to empty string to establish an anonymous authorization. + +=item B I + +Password for simple bind authentication. If this option is not set, +unauthenticated bind operation is used. + =item B B Defines whether TLS must be used when connecting to the I server. @@ -5422,6 +5451,10 @@ dispatched to the daemon using the specified I as an identifier. This allows to "group" several processes together. I must not contain slashes. +=item B I + +Collect context switch of the process. + =back =head2 Plugin C diff --git a/src/curl_json.c b/src/curl_json.c index 3a5a3ab8..937a237e 100644 --- a/src/curl_json.c +++ b/src/curl_json.c @@ -763,9 +763,6 @@ static int cj_config_add_url (oconfig_item_t *ci) /* {{{ */ { user_data_t ud; char *cb_name; - struct timespec interval = { 0, 0 }; - - CDTIME_T_TO_TIMESPEC (db->interval, &interval); if (db->instance == NULL) db->instance = strdup("default"); @@ -781,7 +778,7 @@ static int cj_config_add_url (oconfig_item_t *ci) /* {{{ */ db->instance, db->url ? db->url : db->sock); plugin_register_complex_read (/* group = */ NULL, cb_name, cj_read, - /* interval = */ (db->interval > 0) ? &interval : NULL, + /* interval = */ db->interval, &ud); sfree (cb_name); } diff --git a/src/curl_xml.c b/src/curl_xml.c index 689d5e15..97b964bf 100644 --- a/src/curl_xml.c +++ b/src/curl_xml.c @@ -1015,7 +1015,7 @@ static int cx_config_add_url (oconfig_item_t *ci) /* {{{ */ cb_name = ssnprintf_alloc ("curl_xml-%s-%s", db->instance, db->url); plugin_register_complex_read (/* group = */ "curl_xml", cb_name, cx_read, - /* interval = */ NULL, &ud); + /* interval = */ 0, &ud); sfree (cb_name); } else diff --git a/src/daemon/configfile.c b/src/daemon/configfile.c index 765a23c4..f34adae3 100644 --- a/src/daemon/configfile.c +++ b/src/daemon/configfile.c @@ -289,20 +289,25 @@ static int dispatch_loadplugin (oconfig_item_t *ci) /* default to the global interval set before loading this plugin */ memset (&ctx, 0, sizeof (ctx)); ctx.interval = cf_get_default_interval (); + ctx.flush_interval = 0; + ctx.flush_timeout = 0; - for (i = 0; i < ci->children_num; ++i) { - if (strcasecmp("Globals", ci->children[i].key) == 0) - cf_util_get_flag (ci->children + i, &flags, PLUGIN_FLAGS_GLOBAL); - else if (strcasecmp ("Interval", ci->children[i].key) == 0) { - if (cf_util_get_cdtime (ci->children + i, &ctx.interval) != 0) { - /* cf_util_get_cdtime will log an error */ - continue; - } - } + for (i = 0; i < ci->children_num; ++i) + { + oconfig_item_t *child = ci->children + i; + + if (strcasecmp("Globals", child->key) == 0) + cf_util_get_flag (child, &flags, PLUGIN_FLAGS_GLOBAL); + else if (strcasecmp ("Interval", child->key) == 0) + cf_util_get_cdtime (child, &ctx.interval); + else if (strcasecmp ("FlushInterval", child->key) == 0) + cf_util_get_cdtime (child, &ctx.flush_interval); + else if (strcasecmp ("FlushTimeout", child->key) == 0) + cf_util_get_cdtime (child, &ctx.flush_timeout); else { WARNING("Ignoring unknown LoadPlugin option \"%s\" " "for plugin \"%s\"", - ci->children[i].key, ci->values[0].value.string); + child->key, ci->values[0].value.string); } } diff --git a/src/daemon/plugin.c b/src/daemon/plugin.c index 3d364458..88a2af4f 100644 --- a/src/daemon/plugin.c +++ b/src/daemon/plugin.c @@ -80,6 +80,12 @@ struct write_queue_s write_queue_t *next; }; +struct flush_callback_s { + char *name; + cdtime_t timeout; +}; +typedef struct flush_callback_s flush_callback_t; + /* * Private variables */ @@ -1245,7 +1251,7 @@ int plugin_register_read (const char *name, int plugin_register_complex_read (const char *group, const char *name, plugin_read_cb callback, - const struct timespec *interval, + cdtime_t interval, user_data_t *user_data) { read_func_t *rf; @@ -1266,10 +1272,7 @@ int plugin_register_complex_read (const char *group, const char *name, rf->rf_group[0] = '\0'; rf->rf_name = strdup (name); rf->rf_type = RF_COMPLEX; - if (interval != NULL) - rf->rf_interval = TIMESPEC_TO_CDTIME_T (interval); - else - rf->rf_interval = plugin_get_interval (); + rf->rf_interval = (interval != 0) ? interval : plugin_get_interval (); /* Set user data */ if (user_data == NULL) @@ -1298,11 +1301,105 @@ int plugin_register_write (const char *name, (void *) callback, ud)); } /* int plugin_register_write */ +static int plugin_flush_timeout_callback (user_data_t *ud) +{ + flush_callback_t *cb = ud->data; + + return plugin_flush (cb->name, cb->timeout, /* identifier = */ NULL); +} /* static int plugin_flush_callback */ + +static void plugin_flush_timeout_callback_free (void *data) +{ + flush_callback_t *cb = data; + + if (cb == NULL) return; + + sfree(cb->name); + sfree(cb); +} /* static void plugin_flush_callback_free */ + +static char *plugin_flush_callback_name (const char *name) +{ + char *flush_prefix = "flush/"; + size_t prefix_size; + char *flush_name; + size_t name_size; + + prefix_size = strlen(flush_prefix); + name_size = strlen(name); + + flush_name = malloc (sizeof(char) * (name_size + prefix_size + 1)); + if (flush_name == NULL) + { + ERROR ("plugin_flush_callback_name: malloc failed."); + return (NULL); + } + + sstrncpy (flush_name, flush_prefix, prefix_size + 1); + sstrncpy (flush_name + prefix_size, name, name_size + 1); + + return flush_name; +} /* static char *plugin_flush_callback_name */ + int plugin_register_flush (const char *name, plugin_flush_cb callback, user_data_t *ud) { - return (create_register_callback (&list_flush, name, - (void *) callback, ud)); + int status; + plugin_ctx_t ctx = plugin_get_ctx (); + + status = create_register_callback (&list_flush, name, + (void *) callback, ud); + if (status != 0) + return status; + + if (ctx.flush_interval != 0) + { + char *flush_name; + user_data_t ud; + flush_callback_t *cb; + + flush_name = plugin_flush_callback_name (name); + if (flush_name == NULL) + return (-1); + + cb = malloc(sizeof(flush_callback_t)); + if (cb == NULL) + { + ERROR ("plugin_register_flush: malloc failed."); + sfree(flush_name); + return (-1); + } + + cb->name = strdup (name); + if (cb->name == NULL) + { + ERROR ("plugin_register_flush: strdup failed."); + sfree(cb); + sfree(flush_name); + return (-1); + } + cb->timeout = ctx.flush_timeout; + + ud.data = cb; + ud.free_func = plugin_flush_timeout_callback_free; + + status = plugin_register_complex_read ( + /* group = */ "flush", + /* name = */ flush_name, + /* callback = */ plugin_flush_timeout_callback, + /* interval = */ ctx.flush_interval, + /* user data = */ &ud); + + sfree(flush_name); + if (status != 0) + { + sfree(cb->name); + sfree(cb); + return status; + } + } + + return 0; } /* int plugin_register_flush */ int plugin_register_missing (const char *name, @@ -1521,7 +1618,21 @@ int plugin_unregister_write (const char *name) int plugin_unregister_flush (const char *name) { - return (plugin_unregister (list_flush, name)); + plugin_ctx_t ctx = plugin_get_ctx (); + + if (ctx.flush_interval != 0) + { + char *flush_name; + + flush_name = plugin_flush_callback_name (name); + if (flush_name != NULL) + { + plugin_unregister_read(flush_name); + sfree(flush_name); + } + } + + return plugin_unregister (list_flush, name); } int plugin_unregister_missing (const char *name) diff --git a/src/daemon/plugin.h b/src/daemon/plugin.h index 70a22326..daea4fc9 100644 --- a/src/daemon/plugin.h +++ b/src/daemon/plugin.h @@ -177,6 +177,8 @@ typedef struct user_data_s user_data_t; struct plugin_ctx_s { cdtime_t interval; + cdtime_t flush_interval; + cdtime_t flush_timeout; }; typedef struct plugin_ctx_s plugin_ctx_t; @@ -293,7 +295,7 @@ int plugin_register_read (const char *name, * "plugin_register_complex_read" returns an error (non-zero). */ int plugin_register_complex_read (const char *group, const char *name, plugin_read_cb callback, - const struct timespec *interval, + cdtime_t interval, user_data_t *user_data); int plugin_register_write (const char *name, plugin_write_cb callback, user_data_t *user_data); diff --git a/src/dbi.c b/src/dbi.c index a7963ea2..d2b9a0ea 100644 --- a/src/dbi.c +++ b/src/dbi.c @@ -406,7 +406,7 @@ static int cdbi_config_add_database (oconfig_item_t *ci) /* {{{ */ plugin_register_complex_read (/* group = */ NULL, /* name = */ name ? name : db->name, /* callback = */ cdbi_read_database, - /* interval = */ NULL, + /* interval = */ 0, /* user_data = */ &ud); free (name); } diff --git a/src/java.c b/src/java.c index 2f1efbf1..56a39d40 100644 --- a/src/java.c +++ b/src/java.c @@ -1438,7 +1438,7 @@ static jint JNICALL cjni_api_register_read (JNIEnv *jvm_env, /* {{{ */ ud.free_func = cjni_callback_info_destroy; plugin_register_complex_read (/* group = */ NULL, cbi->name, cjni_read, - /* interval = */ NULL, &ud); + /* interval = */ 0, &ud); (*jvm_env)->DeleteLocalRef (jvm_env, o_read); diff --git a/src/memcached.c b/src/memcached.c index e2ccfee6..ab9de56f 100644 --- a/src/memcached.c +++ b/src/memcached.c @@ -565,7 +565,7 @@ static int memcached_add_read_callback (memcached_t *st) status = plugin_register_complex_read (/* group = */ "memcached", /* name = */ callback_name, /* callback = */ memcached_read, - /* interval = */ NULL, + /* interval = */ 0, /* user_data = */ &ud); return (status); } /* int memcached_add_read_callback */ diff --git a/src/modbus.c b/src/modbus.c index e24f2ec8..97840fd6 100644 --- a/src/modbus.c +++ b/src/modbus.c @@ -1017,18 +1017,15 @@ static int mb_config_add_host (oconfig_item_t *ci) /* {{{ */ { user_data_t ud; char name[1024]; - struct timespec interval = { 0, 0 }; ud.data = host; ud.free_func = host_free; ssnprintf (name, sizeof (name), "modbus-%s", host->host); - CDTIME_T_TO_TIMESPEC (host->interval, &interval); - plugin_register_complex_read (/* group = */ NULL, name, /* callback = */ mb_read, - /* interval = */ (host->interval > 0) ? &interval : NULL, + /* interval = */ host->interval, &ud); } else diff --git a/src/mysql.c b/src/mysql.c index eaa03719..a8a8e86d 100644 --- a/src/mysql.c +++ b/src/mysql.c @@ -213,7 +213,7 @@ static int mysql_config_database (oconfig_item_t *ci) /* {{{ */ plugin_register_complex_read (/* group = */ NULL, cb_name, mysql_read, - /* interval = */ NULL, &ud); + /* interval = */ 0, &ud); } else { diff --git a/src/netapp.c b/src/netapp.c index f446d597..020bfba1 100644 --- a/src/netapp.c +++ b/src/netapp.c @@ -2906,7 +2906,6 @@ static int cna_read (user_data_t *ud); static int cna_register_host (host_config_t *host) /* {{{ */ { char cb_name[256]; - struct timespec interval; user_data_t ud; if (host->vfiler) @@ -2915,15 +2914,13 @@ static int cna_register_host (host_config_t *host) /* {{{ */ else ssnprintf (cb_name, sizeof (cb_name), "netapp-%s", host->name); - CDTIME_T_TO_TIMESPEC (host->interval, &interval); - memset (&ud, 0, sizeof (ud)); ud.data = host; ud.free_func = (void (*) (void *)) free_host_config; plugin_register_complex_read (/* group = */ NULL, cb_name, /* callback = */ cna_read, - /* interval = */ (host->interval > 0) ? &interval : NULL, + /* interval = */ host->interval, /* user data = */ &ud); return (0); diff --git a/src/network.c b/src/network.c index d52da68f..4edc4f6e 100644 --- a/src/network.c +++ b/src/network.c @@ -283,8 +283,8 @@ typedef struct receive_list_entry_s receive_list_entry_t; static int network_config_ttl = 0; /* Ethernet - (IPv6 + UDP) = 1500 - (40 + 8) = 1452 */ static size_t network_config_packet_size = 1452; -static int network_config_forward = 0; -static int network_config_stats = 0; +static _Bool network_config_forward = 0; +static _Bool network_config_stats = 0; static sockent_t *sending_sockets = NULL; @@ -310,6 +310,7 @@ static pthread_t dispatch_thread_id; static char *send_buffer; static char *send_buffer_ptr; static int send_buffer_fill; +static cdtime_t send_buffer_last_update; static value_list_t send_buffer_vl = VALUE_LIST_STATIC; static pthread_mutex_t send_buffer_lock = PTHREAD_MUTEX_INITIALIZER; @@ -353,7 +354,7 @@ static _Bool check_send_okay (const value_list_t *vl) /* {{{ */ _Bool received = 0; int status; - if (network_config_forward != 0) + if (network_config_forward) return (1); if (vl->meta == NULL) @@ -2587,6 +2588,7 @@ static void network_init_buffer (void) memset (send_buffer, 0, network_config_packet_size); send_buffer_ptr = send_buffer; send_buffer_fill = 0; + send_buffer_last_update = 0; memset (&send_buffer_vl, 0, sizeof (send_buffer_vl)); } /* int network_init_buffer */ @@ -2926,6 +2928,7 @@ static int network_write (const data_set_t *ds, const value_list_t *vl, /* status == bytes added to the buffer */ send_buffer_fill += status; send_buffer_ptr += status; + send_buffer_last_update = cdtime(); stats_values_sent++; } @@ -2962,58 +2965,13 @@ static int network_write (const data_set_t *ds, const value_list_t *vl, return ((status < 0) ? -1 : 0); } /* int network_write */ -static int network_config_set_boolean (const oconfig_item_t *ci, /* {{{ */ - int *retval) -{ - if ((ci->values_num != 1) - || ((ci->values[0].type != OCONFIG_TYPE_BOOLEAN) - && (ci->values[0].type != OCONFIG_TYPE_STRING))) - { - ERROR ("network plugin: The `%s' config option needs " - "exactly one boolean argument.", ci->key); - return (-1); - } - - if (ci->values[0].type == OCONFIG_TYPE_BOOLEAN) - { - if (ci->values[0].value.boolean) - *retval = 1; - else - *retval = 0; - } - else - { - char *str = ci->values[0].value.string; - - if (IS_TRUE (str)) - *retval = 1; - else if (IS_FALSE (str)) - *retval = 0; - else - { - ERROR ("network plugin: Cannot parse string value `%s' of the `%s' " - "option as boolean value.", - str, ci->key); - return (-1); - } - } - - return (0); -} /* }}} int network_config_set_boolean */ - static int network_config_set_ttl (const oconfig_item_t *ci) /* {{{ */ { - int tmp; - if ((ci->values_num != 1) - || (ci->values[0].type != OCONFIG_TYPE_NUMBER)) - { - WARNING ("network plugin: The `TimeToLive' config option needs exactly " - "one numeric argument."); - return (-1); - } + int tmp = 0; - tmp = (int) ci->values[0].value.number; - if ((tmp > 0) && (tmp <= 255)) + if (cf_util_get_int (ci, &tmp) != 0) + return (-1); + else if ((tmp > 0) && (tmp <= 255)) network_config_ttl = tmp; else { WARNING ("network plugin: The `TimeToLive' must be between 1 and 255."); @@ -3026,63 +2984,30 @@ static int network_config_set_ttl (const oconfig_item_t *ci) /* {{{ */ static int network_config_set_interface (const oconfig_item_t *ci, /* {{{ */ int *interface) { - if ((ci->values_num != 1) - || (ci->values[0].type != OCONFIG_TYPE_STRING)) - { - WARNING ("network plugin: The `Interface' config option needs exactly " - "one string argument."); - return (-1); - } + char if_name[256]; - if (interface == NULL) + if (cf_util_get_string_buffer (ci, if_name, sizeof (if_name)) != 0) return (-1); - *interface = if_nametoindex (ci->values[0].value.string); - + *interface = if_nametoindex (if_name); return (0); } /* }}} int network_config_set_interface */ static int network_config_set_buffer_size (const oconfig_item_t *ci) /* {{{ */ { - int tmp; - if ((ci->values_num != 1) - || (ci->values[0].type != OCONFIG_TYPE_NUMBER)) - { - WARNING ("network plugin: The `MaxPacketSize' config option needs exactly " - "one numeric argument."); - return (-1); - } + int tmp = 0; - tmp = (int) ci->values[0].value.number; - if ((tmp >= 1024) && (tmp <= 65535)) + if (cf_util_get_int (ci, &tmp) != 0) + return (-1); + else if ((tmp >= 1024) && (tmp <= 65535)) network_config_packet_size = tmp; - - return (0); -} /* }}} int network_config_set_buffer_size */ - -#if HAVE_LIBGCRYPT -static int network_config_set_string (const oconfig_item_t *ci, /* {{{ */ - char **ret_string) -{ - char *tmp; - if ((ci->values_num != 1) - || (ci->values[0].type != OCONFIG_TYPE_STRING)) - { - WARNING ("network plugin: The `%s' config option needs exactly " - "one string argument.", ci->key); + else { + WARNING ("network plugin: The `MaxPacketSize' must be between 1024 and 65535."); return (-1); } - tmp = strdup (ci->values[0].value.string); - if (tmp == NULL) - return (-1); - - sfree (*ret_string); - *ret_string = tmp; - return (0); -} /* }}} int network_config_set_string */ -#endif /* HAVE_LIBGCRYPT */ +} /* }}} int network_config_set_buffer_size */ #if HAVE_LIBGCRYPT static int network_config_set_security_level (oconfig_item_t *ci, /* {{{ */ @@ -3146,15 +3071,14 @@ static int network_config_add_listen (const oconfig_item_t *ci) /* {{{ */ #if HAVE_LIBGCRYPT if (strcasecmp ("AuthFile", child->key) == 0) - network_config_set_string (child, &se->data.server.auth_file); + cf_util_get_string (child, &se->data.server.auth_file); else if (strcasecmp ("SecurityLevel", child->key) == 0) network_config_set_security_level (child, &se->data.server.security_level); else #endif /* HAVE_LIBGCRYPT */ if (strcasecmp ("Interface", child->key) == 0) - network_config_set_interface (child, - &se->interface); + network_config_set_interface (child, &se->interface); else { WARNING ("network plugin: Option `%s' is not allowed here.", @@ -3233,19 +3157,18 @@ static int network_config_add_server (const oconfig_item_t *ci) /* {{{ */ #if HAVE_LIBGCRYPT if (strcasecmp ("Username", child->key) == 0) - network_config_set_string (child, &se->data.client.username); + cf_util_get_string (child, &se->data.client.username); else if (strcasecmp ("Password", child->key) == 0) - network_config_set_string (child, &se->data.client.password); + cf_util_get_string (child, &se->data.client.password); else if (strcasecmp ("SecurityLevel", child->key) == 0) network_config_set_security_level (child, &se->data.client.security_level); else #endif /* HAVE_LIBGCRYPT */ if (strcasecmp ("Interface", child->key) == 0) - network_config_set_interface (child, - &se->interface); - else if (strcasecmp ("ResolveInterval", child->key) == 0) - cf_util_get_cdtime(child, &se->data.client.resolve_interval); + network_config_set_interface (child, &se->interface); + else if (strcasecmp ("ResolveInterval", child->key) == 0) + cf_util_get_cdtime(child, &se->data.client.resolve_interval); else { WARNING ("network plugin: Option `%s' is not allowed here.", @@ -3314,9 +3237,9 @@ static int network_config (oconfig_item_t *ci) /* {{{ */ else if (strcasecmp ("MaxPacketSize", child->key) == 0) network_config_set_buffer_size (child); else if (strcasecmp ("Forward", child->key) == 0) - network_config_set_boolean (child, &network_config_forward); + cf_util_get_boolean (child, &network_config_forward); else if (strcasecmp ("ReportStats", child->key) == 0) - network_config_set_boolean (child, &network_config_stats); + cf_util_get_boolean (child, &network_config_stats); else { WARNING ("network plugin: Option `%s' is not allowed here.", @@ -3537,7 +3460,7 @@ static int network_init (void) network_init_gcrypt (); #endif - if (network_config_stats != 0) + if (network_config_stats) plugin_register_read ("network", network_stats_read); plugin_register_shutdown ("network", network_shutdown); @@ -3615,15 +3538,25 @@ static int network_init (void) * just send the buffer if `flush' is called - if the requested value was in * there, good. If not, well, then there is nothing to flush.. -octo */ -static int network_flush (__attribute__((unused)) cdtime_t timeout, +static int network_flush (cdtime_t timeout, __attribute__((unused)) const char *identifier, __attribute__((unused)) user_data_t *user_data) { pthread_mutex_lock (&send_buffer_lock); if (send_buffer_fill > 0) - flush_buffer (); - + { + if (timeout > 0) + { + cdtime_t now = cdtime (); + if ((send_buffer_last_update + timeout) > now) + { + pthread_mutex_unlock (&send_buffer_lock); + return (0); + } + } + flush_buffer (); + } pthread_mutex_unlock (&send_buffer_lock); return (0); diff --git a/src/onewire.c b/src/onewire.c index 1383fc58..6cfea0ec 100644 --- a/src/onewire.c +++ b/src/onewire.c @@ -592,7 +592,6 @@ static int cow_shutdown (void) static int cow_init (void) { int status; - struct timespec cb_interval; if (device_g == NULL) { @@ -608,11 +607,8 @@ static int cow_init (void) return (1); } - CDTIME_T_TO_TIMESPEC (ow_interval, &cb_interval); - plugin_register_complex_read (/* group = */ NULL, "onewire", cow_read, - (ow_interval != 0) ? &cb_interval : NULL, - /* user data = */ NULL); + ow_interval, /* user data = */ NULL); plugin_register_shutdown ("onewire", cow_shutdown); return (0); diff --git a/src/openldap.c b/src/openldap.c index 8667058e..ffcdb94e 100644 --- a/src/openldap.c +++ b/src/openldap.c @@ -38,6 +38,8 @@ struct cldap_s /* {{{ */ { char *name; + char *binddn; + char *password; char *cacert; char *host; int state; @@ -56,6 +58,8 @@ static void cldap_free (cldap_t *st) /* {{{ */ if (st == NULL) return; + sfree (st->binddn); + sfree (st->password); sfree (st->cacert); sfree (st->host); sfree (st->name); @@ -110,10 +114,19 @@ static int cldap_init_host (cldap_t *st) /* {{{ */ } struct berval cred; - cred.bv_val = ""; - cred.bv_len = 0; + if (st->password != NULL) + { + cred.bv_val = st->password; + cred.bv_len = strlen (st->password); + } + else + { + cred.bv_val = ""; + cred.bv_len = 0; + } - rc = ldap_sasl_bind_s (st->ld, NULL, NULL, &cred, NULL, NULL, NULL); + rc = ldap_sasl_bind_s (st->ld, st->binddn, LDAP_SASL_SIMPLE, &cred, + NULL, NULL, NULL); if (rc != LDAP_SUCCESS) { ERROR ("openldap plugin: Failed to bind to %s: %s", @@ -559,7 +572,11 @@ static int cldap_config_add (oconfig_item_t *ci) /* {{{ */ { oconfig_item_t *child = ci->children + i; - if (strcasecmp ("CACert", child->key) == 0) + if (strcasecmp ("BindDN", child->key) == 0) + status = cf_util_get_string (child, &st->binddn); + else if (strcasecmp ("Password", child->key) == 0) + status = cf_util_get_string (child, &st->password); + else if (strcasecmp ("CACert", child->key) == 0) status = cf_util_get_string (child, &st->cacert); else if (strcasecmp ("StartTLS", child->key) == 0) status = cf_util_get_boolean (child, &st->starttls); @@ -630,7 +647,7 @@ static int cldap_config_add (oconfig_item_t *ci) /* {{{ */ status = plugin_register_complex_read (/* group = */ NULL, /* name = */ callback_name, /* callback = */ cldap_read_host, - /* interval = */ NULL, + /* interval = */ 0, /* user_data = */ &ud); } diff --git a/src/postgresql.c b/src/postgresql.c index 54c856d6..929b925c 100644 --- a/src/postgresql.c +++ b/src/postgresql.c @@ -1196,7 +1196,6 @@ static int c_psql_config_database (oconfig_item_t *ci) c_psql_database_t *db; char cb_name[DATA_MAX_NAME_LEN]; - struct timespec cb_interval = { 0, 0 }; user_data_t ud; static _Bool have_flush = 0; @@ -1291,12 +1290,9 @@ static int c_psql_config_database (oconfig_item_t *ci) ssnprintf (cb_name, sizeof (cb_name), "postgresql-%s", db->instance); if (db->queries_num > 0) { - CDTIME_T_TO_TIMESPEC (db->interval, &cb_interval); - ++db->ref_cnt; plugin_register_complex_read ("postgresql", cb_name, c_psql_read, - /* interval = */ (db->interval > 0) ? &cb_interval : NULL, - &ud); + /* interval = */ db->interval, &ud); } if (db->writers_num > 0) { ++db->ref_cnt; diff --git a/src/processes.c b/src/processes.c index fde96f89..4e0aa783 100644 --- a/src/processes.c +++ b/src/processes.c @@ -180,6 +180,9 @@ typedef struct procstat_entry_s derive_t io_syscr; derive_t io_syscw; + derive_t cswitch_vol; + derive_t cswitch_invol; + struct procstat_entry_s *next; } procstat_entry_t; @@ -211,12 +214,17 @@ typedef struct procstat derive_t io_syscr; derive_t io_syscw; + derive_t cswitch_vol; + derive_t cswitch_invol; + struct procstat *next; struct procstat_entry_s *instances; } procstat_t; static procstat_t *list_head_g = NULL; +static _Bool report_ctx_switch = 0; + #if HAVE_THREAD_INFO static mach_port_t port_host_self; static mach_port_t port_task_self; @@ -398,6 +406,8 @@ static void ps_list_add (const char *name, const char *cmdline, procstat_entry_t pse->io_wchar = entry->io_wchar; pse->io_syscr = entry->io_syscr; pse->io_syscw = entry->io_syscw; + pse->cswitch_vol = entry->cswitch_vol; + pse->cswitch_invol = entry->cswitch_invol; ps->num_proc += pse->num_proc; ps->num_lwp += pse->num_lwp; @@ -412,6 +422,9 @@ static void ps_list_add (const char *name, const char *cmdline, procstat_entry_t ps->io_syscr += ((pse->io_syscr == -1)?0:pse->io_syscr); ps->io_syscw += ((pse->io_syscw == -1)?0:pse->io_syscw); + ps->cswitch_vol += ((pse->cswitch_vol == -1)?0:pse->cswitch_vol); + ps->cswitch_invol += ((pse->cswitch_invol == -1)?0:pse->cswitch_invol); + if ((entry->vmem_minflt_counter == 0) && (entry->vmem_majflt_counter == 0)) { @@ -508,6 +521,8 @@ static void ps_list_reset (void) ps->io_wchar = -1; ps->io_syscr = -1; ps->io_syscw = -1; + ps->cswitch_vol = -1; + ps->cswitch_invol = -1; pse_prev = NULL; pse = ps->instances; @@ -592,6 +607,10 @@ static int ps_config (oconfig_item_t *ci) ps_list_register (c->values[0].value.string, c->values[1].value.string); } + else if (strcasecmp (c->key, "CollectContextSwitch") == 0) + { + cf_util_get_boolean (c, &report_ctx_switch); + } else { ERROR ("processes plugin: The `%s' configuration option is not " @@ -741,19 +760,36 @@ static void ps_submit_proc_list (procstat_t *ps) plugin_dispatch_values (&vl); } + if ( report_ctx_switch ) + { + sstrncpy (vl.type, "contextswitch", sizeof (vl.type)); + sstrncpy (vl.type_instance, "voluntary", sizeof (vl.type_instance)); + vl.values[0].derive = ps->cswitch_vol; + vl.values_len = 1; + plugin_dispatch_values (&vl); + + sstrncpy (vl.type, "contextswitch", sizeof (vl.type)); + sstrncpy (vl.type_instance, "involuntary", sizeof (vl.type_instance)); + vl.values[0].derive = ps->cswitch_invol; + vl.values_len = 1; + plugin_dispatch_values (&vl); + } + DEBUG ("name = %s; num_proc = %lu; num_lwp = %lu; " "vmem_size = %lu; vmem_rss = %lu; vmem_data = %lu; " "vmem_code = %lu; " "vmem_minflt_counter = %"PRIi64"; vmem_majflt_counter = %"PRIi64"; " "cpu_user_counter = %"PRIi64"; cpu_system_counter = %"PRIi64"; " "io_rchar = %"PRIi64"; io_wchar = %"PRIi64"; " - "io_syscr = %"PRIi64"; io_syscw = %"PRIi64";", + "io_syscr = %"PRIi64"; io_syscw = %"PRIi64"; " + "cswitch_vol = %"PRIi64"; cswitch_invol = %"PRIi64";", ps->name, ps->num_proc, ps->num_lwp, ps->vmem_size, ps->vmem_rss, ps->vmem_data, ps->vmem_code, ps->vmem_minflt_counter, ps->vmem_majflt_counter, ps->cpu_user_counter, ps->cpu_system_counter, - ps->io_rchar, ps->io_wchar, ps->io_syscr, ps->io_syscw); + ps->io_rchar, ps->io_wchar, ps->io_syscr, ps->io_syscw, + ps->cswitch_vol, ps->cswitch_invol); } /* void ps_submit_proc_list */ #if KERNEL_LINUX || KERNEL_SOLARIS @@ -778,42 +814,99 @@ static void ps_submit_fork_rate (derive_t value) /* ------- additional functions for KERNEL_LINUX/HAVE_THREAD_INFO ------- */ #if KERNEL_LINUX -static int ps_read_tasks (int pid) +static procstat_t *ps_read_tasks_status (int pid, procstat_t *ps) { char dirname[64]; DIR *dh; + char filename[64]; + FILE *fh; struct dirent *ent; - int count = 0; + derive_t cswitch_vol = 0; + derive_t cswitch_invol = 0; + char buffer[1024]; + char *fields[8]; + int numfields; ssnprintf (dirname, sizeof (dirname), "/proc/%i/task", pid); if ((dh = opendir (dirname)) == NULL) { DEBUG ("Failed to open directory `%s'", dirname); - return (-1); + return (NULL); } while ((ent = readdir (dh)) != NULL) { + char *tpid; + if (!isdigit ((int) ent->d_name[0])) continue; - else - count++; + + tpid = ent->d_name; + + ssnprintf (filename, sizeof (filename), "/proc/%i/task/%s/status", pid, tpid); + if ((fh = fopen (filename, "r")) == NULL) + { + DEBUG ("Failed to open file `%s'", filename); + continue; + } + + while (fgets (buffer, sizeof(buffer), fh) != NULL) + { + derive_t tmp; + char *endptr; + + if (strncmp (buffer, "voluntary_ctxt_switches", 23) != 0 + && strncmp (buffer, "nonvoluntary_ctxt_switches", 26) != 0) + continue; + + numfields = strsplit (buffer, fields, + STATIC_ARRAY_SIZE (fields)); + + if (numfields < 2) + continue; + + errno = 0; + endptr = NULL; + tmp = (derive_t) strtoll (fields[1], &endptr, /* base = */ 10); + if ((errno == 0) && (endptr != fields[1])) + { + if (strncmp (buffer, "voluntary_ctxt_switches", 23) == 0) + { + cswitch_vol += tmp; + } + else if (strncmp (buffer, "nonvoluntary_ctxt_switches", 26) == 0) + { + cswitch_invol += tmp; + } + } + } /* while (fgets) */ + + if (fclose (fh)) + { + char errbuf[1024]; + WARNING ("processes: fclose: %s", + sstrerror (errno, errbuf, sizeof (errbuf))); + } } closedir (dh); - return ((count >= 1) ? count : 1); -} /* int *ps_read_tasks */ + ps->cswitch_vol = cswitch_vol; + ps->cswitch_invol = cswitch_invol; + + return (ps); +} /* int *ps_read_tasks_status */ -/* Read advanced virtual memory data from /proc/pid/status */ -static procstat_t *ps_read_vmem (int pid, procstat_t *ps) +/* Read data from /proc/pid/status */ +static procstat_t *ps_read_status (int pid, procstat_t *ps) { FILE *fh; char buffer[1024]; char filename[64]; - unsigned long long lib = 0; - unsigned long long exe = 0; - unsigned long long data = 0; + unsigned long lib = 0; + unsigned long exe = 0; + unsigned long data = 0; + unsigned long threads = 0; char *fields[8]; int numfields; @@ -823,10 +916,11 @@ static procstat_t *ps_read_vmem (int pid, procstat_t *ps) while (fgets (buffer, sizeof(buffer), fh) != NULL) { - long long tmp; + unsigned long tmp; char *endptr; - if (strncmp (buffer, "Vm", 2) != 0) + if (strncmp (buffer, "Vm", 2) != 0 + && strncmp (buffer, "Threads", 7) != 0) continue; numfields = strsplit (buffer, fields, @@ -837,7 +931,7 @@ static procstat_t *ps_read_vmem (int pid, procstat_t *ps) errno = 0; endptr = NULL; - tmp = strtoll (fields[1], &endptr, /* base = */ 10); + tmp = strtoul (fields[1], &endptr, /* base = */ 10); if ((errno == 0) && (endptr != fields[1])) { if (strncmp (buffer, "VmData", 6) == 0) @@ -852,6 +946,10 @@ static procstat_t *ps_read_vmem (int pid, procstat_t *ps) { exe = tmp; } + else if (strncmp(buffer, "Threads", 7) == 0) + { + threads = tmp; + } } } /* while (fgets) */ @@ -864,6 +962,8 @@ static procstat_t *ps_read_vmem (int pid, procstat_t *ps) ps->vmem_data = data * 1024; ps->vmem_code = (exe + lib) * 1024; + if (threads != 0) + ps->num_lwp = threads; return (ps); } /* procstat_t *ps_read_vmem */ @@ -1006,11 +1106,16 @@ int ps_read_process (int pid, procstat_t *ps, char *state) } else { - if ( (ps->num_lwp = ps_read_tasks (pid)) == -1 ) + ps->num_lwp = strtoul (fields[17], /* endptr = */ NULL, /* base = */ 10); + if ((ps_read_status(pid, ps)) == NULL) { - /* returns -1 => kernel 2.4 */ - ps->num_lwp = 1; + /* No VMem data */ + ps->vmem_data = -1; + ps->vmem_code = -1; + DEBUG("ps_read_process: did not get vmem data for pid %i",pid); } + if (ps->num_lwp <= 0) + ps->num_lwp = 1; ps->num_proc = 1; } @@ -1043,14 +1148,6 @@ int ps_read_process (int pid, procstat_t *ps, char *state) cpu_system_counter = cpu_system_counter * 1000000 / CONFIG_HZ; vmem_rss = vmem_rss * pagesize_g; - if ( (ps_read_vmem(pid, ps)) == NULL) - { - /* No VMem data */ - ps->vmem_data = -1; - ps->vmem_code = -1; - DEBUG("ps_read_process: did not get vmem data for pid %i",pid); - } - ps->cpu_user_counter = cpu_user_counter; ps->cpu_system_counter = cpu_system_counter; ps->vmem_size = (unsigned long) vmem_size; @@ -1068,6 +1165,18 @@ int ps_read_process (int pid, procstat_t *ps, char *state) DEBUG("ps_read_process: not get io data for pid %i",pid); } + if ( report_ctx_switch ) + { + if ( (ps_read_tasks_status(pid, ps)) == NULL) + { + ps->cswitch_vol = -1; + ps->cswitch_invol = -1; + + DEBUG("ps_read_tasks_status: not get context " + "switch data for pid %i",pid); + } + } + /* success */ return (0); } /* int ps_read_process (...) */ @@ -1767,6 +1876,9 @@ static int ps_read (void) pse.io_syscr = ps.io_syscr; pse.io_syscw = ps.io_syscw; + pse.cswitch_vol = ps.cswitch_vol; + pse.cswitch_invol = ps.cswitch_invol; + switch (state) { case 'R': running++; break; diff --git a/src/python.c b/src/python.c index 8b378a29..d2ef1648 100644 --- a/src/python.c +++ b/src/python.c @@ -656,7 +656,6 @@ static PyObject *cpy_register_read(PyObject *self, PyObject *args, PyObject *kwd double interval = 0; char *name = NULL; PyObject *callback = NULL, *data = NULL; - struct timespec ts; static char *kwlist[] = {"callback", "interval", "data", "name", NULL}; if (PyArg_ParseTupleAndKeywords(args, kwds, "O|dOet", kwlist, &callback, &interval, &data, NULL, &name) == 0) return NULL; @@ -678,10 +677,8 @@ static PyObject *cpy_register_read(PyObject *self, PyObject *args, PyObject *kwd user_data = malloc(sizeof(*user_data)); user_data->free_func = cpy_destroy_user_data; user_data->data = c; - ts.tv_sec = interval; - ts.tv_nsec = (interval - ts.tv_sec) * 1000000000; plugin_register_complex_read(/* group = */ NULL, buf, - cpy_read_callback, &ts, user_data); + cpy_read_callback, DOUBLE_TO_CDTIME_T (interval), user_data); return cpy_string_to_unicode_or_bytes(buf); } diff --git a/src/routeros.c b/src/routeros.c index 4ca9d5b2..400ee42b 100644 --- a/src/routeros.c +++ b/src/routeros.c @@ -414,7 +414,7 @@ static int cr_config_router (oconfig_item_t *ci) /* {{{ */ user_data.free_func = (void *) cr_free_data; if (status == 0) status = plugin_register_complex_read (/* group = */ NULL, read_name, - cr_read, /* interval = */ NULL, &user_data); + cr_read, /* interval = */ 0, &user_data); if (status != 0) cr_free_data (router_data); diff --git a/src/snmp.c b/src/snmp.c index cb2bb36d..51afea1b 100644 --- a/src/snmp.c +++ b/src/snmp.c @@ -646,7 +646,6 @@ static int csnmp_config_add_host (oconfig_item_t *ci) /* Registration stuff. */ char cb_name[DATA_MAX_NAME_LEN]; user_data_t cb_data; - struct timespec cb_interval; hd = (host_definition_t *) malloc (sizeof (host_definition_t)); if (hd == NULL) @@ -779,11 +778,8 @@ static int csnmp_config_add_host (oconfig_item_t *ci) cb_data.data = hd; cb_data.free_func = csnmp_host_definition_destroy; - CDTIME_T_TO_TIMESPEC (hd->interval, &cb_interval); - status = plugin_register_complex_read (/* group = */ NULL, cb_name, - csnmp_read_host, /* interval = */ &cb_interval, - /* user_data = */ &cb_data); + csnmp_read_host, hd->interval, /* user_data = */ &cb_data); if (status != 0) { ERROR ("snmp plugin: Registering complex read function failed."); diff --git a/src/tail.c b/src/tail.c index 9ae4139a..480715fc 100644 --- a/src/tail.c +++ b/src/tail.c @@ -331,7 +331,6 @@ static int ctail_read (user_data_t *ud) static int ctail_init (void) { - struct timespec cb_interval; char str[255]; user_data_t ud; size_t i; @@ -348,8 +347,7 @@ static int ctail_init (void) { ud.data = (void *)tail_match_list[i]; ssnprintf(str, sizeof(str), "tail-%zu", i); - CDTIME_T_TO_TIMESPEC (tail_match_list_intervals[i], &cb_interval); - plugin_register_complex_read (NULL, str, ctail_read, &cb_interval, &ud); + plugin_register_complex_read (NULL, str, ctail_read, tail_match_list_intervals[i], &ud); } return (0); diff --git a/src/tail_csv.c b/src/tail_csv.c index 740095d6..41ed980d 100644 --- a/src/tail_csv.c +++ b/src/tail_csv.c @@ -429,7 +429,6 @@ static int tcsv_config_add_file(oconfig_item_t *ci) /* Registration variables */ char cb_name[DATA_MAX_NAME_LEN]; user_data_t cb_data; - struct timespec cb_interval; id = malloc(sizeof(*id)); if (id == NULL) @@ -494,8 +493,7 @@ static int tcsv_config_add_file(oconfig_item_t *ci) memset(&cb_data, 0, sizeof(cb_data)); cb_data.data = id; cb_data.free_func = tcsv_instance_definition_destroy; - CDTIME_T_TO_TIMESPEC(id->interval, &cb_interval); - status = plugin_register_complex_read(NULL, cb_name, tcsv_read, &cb_interval, &cb_data); + status = plugin_register_complex_read(NULL, cb_name, tcsv_read, id->interval, &cb_data); if (status != 0){ ERROR("tail_csv plugin: Registering complex read function failed."); diff --git a/src/varnish.c b/src/varnish.c index 8e6d95ee..0ea8c7f7 100644 --- a/src/varnish.c +++ b/src/varnish.c @@ -739,7 +739,7 @@ static int varnish_init (void) /* {{{ */ plugin_register_complex_read (/* group = */ "varnish", /* name = */ "varnish/localhost", /* callback = */ varnish_read, - /* interval = */ NULL, + /* interval = */ 0, /* user data = */ &ud); return (0); @@ -901,7 +901,7 @@ static int varnish_config_instance (const oconfig_item_t *ci) /* {{{ */ plugin_register_complex_read (/* group = */ "varnish", /* name = */ callback_name, /* callback = */ varnish_read, - /* interval = */ NULL, + /* interval = */ 0, /* user data = */ &ud); have_instance = 1; diff --git a/src/zone.c b/src/zone.c new file mode 100644 index 00000000..15eae6a2 --- /dev/null +++ b/src/zone.c @@ -0,0 +1,214 @@ +/** + * collectd - src/zone.c + * Copyright (C) 2011 Mathijs Mohlmann + * + * 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: + * Mathijs Mohlmann + * Dagobert Michelsen (forward-porting) + **/ + +#if HAVE_CONFIG_H +# include "config.h" +# undef HAVE_CONFIG_H +#endif +/* avoid procfs.h error "Cannot use procfs in the large file compilation environment" */ +#if !defined(_LP64) && _FILE_OFFSET_BITS == 64 +# undef _FILE_OFFSET_BITS +# undef _LARGEFILE64_SOURCE +#endif + +#include "collectd.h" +#include "common.h" +#include "plugin.h" + +#include +#include +#include +#include + +#include "utils_avltree.h" + +#define MAX_PROCFS_PATH 40 +#define FRC2PCT(pp)(((float)(pp))/0x8000*100) + +typedef struct zone_stats { + ushort_t pctcpu; + ushort_t pctmem; +} zone_stats_t; + +static long pagesize; + +static int zone_init (void) +{ + pagesize = sysconf(_SC_PAGESIZE); + return (0); +} + +static int +zone_compare(const zoneid_t *a, const zoneid_t *b) +{ + if (*a == *b) + return(0); + if (*a < *b) + return(-1); + return(1); +} + +static int +zone_read_procfile(char const *pidstr, char const *name, void *buf, size_t bufsize) +{ + int fd; + + char procfile[MAX_PROCFS_PATH]; + (void)snprintf(procfile, sizeof(procfile), "/proc/%s/%s", pidstr, name); + if ((fd = open(procfile, O_RDONLY)) == -1) { + return (1); + } + + if (sread(fd, buf, bufsize) != 0) { + char errbuf[1024]; + ERROR ("zone plugin: Reading \"%s\" failed: %s", procfile, + sstrerror (errno, errbuf, sizeof (errbuf))); + close(fd); + return (1); + } + + close(fd); + return (0); +} + +static int +zone_submit_value(char *zone, gauge_t value) +{ + value_list_t vl = VALUE_LIST_INIT; + value_t values[1]; + + values[0].gauge = value; + + vl.values = values; + vl.values_len = 1; /*STATIC_ARRAY_SIZE (values);*/ + sstrncpy (vl.host, hostname_g, sizeof (vl.host)); + sstrncpy (vl.plugin, "zone", sizeof (vl.plugin)); + sstrncpy (vl.type, "percent", sizeof (vl.type)); + sstrncpy (vl.type_instance, zone, sizeof (vl.type_instance)); + + return(plugin_dispatch_values (&vl)); +} + +static zone_stats_t * +zone_find_stats(c_avl_tree_t *tree, zoneid_t zoneid) +{ + zone_stats_t *ret = NULL; + zoneid_t *key = NULL; + + if (c_avl_get(tree, (void **)&zoneid, (void **)&ret)) { + if (!(ret = malloc(sizeof(zone_stats_t)))) { + WARNING("zone plugin: no memory"); + return(NULL); + } + if (!(key = malloc(sizeof(zoneid_t)))) { + WARNING("zone plugin: no memory"); + return(NULL); + } + *key = zoneid; + if (c_avl_insert(tree, key, ret)) { + WARNING("zone plugin: error inserting into tree"); + return(NULL); + } + } + return(ret); +} + +static void +zone_submit_values(c_avl_tree_t *tree) +{ + char zonename[ZONENAME_MAX]; + zoneid_t *zoneid = NULL; + zone_stats_t *stats = NULL; + + while (c_avl_pick (tree, (void **)&zoneid, (void **)&stats) == 0) + { + if (getzonenamebyid(*zoneid, zonename, sizeof( zonename )) == -1) { + WARNING("zone plugin: error retreiving zonename"); + } else { + zone_submit_value(zonename, (gauge_t)FRC2PCT(stats->pctcpu)); + } + free(stats); + free(zoneid); + } + c_avl_destroy(tree); +} + +static c_avl_tree_t * +zone_scandir(DIR *procdir) +{ + pid_t pid; + dirent_t *direntp; + psinfo_t psinfo; + c_avl_tree_t *tree; + zone_stats_t *stats; + + if (!(tree=c_avl_create((void *) zone_compare))) { + WARNING("zone plugin: Failed to create tree"); + return(NULL); + } + + rewinddir(procdir); + while ((direntp = readdir(procdir))) { + char const *pidstr = direntp->d_name; + if (pidstr[0] == '.') /* skip "." and ".." */ + continue; + + pid = atoi(pidstr); + if (pid == 0 || pid == 2 || pid == 3) + continue; /* skip sched, pageout and fsflush */ + + if (zone_read_procfile(pidstr, "psinfo", &psinfo, sizeof(psinfo_t)) != 0) + continue; + + stats = zone_find_stats(tree, psinfo.pr_zoneid); + if( stats ) { + stats->pctcpu += psinfo.pr_pctcpu; + stats->pctmem += psinfo.pr_pctmem; + } + } + return(tree); +} + +static int zone_read (void) +{ + DIR *procdir; + c_avl_tree_t *tree; + + if ((procdir = opendir("/proc")) == NULL) { + ERROR("zone plugin: cannot open /proc directory\n"); + return (-1); + } + + tree=zone_scandir(procdir); + closedir(procdir); + if (tree == NULL) { + return (-1); + } + zone_submit_values(tree); /* this also frees tree */ + return (0); +} + +void module_register (void) +{ + plugin_register_init ("zone", zone_init); + plugin_register_read ("zone", zone_read); +} /* void module_register */