summary | shortlog | log | commit | commitdiff | tree
raw | patch | inline | side by side (parent: 88057cc)
raw | patch | inline | side by side (parent: 88057cc)
author | Jaroslav Safka <jaroslavx.safka@intel.com> | |
Thu, 23 Jun 2016 04:53:12 +0000 (05:53 +0100) | ||
committer | Maryam Tahhan <maryam.tahhan@intel.com> | |
Mon, 18 Jul 2016 12:07:05 +0000 (13:07 +0100) |
Plugin that allows stats for hugepages to be collected.
Change-Id: Ide5ff31c54206cf5ee3d6155899bd53e8edae7bd
Signed-off-by: Jaroslav Safka <jaroslavx.safka@intel.com>
Signed-off-by: Kim Jones <kim-marie.jones@intel.com>
Signed-off-by: Maryam Tahhan <maryam.tahhan@intel.com>
Change-Id: Ide5ff31c54206cf5ee3d6155899bd53e8edae7bd
Signed-off-by: Jaroslav Safka <jaroslavx.safka@intel.com>
Signed-off-by: Kim Jones <kim-marie.jones@intel.com>
Signed-off-by: Maryam Tahhan <maryam.tahhan@intel.com>
README | patch | blob | history | |
configure.ac | patch | blob | history | |
src/Makefile.am | patch | blob | history | |
src/collectd.conf.in | patch | blob | history | |
src/collectd.conf.pod | patch | blob | history | |
src/hugepages.c | [new file with mode: 0644] | patch | blob |
src/types.db | patch | blob | history |
index 1c3af7a4baa251640ac45a21a96cd04b7236b6a1..1693c75ef04549f748f630c67bf0b8e697febd3f 100644 (file)
--- a/README
+++ b/README
- hddtemp
Hard disk temperatures using hddtempd.
+ - hugepages
+ Report the total number of hugpages, the number of free/reserved
+ hugepages, and the size of the available hugepages. More info on
+ hugepages can be found here:
+ https://www.kernel.org/doc/Documentation/vm/hugetlbpage.txt.
+
- interface
Interface traffic: Number of octets, packets and errors for each
interface.
diff --git a/configure.ac b/configure.ac
index c69842cc3ccf14fee6c7becc0be5248729379688..a69f16bb4d5a43336a4de356cdf233f704819b94 100644 (file)
--- a/configure.ac
+++ b/configure.ac
# For hddtemp module
AC_CHECK_HEADERS(linux/major.h)
+# For hugepages module
+AC_CHECK_HEADERS(dirent.h)
+
# For md module (Linux only)
if test "x$ac_system" = "xLinux"
then
AC_PLUGIN([gmond], [$with_libganglia], [Ganglia plugin])
AC_PLUGIN([grpc], [$with_grpc], [gRPC plugin])
AC_PLUGIN([hddtemp], [yes], [Query hddtempd])
+AC_PLUGIN([hugepages], [yes], [Hugepages statistics])
AC_PLUGIN([interface], [$plugin_interface], [Interface traffic statistics])
AC_PLUGIN([ipc], [$plugin_ipc], [IPC statistics])
AC_PLUGIN([ipmi], [$plugin_ipmi], [IPMI sensor statistics])
AC_MSG_RESULT([ gmond . . . . . . . . $enable_gmond])
AC_MSG_RESULT([ grpc . . . . . . . . $enable_grpc])
AC_MSG_RESULT([ hddtemp . . . . . . . $enable_hddtemp])
+AC_MSG_RESULT([ hugepages . . . . . . $enable_hugepages])
AC_MSG_RESULT([ interface . . . . . . $enable_interface])
AC_MSG_RESULT([ ipc . . . . . . . . . $enable_ipc])
AC_MSG_RESULT([ ipmi . . . . . . . . $enable_ipmi])
diff --git a/src/Makefile.am b/src/Makefile.am
index 641e2fae53cead1c386f4cbf37671d57f29f0156..0cc7e1cbaf22b8aea1380ae7231c5d67b228c638 100644 (file)
--- a/src/Makefile.am
+++ b/src/Makefile.am
endif
endif
+if BUILD_PLUGIN_HUGEPAGES
+pkglib_LTLIBRARIES += hugepages.la
+hugepages_la_SOURCES = hugepages.c
+hugepages_la_LDFLAGS = $(PLUGIN_LDFLAGS)
+hugepages_la_LIBADD =
+endif
+
if BUILD_PLUGIN_INTERFACE
pkglib_LTLIBRARIES += interface.la
interface_la_SOURCES = interface.c
diff --git a/src/collectd.conf.in b/src/collectd.conf.in
index 54072d0fe63feec2a60f6711929c70cafda8c92e..2b57a6873065ad3bb703ee6994c14b2c61fc8437 100644 (file)
--- a/src/collectd.conf.in
+++ b/src/collectd.conf.in
#@BUILD_PLUGIN_GMOND_TRUE@LoadPlugin gmond
#@BUILD_PLUGIN_GRPC_TRUE@LoadPlugin grpc
#@BUILD_PLUGIN_HDDTEMP_TRUE@LoadPlugin hddtemp
+#@BUILD_PLUGIN_HUGEPAGES_TRUE@LoadPlugin hugepages
@BUILD_PLUGIN_INTERFACE_TRUE@@BUILD_PLUGIN_INTERFACE_TRUE@LoadPlugin interface
#@BUILD_PLUGIN_IPC_TRUE@LoadPlugin ipc
#@BUILD_PLUGIN_IPMI_TRUE@LoadPlugin ipmi
# Port "7634"
#</Plugin>
+#<Plugin hugepages>
+# EnableNuma "true"
+# EnableMM "true"
+#</Plugin>
+
#<Plugin interface>
# Interface "eth0"
# IgnoreSelected false
diff --git a/src/collectd.conf.pod b/src/collectd.conf.pod
index 37a4d6b6f476cee1b7733467df35543be6381d39..0a7bd0144abe57867d875dde4a86705695c477ce 100644 (file)
--- a/src/collectd.conf.pod
+++ b/src/collectd.conf.pod
=back
+=head2 Plugin C<hugepages>
+
+To get values from B<hugepages> collectd read directories
+"/sys/devices/system/node/*/hugepages" and
+"/sys/kernel/mm/hugepages"
+Reading of these directories can be disabled by following
+options. Default is enabled.
+
+=over 4
+
+=item B<EnableNuma> I<true>|I<false>
+
+Enable/Disable reading stats in "/sys/devices/system/node/*/hugepages"
+
+=item B<EnableMM> I<true>|I<false>
+
+Enable/Disable reading stats in "/sys/kernel/mm/hugepages"
+
+=back
+
=head2 Plugin C<interface>
=over 4
diff --git a/src/hugepages.c b/src/hugepages.c
--- /dev/null
+++ b/src/hugepages.c
@@ -0,0 +1,286 @@
+/*-
+ * collectd - src/hugepages.c
+ * MIT License
+ *
+ * Copyright(c) 2016 Intel Corporation. All rights reserved.
+ *
+ * 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:
+ * Jaroslav Safka <jaroslavx.safka@intel.com>
+ */
+
+#include "collectd.h"
+#include "common.h" /* auxiliary functions */
+#include "plugin.h" /* plugin_register_*, plugin_dispatch_values */
+
+#include <stdio.h>
+#include <string.h>
+#include <dirent.h>
+
+static int huge_read (void);
+static int huge_config_callback (const char *key, const char *val);
+
+static const char PLUGIN_NAME[] = "hugepages";
+static const char SYS_NODE[] = "/sys/devices/system/node";
+static const char NODE[] = "node";
+static const char HUGEPAGES_DIR[] = "hugepages";
+static const char SYS_NODE_HUGEPAGES[] = "/sys/devices/system/node/%s/hugepages";
+static const char SYS_MM_HUGEPAGES[] = "/sys/kernel/mm/hugepages";
+static const char CONFIG_NAME[] = "hugepages";
+static const char CFG_ENA_NUMA[] = "EnableNuma";
+static const char CFG_ENA_MM[] = "EnableMM";
+
+static const char *CONFIG_KEYS[] = {
+ CFG_ENA_NUMA,
+ CFG_ENA_MM,
+};
+static const size_t CONFIG_KEYS_NUM = sizeof(CONFIG_KEYS)/sizeof(*CONFIG_NAME);
+static int g_config_ena_numa = 1;
+static int g_config_ena_mm = 1;
+
+static int huge_config_callback (const char *key, const char *val)
+{
+ INFO("HugePages config key='%s', val='%s'", key, val);
+
+ if (0 == strcasecmp(key, CFG_ENA_NUMA)) {
+ g_config_ena_numa = IS_TRUE(val);
+ return 0;
+ }
+ if (0 == strcasecmp(key, CFG_ENA_MM)) {
+ g_config_ena_mm = IS_TRUE(val);
+ return 0;
+ }
+
+ return -1;
+}
+
+static void submit_one (const char *plug_inst, const char *type,
+ const char *type_instance, derive_t value)
+{
+ value_t values[1];
+ value_list_t vl = VALUE_LIST_INIT;
+
+ values[0].derive = value;
+
+ vl.values = values;
+ vl.values_len = 1;
+ sstrncpy (vl.host, hostname_g, sizeof (vl.host));
+ sstrncpy (vl.plugin, PLUGIN_NAME, sizeof (vl.plugin));
+ sstrncpy (vl.plugin_instance, plug_inst, sizeof (vl.plugin_instance));
+ sstrncpy (vl.type, type, sizeof (vl.type));
+
+ if (type_instance != NULL) {
+ sstrncpy (vl.type_instance, type_instance, sizeof (vl.type_instance));
+ }
+
+ DEBUG("submit_one pl_inst:%s, inst_type %s, type %s, val=%lu",
+ plug_inst, type_instance, type, value);
+
+ plugin_dispatch_values (&vl);
+}
+
+static int read_hugepage_entry(const char *path, const char* entry,
+ const char* plinst, const char* hpsize)
+{
+ char path2[512];
+ long value = 0;
+ snprintf(path2, sizeof(path2), "%s/%s", path, entry);
+
+ FILE *fh = fopen(path2, "rt");
+ if (NULL == fh) {
+ ERROR("Cannot open %s", path2);
+ return -1;
+ }
+
+ if (fscanf(fh, "%ld", &value) !=1) {
+ ERROR("Cannot parse file %s", path2);
+ fclose(fh);
+ return -1;
+ }
+
+ submit_one (plinst, entry, hpsize, value);
+
+ fclose(fh);
+ return 0;
+}
+
+static int read_syshugepage_dir(const char* path, const char* dirhpsize,
+ const char* node)
+{
+ DIR *dir = NULL;
+ struct dirent *entry = NULL;
+ struct dirent *result = NULL;
+ size_t name_max = 0;
+ size_t len = 0;
+
+ dir = opendir(path);
+ if (NULL == dir) {
+ ERROR("Cannot open directory %s", path);
+ return -1;
+ }
+
+ name_max = pathconf(path, _PC_NAME_MAX);
+ if (name_max == -1) { /* Limit not defined, or error */
+ name_max = 255; /* Take a guess */
+ }
+
+ len = offsetof(struct dirent, d_name) + name_max + 1;
+ entry = malloc(len);
+ if (entry == NULL) {
+ ERROR("Malloc returned NULL");
+ return -1;
+ }
+
+ while (0 == readdir_r(dir, entry, &result)) {
+ if (NULL == result) {
+ /* end of dir */
+ break;
+ }
+ if (result->d_name[0] == '.') {
+ /* not interesting "." and ".." */
+ continue;
+ }
+
+ read_hugepage_entry(path, result->d_name, node, dirhpsize);
+ }
+
+ free(entry);
+ closedir(dir);
+
+
+ return 0;
+}
+
+static int read_syshugepages(const char* path, const char* node)
+{
+ DIR *dir = NULL;
+ struct dirent *entry = NULL;
+ struct dirent *result = NULL;
+ size_t name_max = 0;
+ size_t len = 0;
+ char path2[255];
+
+ dir = opendir(path);
+ if (NULL == dir) {
+ ERROR("Cannot open directory %s", path);
+ return -1;
+ }
+
+ name_max = pathconf(path, _PC_NAME_MAX);
+ if (name_max == -1) { /* Limit not defined, or error */
+ name_max = 255; /* Take a guess */
+ }
+ len = offsetof(struct dirent, d_name) + name_max + 1;
+ entry = malloc(len);
+ if (entry == NULL) {
+ ERROR("Malloc returned NULL");
+ return -1;
+ }
+
+ while (0 == readdir_r(dir, entry, &result)) {
+ /* read "hugepages-XXXXXkB" entries */
+ if (NULL == result) {
+ /* end of dir */
+ break;
+ }
+
+ if (strncmp(result->d_name, HUGEPAGES_DIR, sizeof(HUGEPAGES_DIR)-1)) {
+ /* not node dir */
+ continue;
+ }
+
+ /* /sys/devices/system/node/node?/hugepages/ */
+ snprintf(path2, sizeof(path2), "%s/%s", path, result->d_name);
+ read_syshugepage_dir(path2, result->d_name, node);
+ }
+
+ free(entry);
+ closedir(dir);
+
+ return 0;
+}
+
+static int read_nodes(void)
+{
+ DIR *dir = NULL;
+ struct dirent *entry = NULL;
+ struct dirent *result = NULL;
+ size_t name_max = 0;
+ size_t len = 0;
+ char path[255];
+
+ dir = opendir(SYS_NODE);
+ if (NULL == dir) {
+ ERROR("Cannot open directory %s", SYS_NODE);
+ return -1;
+ }
+
+ name_max = pathconf(SYS_NODE, _PC_NAME_MAX);
+ if (name_max == -1) { /* Limit not defined, or error */
+ name_max = 255; /* Take a guess */
+ }
+ len = offsetof(struct dirent, d_name) + name_max + 1;
+ entry = malloc(len);
+ if (entry == NULL) {
+ ERROR("Malloc returned NULL");
+ return -1;
+ }
+
+ while (0 == readdir_r(dir, entry, &result)) {
+ if (NULL == result) {
+ /* end of dir */
+ break;
+ }
+
+ if (strncmp(result->d_name, NODE, sizeof(NODE)-1)) {
+ /* not node dir */
+ continue;
+ }
+
+ snprintf(path, sizeof(path), SYS_NODE_HUGEPAGES, result->d_name);
+ read_syshugepages(path, result->d_name);
+ }
+
+ free(entry);
+ closedir(dir);
+
+ return 0;
+}
+
+
+static int huge_read (void)
+{
+ if (g_config_ena_mm) {
+ read_syshugepages(SYS_MM_HUGEPAGES, "mm");
+ }
+ if (g_config_ena_numa) {
+ read_nodes();
+ }
+
+ return 0;
+}
+
+void module_register (void)
+{
+ plugin_register_config(CONFIG_NAME, huge_config_callback, CONFIG_KEYS,
+ CONFIG_KEYS_NUM);
+ plugin_register_read (PLUGIN_NAME, huge_read);
+}
+
diff --git a/src/types.db b/src/types.db
index 77a9d06f68e02a0eb86e140824f902d1872c1e34..8a1581a4e3b6cd7ac15f6b775f9e7acd87501b13 100644 (file)
--- a/src/types.db
+++ b/src/types.db
files value:GAUGE:0:U
flow value:GAUGE:0:U
fork_rate value:DERIVE:0:U
+free_hugepages value:DERIVE:0:U
frequency value:GAUGE:0:U
frequency_error value:GAUGE:-2:2
frequency_offset value:GAUGE:-1000000:1000000
node_rssi value:GAUGE:0:255
node_stat value:DERIVE:0:U
node_tx_rate value:GAUGE:0:127
+nr_overcommit_hugepages value:DERIVE:0:U
+nr_hugepages value:DERIVE:0:U
+nr_hugepages_mempolicy value:DERIVE:0:U
objects value:GAUGE:0:U
operations value:DERIVE:0:U
packets value:DERIVE:0:U
requests value:GAUGE:0:U
response_code value:GAUGE:0:U
response_time value:GAUGE:0:U
+resv_hugepages value:DERIVE:0:U
root_delay value:GAUGE:U:U
root_dispersion value:GAUGE:U:U
route_etx value:GAUGE:0:U
spam_check value:GAUGE:0:U
spam_score value:GAUGE:U:U
spl value:GAUGE:U:U
+surplus_hugepages value:DERIVE:0:U
swap value:GAUGE:0:1099511627776
swap_io value:DERIVE:0:U
tcp_connections value:GAUGE:0:4294967295