X-Git-Url: https://git.octo.it/?a=blobdiff_plain;f=src%2Fhugepages.c;h=e066300beb799460f0b12b0f991740ef62983452;hb=48efd3deb4c9139fd060ff3d289896e9031bcc7c;hp=9fa535f019ba005be1fbad1b48e41563f83e9823;hpb=624012732bd5db5449c58d9a0f9d844fb4a391c1;p=collectd.git diff --git a/src/hugepages.c b/src/hugepages.c index 9fa535f0..e066300b 100644 --- a/src/hugepages.c +++ b/src/hugepages.c @@ -25,22 +25,22 @@ * Authors: * Jaroslav Safka * Kim-Marie Jones + * Florian Forster */ #include "collectd.h" -#include "common.h" /* auxiliary functions */ -#include "plugin.h" /* plugin_register_*, plugin_dispatch_values */ + +#include "plugin.h" /* plugin_register_*, plugin_dispatch_values */ +#include "utils/common/common.h" /* auxiliary functions */ static const char g_plugin_name[] = "hugepages"; -static const char g_cfg_rpt_numa[] = "ReportPerNodeHP"; -static const char g_cfg_rpt_mm[] = "ReportRootHP"; -static const char *g_config_keys[] = { - g_cfg_rpt_numa, g_cfg_rpt_mm, -}; -static size_t g_config_keys_num = STATIC_ARRAY_SIZE(g_config_keys); -static int g_flag_rpt_numa = 1; -static int g_flag_rpt_mm = 1; +static bool g_flag_rpt_numa = true; +static bool g_flag_rpt_mm = true; + +static bool g_values_pages = true; +static bool g_values_bytes; +static bool g_values_percent; #define HP_HAVE_NR 0x01 #define HP_HAVE_SURPLUS 0x02 @@ -50,6 +50,7 @@ static int g_flag_rpt_mm = 1; struct entry_info { char *d_name; const char *node; + size_t page_size_kb; gauge_t nr; gauge_t surplus; @@ -57,56 +58,74 @@ struct entry_info { uint8_t flags; }; -static int huge_config_callback(const char *key, const char *val) { - DEBUG("%s: HugePages config key='%s', val='%s'", g_plugin_name, key, val); - - if (strcasecmp(key, g_cfg_rpt_numa) == 0) { - g_flag_rpt_numa = IS_TRUE(val); - return 0; - } - if (strcasecmp(key, g_cfg_rpt_mm) == 0) { - g_flag_rpt_mm = IS_TRUE(val); - return 0; +static int hp_config(oconfig_item_t *ci) { + for (int i = 0; i < ci->children_num; i++) { + oconfig_item_t *child = ci->children + i; + if (strcasecmp("ReportPerNodeHP", child->key) == 0) + cf_util_get_boolean(child, &g_flag_rpt_numa); + else if (strcasecmp("ReportRootHP", child->key) == 0) + cf_util_get_boolean(child, &g_flag_rpt_mm); + else if (strcasecmp("ValuesPages", child->key) == 0) + cf_util_get_boolean(child, &g_values_pages); + else if (strcasecmp("ValuesBytes", child->key) == 0) + cf_util_get_boolean(child, &g_values_bytes); + else if (strcasecmp("ValuesPercentage", child->key) == 0) + cf_util_get_boolean(child, &g_values_percent); + else + ERROR("%s: Invalid configuration option: \"%s\".", g_plugin_name, + child->key); } - return -1; + return 0; } -static void submit_hp(const char *plug_inst, const char *type_instance, - gauge_t free_value, gauge_t used_value) { +static void submit_hp(const struct entry_info *info) { value_list_t vl = VALUE_LIST_INIT; - value_t values[] = { - { .gauge = free_value }, - { .gauge = used_value }, - }; - - vl.values = values; - vl.values_len = STATIC_ARRAY_SIZE (values); - sstrncpy(vl.host, hostname_g, sizeof(vl.host)); - sstrncpy(vl.plugin, g_plugin_name, sizeof(vl.plugin)); - sstrncpy(vl.plugin_instance, plug_inst, sizeof(vl.plugin_instance)); - sstrncpy(vl.type, "hugepages", sizeof(vl.type)); - if (type_instance != NULL) { - sstrncpy(vl.type_instance, type_instance, sizeof(vl.type_instance)); + vl.values = &(value_t){.gauge = NAN}; + vl.values_len = 1; + + sstrncpy(vl.plugin, g_plugin_name, sizeof(vl.plugin)); + if (info->node) { + snprintf(vl.plugin_instance, sizeof(vl.plugin_instance), "%s-%zuKb", + info->node, info->page_size_kb); + } else { + snprintf(vl.plugin_instance, sizeof(vl.plugin_instance), "%zuKb", + info->page_size_kb); } - DEBUG("submit_hp pl_inst:%s, inst_type %s, free=%lf, used=%lf", plug_inst, - type_instance, free_value, used_value); + /* ensure all metrics have the same timestamp */ + vl.time = cdtime(); + + gauge_t free = info->free; + gauge_t used = (info->nr + info->surplus) - info->free; - plugin_dispatch_values(&vl); + if (g_values_pages) { + sstrncpy(vl.type, "vmpage_number", sizeof(vl.type)); + plugin_dispatch_multivalue(&vl, /* store_percentage = */ false, + DS_TYPE_GAUGE, "free", free, "used", used, NULL); + } + if (g_values_bytes) { + gauge_t page_size = (gauge_t)(1024 * info->page_size_kb); + sstrncpy(vl.type, "memory", sizeof(vl.type)); + plugin_dispatch_multivalue(&vl, /* store_percentage = */ false, + DS_TYPE_GAUGE, "free", free * page_size, "used", + used * page_size, NULL); + } + if (g_values_percent) { + sstrncpy(vl.type, "percent", sizeof(vl.type)); + plugin_dispatch_multivalue(&vl, /* store_percentage = */ true, + DS_TYPE_GAUGE, "free", free, "used", used, NULL); + } } static int read_hugepage_entry(const char *path, const char *entry, void *e_info) { char path2[PATH_MAX]; - static const char partial_type_inst[] = "free_used"; - char type_instance[PATH_MAX]; - char *strin; struct entry_info *info = e_info; double value; - ssnprintf(path2, sizeof(path2), "%s/%s", path, entry); + snprintf(path2, sizeof(path2), "%s/%s", path, entry); FILE *fh = fopen(path2, "rt"); if (fh == NULL) { @@ -136,19 +155,7 @@ static int read_hugepage_entry(const char *path, const char *entry, return 0; } - /* Can now submit "used" and "free" values. - * 0x2D is the ASCII "-" character, after which the string - * contains "kB" - * The string passed as param 3 to submit_hp is of the format: - * --kB - */ - assert(strncmp(info->d_name, "hugepages-", strlen("hugepages-")) == 0); - strin = info->d_name += strlen("hugepages-"); - - ssnprintf(type_instance, sizeof(type_instance), "%s-%s", partial_type_inst, - strin); - submit_hp(info->node, type_instance, info->free, - (info->nr + info->surplus) - info->free); + submit_hp(info); /* Reset flags so subsequent calls don't submit again. */ info->flags = 0; @@ -175,12 +182,22 @@ static int read_syshugepages(const char *path, const char *node) { continue; } + long page_size = strtol(result->d_name + strlen(hugepages_dir), + /* endptr = */ NULL, /* base = */ 10); + if (errno != 0) { + ERROR("%s: failed to determine page size from directory name \"%s\": %s", + g_plugin_name, result->d_name, STRERRNO); + continue; + } + /* /sys/devices/system/node/node?/hugepages/ */ - ssnprintf(path2, sizeof(path2), "%s/%s", path, result->d_name); + snprintf(path2, sizeof(path2), "%s/%s", path, result->d_name); walk_directory(path2, read_hugepage_entry, &(struct entry_info){ - .d_name = result->d_name, .node = node, + .d_name = result->d_name, + .node = node, + .page_size_kb = (size_t)page_size, }, /* hidden = */ 0); errno = 0; @@ -219,7 +236,7 @@ static int read_nodes(void) { continue; } - ssnprintf(path, sizeof(path), sys_node_hugepages, result->d_name); + snprintf(path, sizeof(path), sys_node_hugepages, result->d_name); read_syshugepages(path, result->d_name); errno = 0; } @@ -253,7 +270,6 @@ static int huge_read(void) { } void module_register(void) { - plugin_register_config(g_plugin_name, huge_config_callback, g_config_keys, - g_config_keys_num); + plugin_register_complex_config(g_plugin_name, hp_config); plugin_register_read(g_plugin_name, huge_read); }