summaryrefslogtreecommitdiffstats
path: root/collectors/proc.plugin
diff options
context:
space:
mode:
authorVladimir Kobal <vlad@prokk.net>2019-03-06 20:19:34 +0200
committerGitHub <noreply@github.com>2019-03-06 20:19:34 +0200
commit9653ee0d6852030e4e89cc9d8cf8d6b96d6b74bc (patch)
treec065ee89584695a8f200faa88a19c1f752dee3c9 /collectors/proc.plugin
parentc7ddf8d2ea407ba2717e07a51aa631ca26739c3a (diff)
Add IPC shared memory charts (#5522)
Diffstat (limited to 'collectors/proc.plugin')
-rw-r--r--collectors/proc.plugin/README.md35
-rw-r--r--collectors/proc.plugin/ipc.c118
2 files changed, 138 insertions, 15 deletions
diff --git a/collectors/proc.plugin/README.md b/collectors/proc.plugin/README.md
index b505bced27..c484b11d65 100644
--- a/collectors/proc.plugin/README.md
+++ b/collectors/proc.plugin/README.md
@@ -387,12 +387,12 @@ and metrics:
```
[plugin:proc:/sys/class/power_supply]
- # battery capacity = yes
- # battery charge = no
- # battery energy = no
- # power supply voltage = no
- # keep files open = auto
- # directory to monitor = /sys/class/power_supply
+ # battery capacity = yes
+ # battery charge = no
+ # battery energy = no
+ # power supply voltage = no
+ # keep files open = auto
+ # directory to monitor = /sys/class/power_supply
```
#### notes
@@ -413,16 +413,27 @@ This way, alerts which match on these will still work.
## IPC
-This module monitors the number of semaphores, semaphore arrays, number of messages in message queues, and amount of memory used by message queues. As far as the message queue charts are dynamic, sane limits are applied for the number of dimensions per chart (the limit is configurable).
+### Monitored IPC metrics
-#### configuration
+- **number of messages in message queues**
+- **amount of memory used by message queues**
+- **number of semaphores**
+- **number of semaphore arrays**
+- **number of shared memory segments**
+- **amount of memory used by shared memory segments**
+
+As far as the message queue charts are dynamic, sane limits are applied for the number of dimensions per chart (the limit is configurable).
+
+### configuration
```
[plugin:proc:ipc]
- # semaphore totals = yes
- # message queues = yes
- # msg filename to monitor = /proc/sysvipc/msg
- # max dimensions in memory allowed = 50
+ # message queues = yes
+ # semaphore totals = yes
+ # shared memory totals = yes
+ # msg filename to monitor = /proc/sysvipc/msg
+ # shm filename to monitor = /proc/sysvipc/shm
+ # max dimensions in memory allowed = 50
```
[![analytics](https://www.google-analytics.com/collect?v=1&aip=1&t=pageview&_s=1&ds=github&dr=https%3A%2F%2Fgithub.com%2Fnetdata%2Fnetdata&dl=https%3A%2F%2Fmy-netdata.io%2Fgithub%2Fcollectors%2Fproc.plugin%2FREADME&_u=MAC~&cid=5792dfd7-8dc4-476b-af31-da2fdb9f93d2&tid=UA-64295674-3)]()
diff --git a/collectors/proc.plugin/ipc.c b/collectors/proc.plugin/ipc.c
index b16e8b7c8e..048fe74a7a 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;
}