* Clément Stenac <clement.stenac at diwi.org>
* Cosmin Ioiart <cioiart at gmail.com>
* Pavel Rochnyack <pavel2000 at ngs.ru>
+ * Wilfried Goesgens <dothebart at citadel.org>
**/
#include "collectd.h"
unsigned long num_proc;
unsigned long num_lwp;
unsigned long num_fd;
+ unsigned long num_maps;
unsigned long vmem_size;
unsigned long vmem_rss;
unsigned long vmem_data;
_Bool has_cswitch;
_Bool has_fd;
+
+ _Bool has_maps;
} process_entry_t;
typedef struct procstat_entry_s {
unsigned long num_proc;
unsigned long num_lwp;
unsigned long num_fd;
+ unsigned long num_maps;
unsigned long vmem_size;
unsigned long vmem_rss;
unsigned long vmem_data;
derive_t cswitch_invol;
_Bool report_fd_num;
+ _Bool report_maps_num;
_Bool report_ctx_switch;
struct procstat *next;
static _Bool want_init = 1;
static _Bool report_ctx_switch = 0;
static _Bool report_fd_num = 0;
+static _Bool report_maps_num = 0;
#if HAVE_THREAD_INFO
static mach_port_t port_host_self;
new->cswitch_invol = -1;
new->report_fd_num = report_fd_num;
+ new->report_maps_num = report_maps_num;
new->report_ctx_switch = report_ctx_switch;
#if HAVE_REGEX_H
ps->num_proc += entry->num_proc;
ps->num_lwp += entry->num_lwp;
ps->num_fd += entry->num_fd;
+ ps->num_maps += entry->num_maps;
ps->vmem_size += entry->vmem_size;
ps->vmem_rss += entry->vmem_rss;
ps->vmem_data += entry->vmem_data;
ps->num_proc = 0;
ps->num_lwp = 0;
ps->num_fd = 0;
+ ps->num_maps = 0;
ps->vmem_size = 0;
ps->vmem_rss = 0;
ps->vmem_data = 0;
cf_util_get_boolean(c, &ps->report_ctx_switch);
else if (strcasecmp(c->key, "CollectFileDescriptor") == 0)
cf_util_get_boolean(c, &ps->report_fd_num);
+ else if (strcasecmp(c->key, "CollectMemoryMaps") == 0)
+ cf_util_get_boolean(c, &ps->report_maps_num);
else {
ERROR("processes plugin: Option `%s' not allowed here.", c->key);
}
cf_util_get_boolean(c, &report_ctx_switch);
} else if (strcasecmp(c->key, "CollectFileDescriptor") == 0) {
cf_util_get_boolean(c, &report_fd_num);
+ } else if (strcasecmp(c->key, "CollectMemoryMaps") == 0) {
+ cf_util_get_boolean(c, &report_maps_num);
} else {
ERROR("processes plugin: The `%s' configuration option is not "
"understood and will be ignored.",
plugin_dispatch_values(&vl);
if ((ps->io_rchar != -1) && (ps->io_wchar != -1)) {
- sstrncpy(vl.type, "io_octets", sizeof(vl.type));
+ sstrncpy(vl.type, "ps_disk_octets", sizeof(vl.type));
vl.values[0].derive = ps->io_rchar;
vl.values[1].derive = ps->io_wchar;
vl.values_len = 2;
plugin_dispatch_values(&vl);
}
- if (ps->num_fd > 0) {
+ if (ps->num_fd > 0) {
sstrncpy(vl.type, "file_handles", sizeof(vl.type));
vl.values[0].gauge = ps->num_fd;
vl.values_len = 1;
plugin_dispatch_values(&vl);
}
+ if (ps->num_maps > 0) {
+ sstrncpy(vl.type, "memory_maps", sizeof(vl.type));
+ vl.values[0].gauge = ps->num_maps;
+ vl.values_len = 1;
+ plugin_dispatch_values(&vl);
+ }
+
if ((ps->cswitch_vol != -1) && (ps->cswitch_invol != -1)) {
sstrncpy(vl.type, "contextswitch", sizeof(vl.type));
sstrncpy(vl.type_instance, "voluntary", sizeof(vl.type_instance));
plugin_dispatch_values(&vl);
}
- DEBUG("name = %s; num_proc = %lu; num_lwp = %lu; num_fd = %lu; "
+ DEBUG("name = %s; num_proc = %lu; num_lwp = %lu; num_fd = %lu; num_maps = %lu; "
"vmem_size = %lu; vmem_rss = %lu; vmem_data = %lu; "
"vmem_code = %lu; "
"vmem_minflt_counter = %" PRIi64 "; vmem_majflt_counter = %" PRIi64 "; "
"io_syscr = %" PRIi64 "; io_syscw = %" PRIi64 "; "
"io_diskr = %" PRIi64 "; io_diskw = %" PRIi64 "; "
"cswitch_vol = %" PRIi64 "; cswitch_invol = %" PRIi64 ";",
- ps->name, ps->num_proc, ps->num_lwp, ps->num_fd, ps->vmem_size,
+ ps->name, ps->num_proc, ps->num_lwp, ps->num_fd, ps->num_maps, ps->vmem_size,
ps->vmem_rss, ps->vmem_data, ps->vmem_code, ps->vmem_minflt_counter,
ps->vmem_majflt_counter, ps->cpu_user_counter, ps->cpu_system_counter,
ps->io_rchar, ps->io_wchar, ps->io_syscr, ps->io_syscw, ps->io_diskr,
ps->io_diskw, ps->cswitch_vol, ps->cswitch_invol);
+
} /* void ps_submit_proc_list */
#if KERNEL_LINUX || KERNEL_SOLARIS
return 0;
} /* int ps_read_io (...) */
+static int ps_count_maps(pid_t pid) {
+ FILE *fh;
+ char buffer[1024];
+ char filename[64];
+ int count = 0;
+
+ snprintf(filename, sizeof(filename), "/proc/%d/maps", pid);
+ if ((fh = fopen(filename, "r")) == NULL) {
+ DEBUG("ps_count_maps: Failed to open file `%s'", filename);
+ return -1;
+ }
+
+ while (fgets(buffer, sizeof(buffer), fh) != NULL) {
+ if (strchr(buffer, '\n')) {
+ count ++;
+ }
+ } /* while (fgets) */
+
+ if (fclose(fh)) {
+ char errbuf[1024];
+ WARNING("processes: fclose: %s", sstrerror(errno, errbuf, sizeof(errbuf)));
+ }
+ return count;
+} /* int ps_count_maps (...) */
+
static int ps_count_fd(int pid) {
char dirname[64];
DIR *dh;
}
}
+ if (ps->report_maps_num) {
+ int num_maps;
+ if (entry->has_maps == 0 && (num_maps = ps_count_maps(entry->id)) > 0) {
+ entry->num_maps = num_maps;
+ }
+ entry->has_maps = 1;
+ }
+
if (ps->report_fd_num) {
int num_fd;
if (entry->has_fd == 0 && (num_fd = ps_count_fd(entry->id)) > 0) {
*/
ps->num_fd = 0;
+ /* Number of memory mappings */
+ ps->num_maps = 0;
+
/*
* Calculating input/ouput chars
* Formula used is total chars / total blocks => chars/block
/* File descriptor count not implemented */
pse.num_fd = 0;
+ /* Number of memory mappings */
+ pse.num_maps = 0;
+
pse.vmem_minflt_counter = task_events_info.cow_faults;
pse.vmem_majflt_counter = task_events_info.faults;
/* file descriptor count not implemented */
pse.num_fd = 0;
+ /* Number of memory mappings */
+ pse.num_maps = 0;
+
/* context switch counters not implemented */
pse.cswitch_vol = -1;
pse.cswitch_invol = -1;
/* file descriptor count not implemented */
pse.num_fd = 0;
+ /* Number of memory mappings */
+ pse.num_maps = 0;
+
/* context switch counters not implemented */
pse.cswitch_vol = -1;
pse.cswitch_invol = -1;
pse.io_diskw = -1;
pse.num_fd = 0;
+ pse.num_maps = 0;
pse.cswitch_vol = -1;
pse.cswitch_invol = -1;