From a0ba86d57e39b5146d9fc06311b91af2af065e65 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Andr=C3=A9s=20J=2E=20D=C3=ADaz?= Date: Tue, 3 Feb 2015 23:09:01 +0100 Subject: [PATCH] Add IPC module. The IPC module allows collectd to gather information about process IPC mechanims, like used semaphores, size of shared memory segments and so on... --- README | 4 + configure.ac | 3 + src/Makefile.am | 8 ++ src/collectd.conf.in | 1 + src/ipc.c | 308 +++++++++++++++++++++++++++++++++++++++++++++++++++ src/types.db | 9 ++ 6 files changed, 333 insertions(+) create mode 100644 src/ipc.c diff --git a/README b/README index c2c08733..d845a28d 100644 --- a/README +++ b/README @@ -120,6 +120,10 @@ Features Interface traffic: Number of octets, packets and errors for each interface. + - ipc + IPC counters: semaphores used, number of allocated segments in shared + memory and more. + - iptables Iptables' counters: Number of bytes that were matched by a certain iptables rule. diff --git a/configure.ac b/configure.ac index f2d7ebdb..2deb4b44 100644 --- a/configure.ac +++ b/configure.ac @@ -5158,6 +5158,7 @@ then plugin_entropy="yes" plugin_fscache="yes" plugin_interface="yes" + plugin_ipc="yes" plugin_irq="yes" plugin_load="yes" plugin_lvm="yes" @@ -5491,6 +5492,7 @@ AC_PLUGIN([fscache], [$plugin_fscache], [fscache statistics]) AC_PLUGIN([gmond], [$with_libganglia], [Ganglia plugin]) AC_PLUGIN([hddtemp], [yes], [Query hddtempd]) AC_PLUGIN([interface], [$plugin_interface], [Interface traffic statistics]) +AC_PLUGIN([ipc], [$plugin_ipc], [IPC statistics]) AC_PLUGIN([ipmi], [$plugin_ipmi], [IPMI sensor statistics]) AC_PLUGIN([iptables], [$with_libiptc], [IPTables rule counters]) AC_PLUGIN([ipvs], [$plugin_ipvs], [IPVS connection statistics]) @@ -5862,6 +5864,7 @@ Configuration: gmond . . . . . . . . $enable_gmond hddtemp . . . . . . . $enable_hddtemp interface . . . . . . $enable_interface + ipc . . . . . . . . . $enable_ipc ipmi . . . . . . . . $enable_ipmi iptables . . . . . . $enable_iptables ipvs . . . . . . . . $enable_ipvs diff --git a/src/Makefile.am b/src/Makefile.am index 004fc94b..eb10a2bc 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -397,6 +397,14 @@ interface_la_LIBADD += -lperfstat endif endif # BUILD_PLUGIN_INTERFACE +if BUILD_PLUGIN_IPC +pkglib_LTLIBRARIES += ipc.la +ipc_la_SOURCES = ipc.c +ipc_la_LDFLAGS = -module -avoid-version +collectd_LDADD += "-dlopen" ipc.la +collectd_DEPENDENCIES += ipc.la +endif + if BUILD_PLUGIN_IPTABLES pkglib_LTLIBRARIES += iptables.la iptables_la_SOURCES = iptables.c diff --git a/src/collectd.conf.in b/src/collectd.conf.in index 34cd24f8..a6f919ef 100644 --- a/src/collectd.conf.in +++ b/src/collectd.conf.in @@ -121,6 +121,7 @@ #@BUILD_PLUGIN_GMOND_TRUE@LoadPlugin gmond #@BUILD_PLUGIN_HDDTEMP_TRUE@LoadPlugin hddtemp @BUILD_PLUGIN_INTERFACE_TRUE@@BUILD_PLUGIN_INTERFACE_TRUE@LoadPlugin interface +@BUILD_PLUGIN_IPC_TRUE@@BUILD_PLUGIN_IPC_TRUE@LoadPlugin ipc #@BUILD_PLUGIN_IPTABLES_TRUE@LoadPlugin iptables #@BUILD_PLUGIN_IPMI_TRUE@LoadPlugin ipmi #@BUILD_PLUGIN_IPVS_TRUE@LoadPlugin ipvs diff --git a/src/ipc.c b/src/ipc.c new file mode 100644 index 00000000..c10cdb1d --- /dev/null +++ b/src/ipc.c @@ -0,0 +1,308 @@ +/** + * collectd - src/ipc.c, based on src/memcached.c + * Copyright (C) 2010 Andres J. Diaz + * Copyright (C) 2010 Manuel L. Sanmartin + * + * 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. + * + * 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: + * Andres J. Diaz + * Manuel L. Sanmartin + **/ + +/* Many of this code is based on busybox ipc implementation, which is: + * (C) Rodney Radford and distributed under GPLv2. + */ + +#include "collectd.h" +#include "common.h" +#include "plugin.h" +#include "configfile.h" + +#if KERNEL_LINUX + /* X/OPEN tells us to use for semctl() */ + /* X/OPEN tells us to use for msgctl() */ + /* X/OPEN tells us to use for shmctl() */ +# include +# include +# include +# include +# include + + /* For older kernels the same holds for the defines below */ +# ifndef MSG_STAT +# define MSG_STAT 11 +# define MSG_INFO 12 +# endif + +# ifndef SHM_STAT +# define SHM_STAT 13 +# define SHM_INFO 14 + struct shm_info { + int used_ids; + ulong shm_tot; /* total allocated shm */ + ulong shm_rss; /* total resident shm */ + ulong shm_swp; /* total swapped shm */ + ulong swap_attempts; + ulong swap_successes; + }; +# endif + +# ifndef SEM_STAT +# define SEM_STAT 18 +# define SEM_INFO 19 +# endif + + /* The last arg of semctl is a union semun, but where is it defined? + X/OPEN tells us to define it ourselves, but until recently + Linux include files would also define it. */ +# if defined(__GNU_LIBRARY__) && !defined(_SEM_SEMUN_UNDEFINED) + /* union semun is defined by including */ +# else + /* according to X/OPEN we have to define it ourselves */ + union semun { + int val; + struct semid_ds *buf; + unsigned short *array; + struct seminfo *__buf; + }; +# endif +static long pagesize_g; +/* #endif KERNEL_LINUX */ +#elif KERNEL_AIX +# include +/* #endif KERNEL_AIX */ +#else +# error "No applicable input method." +#endif + +__attribute__ ((nonnull(1))) +static void ipc_submit_g (const char *type, gauge_t value) /* {{{ */ +{ + value_t values[1]; + value_list_t vl = VALUE_LIST_INIT; + + values[0].gauge = value; + + vl.values = values; + vl.values_len = 1; + sstrncpy (vl.host, hostname_g, sizeof (vl.host)); + sstrncpy (vl.plugin, "ipc", sizeof (vl.plugin)); + sstrncpy (vl.type, type, sizeof (vl.type)); + + plugin_dispatch_values (&vl); +} /* }}} */ + +#if KERNEL_AIX +static caddr_t ipc_get_info (cid_t cid, int cmd, int version, int stsize, int *nmemb) /* {{{ */ +{ + int size = 0; + caddr_t buff = NULL; + + if (get_ipc_info(cid, cmd, version, buff, &size) < 0) + { + if (errno != ENOSPC) { + char errbuf[1024]; + WARNING ("ipc plugin: get_ipc_info: %s", + sstrerror (errno, errbuf, sizeof (errbuf))); + return (NULL); + } + } + + if (size == 0) + return NULL; + + if (size % stsize) { + ERROR ("ipc plugin: ipc_get_info: missmatch struct size and buffer size"); + return (NULL); + } + + *nmemb = size / stsize; + + buff = (caddr_t)malloc (size); + if (buff == NULL) { + ERROR ("ipc plugin: ipc_get_info malloc failed."); + return (NULL); + } + + if (get_ipc_info(cid, cmd, version, buff, &size) < 0) + { + char errbuf[1024]; + WARNING ("ipc plugin: get_ipc_info: %s", + sstrerror (errno, errbuf, sizeof (errbuf))); + free(buff); + return (NULL); + } + + return buff; +} /* }}} */ +#endif /* KERNEL_AIX */ + +static int ipc_read_sem (void) /* {{{ */ +{ +#if KERNEL_LINUX + struct seminfo seminfo; + union semun arg; + + arg.array = (ushort *) (void *) &seminfo; + + if ( semctl(0, 0, SEM_INFO, arg) < 0 ) + { + ERROR("Kernel is not configured for semaphores"); + return (-1); + } + + ipc_submit_g("sem_used_arrays", seminfo.semusz); + ipc_submit_g("sem_used", seminfo.semaem); + +/* #endif KERNEL_LINUX */ +#elif KERNEL_AIX + ipcinfo_sem_t *ipcinfo_sem; + unsigned short sem_nsems=0; + unsigned short sems=0; + int i,n; + + ipcinfo_sem = (ipcinfo_sem_t *)ipc_get_info(0, + GET_IPCINFO_SEM_ALL, IPCINFO_SEM_VERSION, sizeof(ipcinfo_sem_t), &n); + if (ipcinfo_sem == NULL) + return -1; + + for (i=0; ishm_segsz; + } + free(ipcinfo_shm); + + ipc_submit_g("shm_segments", shm_segments); + ipc_submit_g("shm_bytes_total", shm_bytes); + +#endif /* KERNEL_AIX */ + return (0); +} +/* }}} */ + +static int ipc_read_msg (void) /* {{{ */ +{ +#if KERNEL_LINUX + struct msginfo msginfo; + + if ( msgctl(0, MSG_INFO, (struct msqid_ds *) (void *) &msginfo) < 0 ) + { + ERROR("Kernel is not configured for message queues"); + return (-1); + } + ipc_submit_g("msg_alloc_queues", msginfo.msgmni); + ipc_submit_g("msg_used_headers", msginfo.msgmap); + ipc_submit_g("msg_used_space", msginfo.msgtql); +/* #endif KERNEL_LINUX */ +#elif KERNEL_AIX + ipcinfo_msg_t *ipcinfo_msg; + uint32_t msg_used_space=0; + uint32_t msg_alloc_queues=0; + msgqnum32_t msg_qnum=0; + int i,n; + + ipcinfo_msg = (ipcinfo_msg_t *)ipc_get_info(0, + GET_IPCINFO_MSG_ALL, IPCINFO_MSG_VERSION, sizeof(ipcinfo_msg_t), &n); + if (ipcinfo_msg == NULL) + return -1; + + for (i=0; i