From d61648a21e25935f179fba85d07520d3c4b8f328 Mon Sep 17 00:00:00 2001 From: Florian Forster Date: Sun, 4 Mar 2012 10:41:11 +0100 Subject: [PATCH] numa plugin: Add plugin for Non-Uniform Memory Access (NUMA). Change-Id: I2610c7d8f73082154672114ad82001c6bd1b6f14 --- README | 3 + configure.in | 8 ++- src/Makefile.am | 8 +++ src/numa.c | 168 ++++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 185 insertions(+), 2 deletions(-) create mode 100644 src/numa.c diff --git a/README b/README index 69d3b367..e65f46bf 100644 --- a/README +++ b/README @@ -196,6 +196,9 @@ Features Network UPS tools: UPS current, voltage, power, charge, utilisation, temperature, etc. See upsd(8). + - numa + Information about Non-Uniform Memory Access (NUMA). + - olsrd Queries routing information from the “Optimized Link State Routing” daemon. diff --git a/configure.in b/configure.in index 61e61fea..0a0a8f8c 100644 --- a/configure.in +++ b/configure.in @@ -4433,6 +4433,7 @@ plugin_curl_xml="no" plugin_df="no" plugin_disk="no" plugin_entropy="no" +plugin_fscache="no" plugin_interface="no" plugin_ipmi="no" plugin_ipvs="no" @@ -4442,7 +4443,7 @@ plugin_load="no" plugin_memory="no" plugin_multimeter="no" plugin_nfs="no" -plugin_fscache="no" +plugin_numa="no" plugin_perl="no" plugin_processes="no" plugin_protocols="no" @@ -4469,12 +4470,13 @@ then plugin_cpufreq="yes" plugin_disk="yes" plugin_entropy="yes" + plugin_fscache="yes" plugin_interface="yes" plugin_irq="yes" plugin_load="yes" plugin_memory="yes" plugin_nfs="yes" - plugin_fscache="yes" + plugin_numa="yes" plugin_processes="yes" plugin_protocols="yes" plugin_serial="yes" @@ -4780,6 +4782,7 @@ AC_PLUGIN([nginx], [$with_libcurl], [nginx statistics]) AC_PLUGIN([notify_desktop], [$with_libnotify], [Desktop notifications]) AC_PLUGIN([notify_email], [$with_libesmtp], [Email notifier]) AC_PLUGIN([ntpd], [yes], [NTPd statistics]) +AC_PLUGIN([numa], [$plugin_numa], [NUMA virtual memory statistics]) AC_PLUGIN([nut], [$with_libupsclient], [Network UPS tools statistics]) AC_PLUGIN([olsrd], [yes], [olsrd statistics]) AC_PLUGIN([onewire], [$with_libowcapi], [OneWire sensor statistics]) @@ -5110,6 +5113,7 @@ Configuration: notify_desktop . . . $enable_notify_desktop notify_email . . . . $enable_notify_email ntpd . . . . . . . . $enable_ntpd + numa . . . . . . . . $enable_numa nut . . . . . . . . . $enable_nut olsrd . . . . . . . . $enable_olsrd onewire . . . . . . . $enable_onewire diff --git a/src/Makefile.am b/src/Makefile.am index 0869a086..05f94d9e 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -772,6 +772,14 @@ collectd_LDADD += "-dlopen" ntpd.la collectd_DEPENDENCIES += ntpd.la endif +if BUILD_PLUGIN_NUMA +pkglib_LTLIBRARIES += numa.la +numa_la_SOURCES = numa.c +numa_la_LDFLAGS = -module -avoid-version +collectd_LDADD += "-dlopen" numa.la +collectd_DEPENDENCIES += numa.la +endif + if BUILD_PLUGIN_NUT pkglib_LTLIBRARIES += nut.la nut_la_SOURCES = nut.c diff --git a/src/numa.c b/src/numa.c new file mode 100644 index 00000000..4b4ef208 --- /dev/null +++ b/src/numa.c @@ -0,0 +1,168 @@ +/** + * collectd - src/numa.c + * Copyright (C) 2012 Florian Forster + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + * Authors: + * Florian Forster + **/ + +#include "collectd.h" +#include "common.h" +#include "plugin.h" + +#if !KERNEL_LINUX +# error "No applicable input method." +#endif + +#ifndef NUMA_ROOT_DIR +# define NUMA_ROOT_DIR "/sys/devices/system/node" +#endif + +static int max_node = -1; + +static void numa_dispatch_value (int node, /* {{{ */ + const char *type_instance, value_t v) +{ + value_list_t vl = VALUE_LIST_INIT; + + vl.values = &v; + vl.values_len = 1; + + sstrncpy (vl.host, hostname_g, sizeof (vl.host)); + sstrncpy (vl.plugin, "numa", sizeof (vl.plugin)); + ssnprintf (vl.plugin_instance, sizeof (vl.plugin_instance), "node%i", node); + sstrncpy (vl.type, "vmpage_action", sizeof (vl.type)); + sstrncpy (vl.type_instance, type_instance, sizeof (vl.type_instance)); + + plugin_dispatch_values (&vl); +} /* }}} void numa_dispatch_value */ + +static int numa_read_node (int node) /* {{{ */ +{ + char path[PATH_MAX]; + FILE *fh; + char buffer[128]; + int status; + int success; + + ssnprintf (path, sizeof (path), NUMA_ROOT_DIR "/node%i/numastat", node); + + fh = fopen (path, "r"); + if (fh == NULL) + { + char errbuf[1024]; + ERROR ("numa plugin: Reading node %i failed: open(%s): %s", + node, path, sstrerror (errno, errbuf, sizeof (errbuf))); + return (-1); + } + + success = 0; + while (fgets (buffer, sizeof (buffer), fh) != NULL) + { + char *fields[4]; + value_t v; + + status = strsplit (buffer, fields, STATIC_ARRAY_SIZE (fields)); + if (status != 2) + { + WARNING ("numa plugin: Ignoring line with unexpected " + "number of fields (node %i).", node); + continue; + } + + v.derive = 0; + status = parse_value (fields[1], &v, DS_TYPE_DERIVE); + if (status != 0) + continue; + + numa_dispatch_value (node, fields[0], v); + success++; + } + + fclose (fh); + return (success ? 0 : -1); +} /* }}} int numa_read_node */ + +static int numa_read (void) /* {{{ */ +{ + int i; + int status; + int success; + + if (max_node < 0) + { + WARNING ("numa plugin: No NUMA nodes were detected."); + return (-1); + } + + success = 0; + for (i = 0; i <= max_node; i++) + { + status = numa_read_node (i); + if (status == 0) + success++; + } + + return (success ? 0 : -1); +} /* }}} int numa_read */ + +static int numa_init (void) /* {{{ */ +{ + /* Determine the number of nodes on this machine. */ + while (42) + { + char path[PATH_MAX]; + struct stat statbuf; + int status; + + ssnprintf (path, sizeof (path), NUMA_ROOT_DIR "/node%i", max_node + 1); + memset (&statbuf, 0, sizeof (statbuf)); + + status = stat (path, &statbuf); + if (status == 0) + { + max_node++; + continue; + } + else if (errno == ENOENT) + { + break; + } + else /* ((status != 0) && (errno != ENOENT)) */ + { + char errbuf[1024]; + ERROR ("numa plugin: stat(%s) failed: %s", path, + sstrerror (errno, errbuf, sizeof (errbuf))); + return (-1); + } + } + + DEBUG ("numa plugin: Found %i nodes.", max_node + 1); + return (0); +} /* }}} int numa_init */ + +void module_register (void) +{ + plugin_register_init ("numa", numa_init); + plugin_register_read ("numa", numa_read); +} /* void module_register */ + +/* vim: set sw=2 sts=2 et : */ -- 2.30.2