From 005af449f773efba843edabff054deb9a20dacbb Mon Sep 17 00:00:00 2001 From: Dagobert Michelsen Date: Wed, 13 May 2015 16:39:26 +0200 Subject: [PATCH] Zone support for Solaris, forward-port of https://www.mail-archive.com/collectd@verplant.org/msg01232.html --- configure.ac | 4 ++ src/Makefile.am | 7 ++ src/collectd.conf.in | 1 + src/types.db | 1 + src/zone.c | 191 +++++++++++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 204 insertions(+) create mode 100644 src/zone.c diff --git a/configure.ac b/configure.ac index f62dfb33..d4e3301a 100644 --- a/configure.ac +++ b/configure.ac @@ -5153,6 +5153,7 @@ plugin_vmem="no" plugin_vserver="no" plugin_wireless="no" plugin_zfs_arc="no" +plugin_zone="no" plugin_zookeeper="no" # Linux @@ -5245,6 +5246,7 @@ then plugin_nfs="yes" plugin_uptime="yes" plugin_zfs_arc="yes" + plugin_zone="yes" fi if test "x$with_devinfo$with_kstat" = "xyesyes" @@ -5608,6 +5610,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 @@ -5983,6 +5986,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/src/Makefile.am b/src/Makefile.am index 5303c8a9..95e9f508 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -1268,6 +1268,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/collectd.conf.in b/src/collectd.conf.in index d31ef157..4950e401 100644 --- a/src/collectd.conf.in +++ b/src/collectd.conf.in @@ -204,6 +204,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 ############################################################################## diff --git a/src/types.db b/src/types.db index 5474659b..9e644385 100644 --- a/src/types.db +++ b/src/types.db @@ -226,6 +226,7 @@ voltage value:GAUGE:U:U vs_memory value:GAUGE:0:9223372036854775807 vs_processes value:GAUGE:0:65535 vs_threads value:GAUGE:0:65535 +zone_cpu value:GAUGE:0:100.1 # # Legacy types diff --git a/src/zone.c b/src/zone.c new file mode 100644 index 00000000..21a9497e --- /dev/null +++ b/src/zone.c @@ -0,0 +1,191 @@ +/** + * 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 + **/ + +#define _BSD_SOURCE + +#include "collectd.h" +#include "common.h" +#include "plugin.h" + +#include +#include +#include +#include + +#include "utils_avltree.h" + +#define MAX_PROCFS_PATH 40 +#define MAX_ZONE_NAME 20 +#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_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 *pidstr, char *file, void *buf, size_t bufsize) +{ + int fd; + + char procfile[MAX_PROCFS_PATH]; + (void)snprintf(procfile, MAX_PROCFS_PATH, "/proc/%s/%s", pidstr, file); + while ((fd = open(procfile, O_RDONLY)) == -1) { + if ((errno != EMFILE) || (errno != ENFILE)) { + return(1); + } + } + + if (pread(fd, buf, bufsize, 0) != bufsize) { + 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, "zone_cpu", 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("no memory"); + return(NULL); + } + if (!(key = malloc(sizeof(zoneid_t)))) { + WARNING("no memory"); + return(NULL); + } + *key = zoneid; + if (c_avl_insert(tree, key, ret)) { + WARNING("error inserting into tree"); + return(NULL); + } + } + return(ret); +} + +static void +zone_submit_values(c_avl_tree_t *tree) +{ + char zonename[MAX_ZONE_NAME]; + zoneid_t *zoneid = NULL; + zone_stats_t *stats = NULL; + + while (c_avl_pick (tree, (void **)&zoneid, (void **)&stats) == 0) + { + getzonenamebyid(*zoneid, zonename, MAX_ZONE_NAME-1); + 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) +{ + char *pidstr; + pid_t pid; + dirent_t *direntp; + psinfo_t psinfo; + c_avl_tree_t *tree; + zone_stats_t *stats; +/* size_t physmem = sysconf(_SC_PHYS_PAGES) * pagesize;*/ + + if (!(tree=c_avl_create((int (*) + (const void *, const void *))zone_compare))) { + WARNING("Failed to create tree"); + return(NULL); + } + + for (rewinddir(procdir); (direntp = readdir(procdir)); ) { + 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); + stats->pctcpu += psinfo.pr_pctcpu; + stats->pctmem += psinfo.pr_pctmem; + } + return(tree); +} + + +static int zone_read (void) +{ + DIR *procdir; + c_avl_tree_t *tree; + + pagesize = sysconf(_SC_PAGESIZE); + if ((procdir = opendir("/proc")) == NULL) { + ERROR("cannot open /proc directory\n"); + exit(1); + } + + tree=zone_scandir(procdir); + closedir(procdir); + zone_submit_values(tree); /* this also frees tree */ + return (0); +} + +void module_register (void) +{ + plugin_register_read ("zone", zone_read); +} /* void module_register */ -- 2.11.0