Browse Source

Add IPC shared memory charts (#5522)

Vladimir Kobal 6 years ago
parent
commit
9653ee0d68
3 changed files with 145 additions and 22 deletions
  1. 7 7
      collectors/all.h
  2. 23 12
      collectors/proc.plugin/README.md
  3. 115 3
      collectors/proc.plugin/ipc.c

+ 7 - 7
collectors/all.h

@@ -53,13 +53,13 @@
 #define NETDATA_CHART_PRIO_SYSTEM_SOFT_INTR           1100 // freebsd only
 #define NETDATA_CHART_PRIO_SYSTEM_ENTROPY             1000
 #define NETDATA_CHART_PRIO_SYSTEM_UPTIME              1000
-#define NETDATA_CHART_PRIO_SYSTEM_IPC_MSQ_QUEUES       990 // freebsd only
-#define NETDATA_CHART_PRIO_SYSTEM_IPC_MSQ_MESSAGES    1000
-#define NETDATA_CHART_PRIO_SYSTEM_IPC_MSQ_SIZE        1100
-#define NETDATA_CHART_PRIO_SYSTEM_IPC_SEMAPHORES      1000
-#define NETDATA_CHART_PRIO_SYSTEM_IPC_SEM_ARRAYS      1000
-#define NETDATA_CHART_PRIO_SYSTEM_IPC_SHARED_MEM_SEGS 1000 // freebsd only
-#define NETDATA_CHART_PRIO_SYSTEM_IPC_SHARED_MEM_SIZE 1000 // freebsd only
+#define NETDATA_CHART_PRIO_SYSTEM_IPC_MSQ_QUEUES      1200 // freebsd only
+#define NETDATA_CHART_PRIO_SYSTEM_IPC_MSQ_MESSAGES    1201
+#define NETDATA_CHART_PRIO_SYSTEM_IPC_MSQ_SIZE        1202
+#define NETDATA_CHART_PRIO_SYSTEM_IPC_SEMAPHORES      1203
+#define NETDATA_CHART_PRIO_SYSTEM_IPC_SEM_ARRAYS      1204
+#define NETDATA_CHART_PRIO_SYSTEM_IPC_SHARED_MEM_SEGS 1205
+#define NETDATA_CHART_PRIO_SYSTEM_IPC_SHARED_MEM_SIZE 1206
 #define NETDATA_CHART_PRIO_SYSTEM_PACKETS             7001 // freebsd only
 
 

+ 23 - 12
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)]()

+ 115 - 3
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;
 }