summaryrefslogtreecommitdiffstats
path: root/collectors/proc.plugin/ipc.c
diff options
context:
space:
mode:
Diffstat (limited to 'collectors/proc.plugin/ipc.c')
-rw-r--r--collectors/proc.plugin/ipc.c118
1 files changed, 115 insertions, 3 deletions
diff --git a/collectors/proc.plugin/ipc.c b/collectors/proc.plugin/ipc.c
index b16e8b7c8..048fe74a7 100644
--- a/collectors/proc.plugin/ipc.c
+++ b/collectors/proc.plugin/ipc.c
@@ -65,6 +65,11 @@ struct message_queue {
struct message_queue * next;
};
+struct shm_stats {
+ unsigned long long segments;
+ unsigned long long bytes;
+};
+
static inline int ipc_sem_get_limits(struct ipc_limits *lim) {
static procfile *ff = NULL;
static int error_shown = 0;
@@ -179,7 +184,7 @@ int ipc_msq_get_info(char *msg_filename, struct message_queue **message_queue_ro
struct message_queue *msq;
if(unlikely(!ff)) {
- ff = procfile_open(config_get("plugin:proc:ipc", "msg filename to monitor", msg_filename), " \t:", PROCFILE_FLAG_DEFAULT);
+ ff = procfile_open(msg_filename, " \t:", PROCFILE_FLAG_DEFAULT);
if(unlikely(!ff)) return 1;
}
@@ -230,10 +235,49 @@ int ipc_msq_get_info(char *msg_filename, struct message_queue **message_queue_ro
return 0;
}
+int ipc_shm_get_info(char *shm_filename, struct shm_stats *shm) {
+ static procfile *ff;
+
+ if(unlikely(!ff)) {
+ ff = procfile_open(shm_filename, " \t:", PROCFILE_FLAG_DEFAULT);
+ if(unlikely(!ff)) return 1;
+ }
+
+ ff = procfile_readall(ff);
+ if(unlikely(!ff)) return 1;
+
+ size_t lines = procfile_lines(ff);
+ size_t words = 0;
+
+ if(unlikely(lines < 2)) {
+ error("Cannot read %s. Expected 2 or more lines, read %zu.", ff->filename, lines);
+ return 1;
+ }
+
+ shm->segments = 0;
+ shm->bytes = 0;
+
+ // loop through all lines except the first and the last ones
+ size_t l;
+ for(l = 1; l < lines - 1; l++) {
+ words = procfile_linewords(ff, l);
+ if(unlikely(words < 2)) continue;
+ if(unlikely(words < 16)) {
+ error("Cannot read %s line. Expected 16 params, read %zu.", ff->filename, words);
+ continue;
+ }
+
+ shm->segments++;
+ shm->bytes += str2ull(procfile_lineword(ff, l, 3));
+ }
+
+ return 0;
+}
+
int do_ipc(int update_every, usec_t dt) {
(void)dt;
- static int do_sem = -1, do_msg = -1;
+ static int do_sem = -1, do_msg = -1, do_shm = -1;
static int read_limits_next = -1;
static struct ipc_limits limits;
static struct ipc_status status;
@@ -243,15 +287,21 @@ int do_ipc(int update_every, usec_t dt) {
static char *msg_filename = NULL;
static struct message_queue *message_queue_root = NULL;
static long long dimensions_limit;
+ static char *shm_filename = NULL;
if(unlikely(do_sem == -1)) {
- do_sem = config_get_boolean("plugin:proc:ipc", "semaphore totals", CONFIG_BOOLEAN_YES);
do_msg = config_get_boolean("plugin:proc:ipc", "message queues", CONFIG_BOOLEAN_YES);
+ do_sem = config_get_boolean("plugin:proc:ipc", "semaphore totals", CONFIG_BOOLEAN_YES);
+ do_shm = config_get_boolean("plugin:proc:ipc", "shared memory totals", CONFIG_BOOLEAN_YES);
char filename[FILENAME_MAX + 1];
+
snprintfz(filename, FILENAME_MAX, "%s%s", netdata_configured_host_prefix, "/proc/sysvipc/msg");
msg_filename = config_get("plugin:proc:ipc", "msg filename to monitor", filename);
+ snprintfz(filename, FILENAME_MAX, "%s%s", netdata_configured_host_prefix, "/proc/sysvipc/shm");
+ shm_filename = config_get("plugin:proc:ipc", "shm filename to monitor", filename);
+
dimensions_limit = config_get_number("plugin:proc:ipc", "max dimensions in memory allowed", 50);
// make sure it works
@@ -460,5 +510,67 @@ int do_ipc(int update_every, usec_t dt) {
}
}
+ // --------------------------------------------------------------------
+
+ if(likely(do_shm != CONFIG_BOOLEAN_NO)) {
+ static RRDSET *st_shm_segments = NULL, *st_shm_bytes = NULL;
+ static RRDDIM *rd_shm_segments = NULL, *rd_shm_bytes = NULL;
+ struct shm_stats shm;
+
+ if(!ipc_shm_get_info(shm_filename, &shm)) {
+ if(unlikely(!st_shm_segments)) {
+ st_shm_segments = rrdset_create_localhost(
+ "system"
+ , "shared_memory_segments"
+ , NULL
+ , "ipc shared memory"
+ , NULL
+ , "IPC Shared Memory Number of Segments"
+ , "segments"
+ , PLUGIN_PROC_NAME
+ , "ipc"
+ , NETDATA_CHART_PRIO_SYSTEM_IPC_SHARED_MEM_SEGS
+ , update_every
+ , RRDSET_TYPE_STACKED
+ );
+
+ rd_shm_segments = rrddim_add(st_shm_segments, "segments", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE);
+ }
+ else
+ rrdset_next(st_shm_segments);
+
+ rrddim_set_by_pointer(st_shm_segments, rd_shm_segments, shm.segments);
+
+ rrdset_done(st_shm_segments);
+
+ // --------------------------------------------------------------------
+
+ if(unlikely(!st_shm_bytes)) {
+ st_shm_bytes = rrdset_create_localhost(
+ "system"
+ , "shared_memory_bytes"
+ , NULL
+ , "ipc shared memory"
+ , NULL
+ , "IPC Shared Memory Used Bytes"
+ , "bytes"
+ , PLUGIN_PROC_NAME
+ , "ipc"
+ , NETDATA_CHART_PRIO_SYSTEM_IPC_SHARED_MEM_SIZE
+ , update_every
+ , RRDSET_TYPE_STACKED
+ );
+
+ rd_shm_bytes = rrddim_add(st_shm_bytes, "bytes", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE);
+ }
+ else
+ rrdset_next(st_shm_bytes);
+
+ rrddim_set_by_pointer(st_shm_bytes, rd_shm_bytes, shm.bytes);
+
+ rrdset_done(st_shm_bytes);
+ }
+ }
+
return 0;
}