diff options
Diffstat (limited to 'collectors/proc.plugin/ipc.c')
-rw-r--r-- | collectors/proc.plugin/ipc.c | 118 |
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; } |