Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add IPC shared memory charts #5522

Merged
merged 1 commit into from Mar 6, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
14 changes: 7 additions & 7 deletions collectors/all.h
Expand Up @@ -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


Expand Down
35 changes: 23 additions & 12 deletions collectors/proc.plugin/README.md
Expand Up @@ -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
Expand All @@ -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)]()
118 changes: 115 additions & 3 deletions collectors/proc.plugin/ipc.c
Expand Up @@ -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;
Expand Down Expand Up @@ -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;
}

Expand Down Expand Up @@ -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;
Expand All @@ -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
Expand Down Expand Up @@ -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;
}