Hello Florian,
here is a new version of my lpar plugin. I tried to address the shortcomings of the previous attempt: - Minimum and maximum proc capacity are gone, being static values - The plugin now uses the cpu type for every value, so there is no need anymore for the lpar_cpu type - This also means there is no need anymore to compute rates in the plugin, so the code is IMHO much more elegant - There is a config option "ReportBySerial", as described in my previous email - We now use pool_busy_time directly instead of computing it from total and idle The patch is against the current 4.10 branch, rather than against ar/lpar, because it is more of a complete rewrite than just fixes. I could provide a patch against ar/lpar however if you prefer so. Regards, Aurélien Reynaud
diff --git a/configure.in b/configure.in index 75ac706..a928302 100644 --- a/configure.in +++ b/configure.in @@ -4292,6 +4292,7 @@ AC_PLUGIN([java], [$with_java], [Embed the Java Virtual Machine]) AC_PLUGIN([libvirt], [$plugin_libvirt], [Virtual machine statistics]) AC_PLUGIN([load], [$plugin_load], [System load]) AC_PLUGIN([logfile], [yes], [File logging plugin]) +AC_PLUGIN([lpar], [$with_perfstat], [AIX logical partitions statistics]) AC_PLUGIN([madwifi], [$have_linux_wireless_h], [Madwifi wireless statistics]) AC_PLUGIN([match_empty_counter], [yes], [The empty counter match]) AC_PLUGIN([match_hashed], [yes], [The hashed match]) @@ -4609,6 +4610,7 @@ Configuration: libvirt . . . . . . . $enable_libvirt load . . . . . . . . $enable_load logfile . . . . . . . $enable_logfile + lpar... . . . . . . . $enable_lpar madwifi . . . . . . . $enable_madwifi match_empty_counter . $enable_match_empty_counter match_hashed . . . . $enable_match_hashed diff --git a/src/Makefile.am b/src/Makefile.am index c6b0538..3bf4184 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -499,6 +499,15 @@ collectd_LDADD += "-dlopen" logfile.la collectd_DEPENDENCIES += logfile.la endif +if BUILD_PLUGIN_LPAR +pkglib_LTLIBRARIES += lpar.la +lpar_la_SOURCES = lpar.c +lpar_la_LDFLAGS = -module -avoid-version +collectd_LDADD += "-dlopen" lpar.la +collectd_DEPENDENCIES += lpar.la +lpar_la_LIBADD = -lperfstat +endif + if BUILD_PLUGIN_MADWIFI pkglib_LTLIBRARIES += madwifi.la madwifi_la_SOURCES = madwifi.c madwifi.h diff --git a/src/lpar.c b/src/lpar.c new file mode 100755 index 0000000..2267e03 --- /dev/null +++ b/src/lpar.c @@ -0,0 +1,202 @@ +/** + * collectd - src/lpar.c + * Copyright (C) 2010 Aurélien Reynaud + * + * 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: + * Aurelien Reynaud <collectd at wattapower.net> + **/ + +#include "collectd.h" +#include "common.h" +#include "plugin.h" +#include <sys/protosw.h> +#include <libperfstat.h> +#include <sys/utsname.h> + +#ifndef XINTFRAC +# include <sys/systemcfg.h> +# define XINTFRAC ((double)(_system_configuration.Xint) / \ + (double)(_system_configuration.Xfrac)) +#endif +#define HTIC2SEC(x) ((double)x * XINTFRAC / 1000000000.0) + +/* Max length of the type instance string */ +#define TYPE_INST_LEN (sizeof("pool--total") + 2*sizeof(int) + 1) + +static const char *config_keys[] = +{ + "CpuPoolStats", + "ReportBySerial" +}; +static int config_keys_num = STATIC_ARRAY_SIZE (config_keys); +static int pool_stats = 0, + report_by_serial = 0; + +static u_longlong_t last_time_base; +static u_longlong_t ent_counter; +static int donate_flag = 0; + + +static int lpar_config (const char *key, const char *value) +{ + if (strcasecmp ("CpuPoolStats", key) == 0) + { + if (IS_TRUE (value)) + pool_stats = 1; + } + else if (strcasecmp ("ReportBySerial", key) == 0) + { + if (IS_TRUE (value)) + report_by_serial = 1; + } + else + { + return (-1); + } + + return (0); +} /* int lpar_config */ + +static int lpar_init (void) +{ + perfstat_partition_total_t lparstats; + + /* Retrieve the initial metrics */ + if (!perfstat_partition_total (NULL, &lparstats, + sizeof (perfstat_partition_total_t), 1)) + { + ERROR ("lpar plugin: perfstat_partition_total failed."); + return (-1); + } + + if (!lparstats.type.b.shared_enabled && lparstats.type.b.donate_enabled) + { + donate_flag = 1; + } + + if (pool_stats && !lparstats.type.b.pool_util_authority) + { + WARNING ("lpar plugin: this system does not have pool authority. " + "Disabling CPU pool statistics collection."); + pool_stats = 0; + } + + /* Initialize the fake counter for entitled capacity */ + last_time_base = lparstats.timebase_last; + ent_counter = 0; + + return (0); +} /* int lpar_init */ + +static void lpar_submit (const char *type_instance, double value) +{ + value_t values[1]; + value_list_t vl = VALUE_LIST_INIT; + + /* Although it appears as a double, value is really a (scaled) counter, + expressed in CPU x seconds. At high collection rates (< 1 min), its + integer part is very small and the resulting graphs get blocky. We regain + some precision by applying a x100 factor before casting it to a counter, + turning the final value into CPU units instead of CPUs. */ + values[0].counter = (counter_t)(value * 100.0 + 0.5); + + vl.values = values; + vl.values_len = 1; + + /* An LPAR has the same serial number as the physical system it is currently + running on. It is a convenient way of tracking LPARs as they are moved + from chassis to chassis through Live Partition Mobility (LPM). */ + if (report_by_serial) + { + struct utsname name; + if (uname (&name) != 0) + { + ERROR ("lpar plugin: uname failed."); + return; + } + sstrncpy (vl.host, name.machine, sizeof (vl.host)); + sstrncpy (vl.plugin_instance, hostname_g, sizeof (vl.plugin)); + } + else + { + sstrncpy (vl.host, hostname_g, sizeof (vl.host)); + } + sstrncpy (vl.plugin, "lpar", sizeof (vl.plugin)); + sstrncpy (vl.type, "cpu", sizeof (vl.type)); + sstrncpy (vl.type_instance, type_instance, sizeof (vl.type_instance)); + + plugin_dispatch_values (&vl); +} + +static int lpar_read (void) +{ + u_longlong_t delta_time_base; + perfstat_partition_total_t lparstats; + + /* Retrieve the current metrics */ + if (!perfstat_partition_total (NULL, &lparstats, + sizeof (perfstat_partition_total_t), 1)) + { + ERROR ("lpar plugin: perfstat_partition_total failed."); + return (-1); + } + + delta_time_base = lparstats.timebase_last - last_time_base; + last_time_base = lparstats.timebase_last; + + lpar_submit ("user", HTIC2SEC(lparstats.puser)); + lpar_submit ("sys", HTIC2SEC(lparstats.psys)); + lpar_submit ("wait", HTIC2SEC(lparstats.pwait)); + lpar_submit ("idle", HTIC2SEC(lparstats.pidle)); + /* Entitled capacity is reported as an absolute value instead of a counter, + so we fake one. It's also in CPU units, hence the division by 100 before + submission. */ + ent_counter += lparstats.entitled_proc_capacity * delta_time_base; + lpar_submit ("ent", HTIC2SEC(ent_counter) / 100.0); + + if (donate_flag) + { + lpar_submit ("idle_donated", HTIC2SEC(lparstats.idle_donated_purr)); + lpar_submit ("busy_donated", HTIC2SEC(lparstats.busy_donated_purr)); + lpar_submit ("idle_stolen", HTIC2SEC(lparstats.idle_stolen_purr)); + lpar_submit ("busy_stolen", HTIC2SEC(lparstats.busy_stolen_purr)); + } + + if (pool_stats) + { + char typinst[TYPE_INST_LEN]; + + /* Pool stats are in CPU x ns */ + ssnprintf (typinst, sizeof(typinst), "pool-%X-busy", lparstats.pool_id); + lpar_submit (typinst, (double)lparstats.pool_busy_time / 1000000000.0); + + ssnprintf (typinst, sizeof(typinst), "pool-%X-total", lparstats.pool_id); + lpar_submit (typinst, (double)lparstats.pool_max_time / 1000000000.0); + } + + return (0); +} /* int lpar_read */ + +void module_register (void) +{ + plugin_register_config ("lpar", lpar_config, + config_keys, config_keys_num); + plugin_register_init ("lpar", lpar_init); + plugin_register_read ("lpar", lpar_read); +} /* void module_register */ + +/* vim: set sw=2 sts=2 ts=8 : */ +
_______________________________________________ collectd mailing list collectd@verplant.org http://mailman.verplant.org/listinfo/collectd