Skip to content

Commit

Permalink
in_node_exporter_metrics: Implement NVMe metrics (#8049)
Browse files Browse the repository at this point in the history
Signed-off-by: Hiroshi Hatake <[email protected]>
  • Loading branch information
cosmo0920 authored Nov 7, 2023
1 parent 3d42367 commit 880c715
Show file tree
Hide file tree
Showing 6 changed files with 300 additions and 2 deletions.
1 change: 1 addition & 0 deletions plugins/in_node_exporter_metrics/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ set(src
ne_filefd.c
ne_textfile.c
ne_processes.c
ne_nvme.c
ne_utils.c
ne_config.c
ne_systemd.c
Expand Down
10 changes: 9 additions & 1 deletion plugins/in_node_exporter_metrics/ne.c
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@
#include "ne_textfile.h"
#include "ne_systemd.h"
#include "ne_processes.h"
#include "ne_nvme.h"

/*
* Update the metrics, this function is invoked every time 'scrape_interval'
Expand Down Expand Up @@ -114,7 +115,7 @@ static int get_interval_property(struct flb_ne *ctx, flb_sds_t name)
return interval;
}

static int activate_collector(struct flb_ne *ctx, struct flb_config *config,
static int activate_collector(struct flb_ne *ctx, struct flb_config *config,
struct flb_ne_collector *coll, flb_sds_t name)
{
int interval;
Expand Down Expand Up @@ -190,6 +191,7 @@ static int in_ne_init(struct flb_input_instance *in,
mk_list_add(&textfile_collector._head, &ctx->collectors);
mk_list_add(&systemd_collector._head, &ctx->collectors);
mk_list_add(&processes_collector._head, &ctx->collectors);
mk_list_add(&nvme_collector._head, &ctx->collectors);

mk_list_foreach(head, &ctx->collectors) {
coll = mk_list_entry(head, struct flb_ne_collector, _head);
Expand Down Expand Up @@ -401,6 +403,12 @@ static struct flb_config_map config_map[] = {
"scrape interval to collect processes metrics from the node."
},

{
FLB_CONFIG_MAP_TIME, "collector.nvme.scrape_interval", "0",
0, FLB_FALSE, 0,
"scrape interval to collect nvme metrics from the node."
},

{
FLB_CONFIG_MAP_CLIST, "metrics",
NE_DEFAULT_ENABLED_METRICS,
Expand Down
5 changes: 4 additions & 1 deletion plugins/in_node_exporter_metrics/ne.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@
/* Default enabled metrics */

#ifdef __linux__
#define NE_DEFAULT_ENABLED_METRICS "cpu,cpufreq,meminfo,diskstats,filesystem,uname,stat,time,loadavg,vmstat,netdev,filefd,systemd"
#define NE_DEFAULT_ENABLED_METRICS "cpu,cpufreq,meminfo,diskstats,filesystem,uname,stat,time,loadavg,vmstat,netdev,filefd,systemd,nvme"
#elif __APPLE__
#define NE_DEFAULT_ENABLED_METRICS "cpu,loadavg,meminfo,diskstats,uname,netdev"
#endif
Expand Down Expand Up @@ -203,6 +203,9 @@ struct flb_ne {
struct cmt_gauge *processes_procs_state;
struct cmt_gauge *processes_pid_used;
struct cmt_gauge *processes_pid_max;

/* nvme */
struct cmt_gauge *nvme_info;
};

struct flb_ne_collector {
Expand Down
32 changes: 32 additions & 0 deletions plugins/in_node_exporter_metrics/ne_nvme.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */

/* Fluent Bit
* ==========
* Copyright (C) 2023 The Fluent Bit Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

#ifdef __linux__
#include "ne_nvme_linux.c"
#else

#include "ne.h"

struct flb_ne_collector nvme_collector = {
.name = "nvme",
.cb_init = NULL,
.cb_update = NULL,
.cb_exit = NULL
};
#endif
27 changes: 27 additions & 0 deletions plugins/in_node_exporter_metrics/ne_nvme.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */

/* Fluent Bit
* ==========
* Copyright (C) 2023 The Fluent Bit Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

#ifndef FLB_IN_NE_NVME_H
#define FLB_IN_NE_NVME_H

#include "ne.h"

extern struct flb_ne_collector nvme_collector;

#endif
227 changes: 227 additions & 0 deletions plugins/in_node_exporter_metrics/ne_nvme_linux.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,227 @@
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */

/* Fluent Bit
* ==========
* Copyright (C) 2023 The Fluent Bit Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

#include <fluent-bit/flb_info.h>
#include <fluent-bit/flb_sds.h>
#include <fluent-bit/flb_input_plugin.h>

#include "ne.h"
#include "ne_utils.h"

#include <unistd.h>


static int nvme_configure(struct flb_ne *ctx)
{
struct cmt_gauge *g;

/* node_nvme_info */
g = cmt_gauge_create(ctx->cmt, "node", "nvme", "info",
"Non-numeric data from /sys/class/nvme/<device>",
5, (char *[]){"device", "firmware_revision", "model", "serial", "state"});
if (!g) {
return -1;
}
ctx->nvme_info = g;

return 0;
}

static int check_path_for_sysfs(struct flb_ne *ctx, const char *prefix, const char *path)
{
int len;
flb_sds_t p;

/* Compose the proc path */
p = flb_sds_create(prefix);
if (!p) {
return -1;
}

if (path) {
flb_sds_cat_safe(&p, "/", 1);
len = strlen(path);
flb_sds_cat_safe(&p, path, len);
}

if (access(p, F_OK) == -1 &&
(errno == ENOENT || errno == ESRCH)) {
flb_plg_debug(ctx->ins, "error reading stat for path %s. errno = %d", p, errno);
flb_sds_destroy(p);

return -1;
}

flb_sds_destroy(p);
return 0;
}

struct nvme_sys_info {
char *name;
char *serial;
char *model;
char *state;
char *firmware_revision;
};

static void cleanup_nvme_sys_info(struct nvme_sys_info *info)
{
if (info == NULL) {
return;
}

/* Note: name member is not allocated. Just for using reference. */
flb_sds_destroy(info->serial);
flb_sds_destroy(info->model);
flb_sds_destroy(info->state);
flb_sds_destroy(info->firmware_revision);
}

static int nvme_get_entry_value(struct flb_ne *ctx,
char *entry_path,
struct flb_slist_entry *nvme_info,
struct mk_list *out_info_list)
{
int ret;
char nvme_sysentry[PATH_MAX];
snprintf(nvme_sysentry, sizeof(nvme_sysentry) - 1, "/%s", entry_path);

if (check_path_for_sysfs(ctx, nvme_info->str, entry_path) != 0) {
return -1;
}
ret = ne_utils_file_read_lines(nvme_info->str, nvme_sysentry, out_info_list);
if (ret == -1) {
return ret;
}

return 0;
}

static int nvme_update(struct flb_ne *ctx)
{
int ret;
flb_sds_t device_str;
flb_sds_t tmp;
const char *pattern = "/nvme[0-9]*";
struct mk_list *head;
struct mk_list nvme_class_list;
struct mk_list nvme_firmware;
struct mk_list nvme_model;
struct mk_list nvme_serial;
struct mk_list nvme_state;
struct flb_slist_entry *nvme_info;
struct flb_slist_entry *entry;
uint64_t ts;
char *nvme_class_path = "/sys/class/nvme";
struct nvme_sys_info nvme_sinfo = {
.name = "",
.serial = "",
.model = "",
.state = "",
.firmware_revision = ""
};

mk_list_init(&nvme_class_list);

ts = cfl_time_now();

/* scan nvme entries */
ret = ne_utils_path_scan(ctx, nvme_class_path, pattern, NE_SCAN_DIR, &nvme_class_list);
if (ret != 0) {
return -1;
}

if (mk_list_size(&nvme_class_list) == 0) {
return 0;
}

mk_list_foreach(head, &nvme_class_list) {
nvme_info = mk_list_entry(head, struct flb_slist_entry, _head);
device_str = nvme_info->str + strlen(nvme_class_path) + 1;
nvme_sinfo.name = device_str;

mk_list_init(&nvme_firmware);
if (nvme_get_entry_value(ctx, "firmware_rev", nvme_info, &nvme_firmware) == 0) {
entry = mk_list_entry_first(&nvme_firmware, struct flb_slist_entry, _head);
tmp = flb_sds_create_len(entry->str, strlen(entry->str));
flb_sds_trim(tmp);
nvme_sinfo.firmware_revision = tmp;
}

mk_list_init(&nvme_model);
if (nvme_get_entry_value(ctx, "model", nvme_info, &nvme_model) == 0) {
entry = mk_list_entry_first(&nvme_model, struct flb_slist_entry, _head);
tmp = flb_sds_create_len(entry->str, strlen(entry->str));
flb_sds_trim(tmp);
nvme_sinfo.model = tmp;
}

mk_list_init(&nvme_serial);
if (nvme_get_entry_value(ctx, "serial", nvme_info, &nvme_serial) == 0) {
entry = mk_list_entry_first(&nvme_serial, struct flb_slist_entry, _head);
tmp = flb_sds_create_len(entry->str, strlen(entry->str));
flb_sds_trim(tmp);
nvme_sinfo.serial = tmp;
}

mk_list_init(&nvme_state);
if (nvme_get_entry_value(ctx, "state", nvme_info, &nvme_state) == 0) {
entry = mk_list_entry_first(&nvme_state, struct flb_slist_entry, _head);
tmp = flb_sds_create_len(entry->str, strlen(entry->str));
flb_sds_trim(tmp);
nvme_sinfo.state = tmp;
}

cmt_gauge_set(ctx->nvme_info, ts, 1,
5, (char *[]){ nvme_sinfo.name, nvme_sinfo.firmware_revision, nvme_sinfo.model,
nvme_sinfo.serial, nvme_sinfo.state});

flb_slist_destroy(&nvme_firmware);
flb_slist_destroy(&nvme_model);
flb_slist_destroy(&nvme_serial);
flb_slist_destroy(&nvme_state);

cleanup_nvme_sys_info(&nvme_sinfo);
}
flb_slist_destroy(&nvme_class_list);

return 0;
}


static int ne_nvme_init(struct flb_ne *ctx)
{
nvme_configure(ctx);
return 0;
}

static int ne_nvme_update(struct flb_input_instance *ins, struct flb_config *config, void *in_context)
{
struct flb_ne *ctx = (struct flb_ne *)in_context;

nvme_update(ctx);
return 0;
}

struct flb_ne_collector nvme_collector = {
.name = "nvme",
.cb_init = ne_nvme_init,
.cb_update = ne_nvme_update,
.cb_exit = NULL
};

0 comments on commit 880c715

Please sign in to comment.