summaryrefslogtreecommitdiffstats
path: root/collectors/apps.plugin/apps_plugin.c
diff options
context:
space:
mode:
Diffstat (limited to 'collectors/apps.plugin/apps_plugin.c')
-rw-r--r--collectors/apps.plugin/apps_plugin.c851
1 files changed, 641 insertions, 210 deletions
diff --git a/collectors/apps.plugin/apps_plugin.c b/collectors/apps.plugin/apps_plugin.c
index 3132b2243..105c54262 100644
--- a/collectors/apps.plugin/apps_plugin.c
+++ b/collectors/apps.plugin/apps_plugin.c
@@ -2,7 +2,7 @@
/*
* netdata apps.plugin
- * (C) Copyright 2016-2017 Costa Tsaousis <costa@tsaousis.gr>
+ * (C) Copyright 2023 Netdata Inc.
* Released under GPL v3+
*/
@@ -106,6 +106,7 @@ static int
enable_file_charts = 1,
max_fds_cache_seconds = 60,
#endif
+ enable_function_cmdline = 0,
enable_detailed_uptime_charts = 0,
enable_users_charts = 1,
enable_groups_charts = 1,
@@ -140,6 +141,17 @@ static const char *proc_states[] = {
// internal flags
// handled in code (automatically set)
+// log each problem once per process
+// log flood protection flags (log_thrown)
+typedef enum __attribute__((packed)) {
+ PID_LOG_IO = (1 << 0),
+ PID_LOG_STATUS = (1 << 1),
+ PID_LOG_CMDLINE = (1 << 2),
+ PID_LOG_FDS = (1 << 3),
+ PID_LOG_STAT = (1 << 4),
+ PID_LOG_LIMITS = (1 << 5),
+} PID_LOG;
+
static int
show_guest_time = 0, // 1 when guest values are collected
show_guest_time_old = 0,
@@ -168,7 +180,7 @@ static size_t
// the metrics. This results in utilization that exceeds the total utilization
// of the system.
//
-// With normalization we align the per-process utilization, to the total of
+// During normalization, we align the per-process utilization, to the total of
// the system. We first consume the exited children utilization and it the
// collected values is above the total, we proportionally scale each reported
// metric.
@@ -210,6 +222,27 @@ struct openfds {
kernel_uint_t other;
};
+#define pid_openfds_sum(p) ((p)->openfds.files + (p)->openfds.pipes + (p)->openfds.sockets + (p)->openfds.inotifies + (p)->openfds.eventfds + (p)->openfds.timerfds + (p)->openfds.signalfds + (p)->openfds.eventpolls + (p)->openfds.other)
+
+struct pid_limits {
+// kernel_uint_t max_cpu_time;
+// kernel_uint_t max_file_size;
+// kernel_uint_t max_data_size;
+// kernel_uint_t max_stack_size;
+// kernel_uint_t max_core_file_size;
+// kernel_uint_t max_resident_set;
+// kernel_uint_t max_processes;
+ kernel_uint_t max_open_files;
+// kernel_uint_t max_locked_memory;
+// kernel_uint_t max_address_space;
+// kernel_uint_t max_file_locks;
+// kernel_uint_t max_pending_signals;
+// kernel_uint_t max_msgqueue_size;
+// kernel_uint_t max_nice_priority;
+// kernel_uint_t max_realtime_priority;
+// kernel_uint_t max_realtime_timeout;
+};
+
// ----------------------------------------------------------------------------
// target
//
@@ -267,6 +300,8 @@ struct target {
struct openfds openfds;
+ NETDATA_DOUBLE max_open_files_percent;
+
kernel_uint_t starttime;
kernel_uint_t collected_starttime;
kernel_uint_t uptime_min;
@@ -317,12 +352,6 @@ struct pid_fd {
struct pid_stat {
int32_t pid;
- char comm[MAX_COMPARE_NAME + 1];
- char *cmdline;
-
- uint32_t log_thrown;
-
- char state;
int32_t ppid;
// int32_t pgrp;
// int32_t session;
@@ -330,6 +359,11 @@ struct pid_stat {
// int32_t tpgid;
// uint64_t flags;
+ char state;
+
+ char comm[MAX_COMPARE_NAME + 1];
+ char *cmdline;
+
// these are raw values collected
kernel_uint_t minflt_raw;
kernel_uint_t cminflt_raw;
@@ -414,22 +448,30 @@ struct pid_stat {
kernel_uint_t io_storage_bytes_written;
kernel_uint_t io_cancelled_write_bytes;
+ kernel_uint_t uptime;
+
struct pid_fd *fds; // array of fds it uses
size_t fds_size; // the size of the fds array
struct openfds openfds;
+ struct pid_limits limits;
- int children_count; // number of processes directly referencing this
- unsigned char keep:1; // 1 when we need to keep this process in memory even after it exited
- int keeploops; // increases by 1 every time keep is 1 and updated 0
- unsigned char updated:1; // 1 when the process is currently running
- unsigned char merged:1; // 1 when it has been merged to its parent
- unsigned char read:1; // 1 when we have already read this process for this iteration
+ NETDATA_DOUBLE openfds_limits_percent;
int sortlist; // higher numbers = top on the process tree
// each process gets a unique number
+ int children_count; // number of processes directly referencing this
+ int keeploops; // increases by 1 every time keep is 1 and updated 0
+
+ PID_LOG log_thrown;
+
+ bool keep; // true when we need to keep this process in memory even after it exited
+ bool updated; // true when the process is currently running
+ bool merged; // true when it has been merged to its parent
+ bool read; // true when we have already read this process for this iteration
bool matched_by_config;
+
struct target *target; // app_groups.conf targets
struct target *user_target; // uid based targets
struct target *group_target; // gid based targets
@@ -439,8 +481,7 @@ struct pid_stat {
usec_t io_collected_usec;
usec_t last_io_collected_usec;
-
- kernel_uint_t uptime;
+ usec_t last_limits_collected_usec;
char *fds_dirname; // the full directory name in /proc/PID/fd
@@ -448,6 +489,7 @@ struct pid_stat {
char *status_filename;
char *io_filename;
char *cmdline_filename;
+ char *limits_filename;
struct pid_stat *parent;
struct pid_stat *prev;
@@ -458,14 +500,6 @@ size_t pagesize;
kernel_uint_t global_uptime;
-// log each problem once per process
-// log flood protection flags (log_thrown)
-#define PID_LOG_IO 0x00000001
-#define PID_LOG_STATUS 0x00000002
-#define PID_LOG_CMDLINE 0x00000004
-#define PID_LOG_FDS 0x00000008
-#define PID_LOG_STAT 0x00000010
-
static struct pid_stat
*root_of_pids = NULL, // global list of all processes running
**all_pids = NULL; // to avoid allocations, we pre-allocate
@@ -524,8 +558,6 @@ static int
all_files_len = 0,
all_files_size = 0;
-long currentmaxfds = 0;
-
// ----------------------------------------------------------------------------
// read users and groups from files
@@ -665,7 +697,7 @@ int read_user_or_group_ids(struct user_or_group_ids *ids, struct timespec *last_
}
else {
if(unlikely(avl_insert(&ids->index, (avl_t *) user_or_group_id) != (void *) user_or_group_id)) {
- error("INTERNAL ERROR: duplicate indexing of id during realloc");
+ netdata_log_error("INTERNAL ERROR: duplicate indexing of id during realloc");
};
user_or_group_id->next = ids->root;
@@ -681,7 +713,7 @@ int read_user_or_group_ids(struct user_or_group_ids *ids, struct timespec *last_
while(user_or_group_id) {
if(unlikely(!user_or_group_id->updated)) {
if(unlikely((struct user_or_group_id *)avl_remove(&ids->index, (avl_t *) user_or_group_id) != user_or_group_id))
- error("INTERNAL ERROR: removal of unused id from index, removed a different id");
+ netdata_log_error("INTERNAL ERROR: removal of unused id from index, removed a different id");
if(prev_user_id)
prev_user_id->next = user_or_group_id->next;
@@ -946,7 +978,7 @@ static int read_apps_groups_conf(const char *path, const char *file)
// add this target
struct target *n = get_apps_groups_target(s, w, name);
if(!n) {
- error("Cannot create target '%s' (line %zu, word %zu)", s, line, word);
+ netdata_log_error("Cannot create target '%s' (line %zu, word %zu)", s, line, word);
continue;
}
@@ -996,7 +1028,7 @@ static inline void del_pid_entry(pid_t pid) {
struct pid_stat *p = all_pids[pid];
if(unlikely(!p)) {
- error("attempted to free pid %d that is not allocated.", pid);
+ netdata_log_error("attempted to free pid %d that is not allocated.", pid);
return;
}
@@ -1018,6 +1050,7 @@ static inline void del_pid_entry(pid_t pid) {
freez(p->fds_dirname);
freez(p->stat_filename);
freez(p->status_filename);
+ freez(p->limits_filename);
#ifndef __FreeBSD__
arl_free(p->status_arl);
#endif
@@ -1032,9 +1065,9 @@ static inline void del_pid_entry(pid_t pid) {
// ----------------------------------------------------------------------------
-static inline int managed_log(struct pid_stat *p, uint32_t log, int status) {
+static inline int managed_log(struct pid_stat *p, PID_LOG log, int status) {
if(unlikely(!status)) {
- // error("command failed log %u, errno %d", log, errno);
+ // netdata_log_error("command failed log %u, errno %d", log, errno);
if(unlikely(debug_enabled || errno != ENOENT)) {
if(unlikely(debug_enabled || !(p->log_thrown & log))) {
@@ -1042,41 +1075,48 @@ static inline int managed_log(struct pid_stat *p, uint32_t log, int status) {
switch(log) {
case PID_LOG_IO:
#ifdef __FreeBSD__
- error("Cannot fetch process %d I/O info (command '%s')", p->pid, p->comm);
+ netdata_log_error("Cannot fetch process %d I/O info (command '%s')", p->pid, p->comm);
#else
- error("Cannot process %s/proc/%d/io (command '%s')", netdata_configured_host_prefix, p->pid, p->comm);
+ netdata_log_error("Cannot process %s/proc/%d/io (command '%s')", netdata_configured_host_prefix, p->pid, p->comm);
#endif
break;
case PID_LOG_STATUS:
#ifdef __FreeBSD__
- error("Cannot fetch process %d status info (command '%s')", p->pid, p->comm);
+ netdata_log_error("Cannot fetch process %d status info (command '%s')", p->pid, p->comm);
#else
- error("Cannot process %s/proc/%d/status (command '%s')", netdata_configured_host_prefix, p->pid, p->comm);
+ netdata_log_error("Cannot process %s/proc/%d/status (command '%s')", netdata_configured_host_prefix, p->pid, p->comm);
#endif
break;
case PID_LOG_CMDLINE:
#ifdef __FreeBSD__
- error("Cannot fetch process %d command line (command '%s')", p->pid, p->comm);
+ netdata_log_error("Cannot fetch process %d command line (command '%s')", p->pid, p->comm);
#else
- error("Cannot process %s/proc/%d/cmdline (command '%s')", netdata_configured_host_prefix, p->pid, p->comm);
+ netdata_log_error("Cannot process %s/proc/%d/cmdline (command '%s')", netdata_configured_host_prefix, p->pid, p->comm);
#endif
break;
case PID_LOG_FDS:
#ifdef __FreeBSD__
- error("Cannot fetch process %d files (command '%s')", p->pid, p->comm);
+ netdata_log_error("Cannot fetch process %d files (command '%s')", p->pid, p->comm);
#else
- error("Cannot process entries in %s/proc/%d/fd (command '%s')", netdata_configured_host_prefix, p->pid, p->comm);
+ netdata_log_error("Cannot process entries in %s/proc/%d/fd (command '%s')", netdata_configured_host_prefix, p->pid, p->comm);
#endif
break;
+ case PID_LOG_LIMITS:
+ #ifdef __FreeBSD__
+ ;
+ #else
+ netdata_log_error("Cannot process %s/proc/%d/limits (command '%s')", netdata_configured_host_prefix, p->pid, p->comm);
+ #endif
+
case PID_LOG_STAT:
break;
default:
- error("unhandled error for pid %d, command '%s'", p->pid, p->comm);
+ netdata_log_error("unhandled error for pid %d, command '%s'", p->pid, p->comm);
break;
}
}
@@ -1084,7 +1124,7 @@ static inline int managed_log(struct pid_stat *p, uint32_t log, int status) {
errno = 0;
}
else if(unlikely(p->log_thrown & log)) {
- // error("unsetting log %u on pid %d", log, p->pid);
+ // netdata_log_error("unsetting log %u on pid %d", log, p->pid);
p->log_thrown &= ~log;
}
@@ -1276,8 +1316,7 @@ void arl_callback_status_voluntary_ctxt_switches(const char *name, uint32_t hash
if(unlikely(procfile_linewords(aptr->ff, aptr->line) < 2)) return;
struct pid_stat *p = aptr->p;
- pid_incremental_rate(
- stat, p->status_voluntary_ctxt_switches, str2kernel_uint_t(procfile_lineword(aptr->ff, aptr->line, 1)));
+ pid_incremental_rate(stat, p->status_voluntary_ctxt_switches, str2kernel_uint_t(procfile_lineword(aptr->ff, aptr->line, 1)));
}
void arl_callback_status_nonvoluntary_ctxt_switches(const char *name, uint32_t hash, const char *value, void *dst) {
@@ -1286,8 +1325,7 @@ void arl_callback_status_nonvoluntary_ctxt_switches(const char *name, uint32_t h
if(unlikely(procfile_linewords(aptr->ff, aptr->line) < 2)) return;
struct pid_stat *p = aptr->p;
- pid_incremental_rate(
- stat, p->status_nonvoluntary_ctxt_switches, str2kernel_uint_t(procfile_lineword(aptr->ff, aptr->line, 1)));
+ pid_incremental_rate(stat, p->status_nonvoluntary_ctxt_switches, str2kernel_uint_t(procfile_lineword(aptr->ff, aptr->line, 1)));
}
static void update_proc_state_count(char proc_state) {
@@ -1313,6 +1351,64 @@ static void update_proc_state_count(char proc_state) {
}
#endif // !__FreeBSD__
+#define MAX_PROC_PID_LIMITS 8192
+#define PROC_PID_LIMITS_MAX_OPEN_FILES_KEY "\nMax open files "
+
+static inline kernel_uint_t get_proc_pid_limits_limit(char *buf, const char *key, size_t key_len, kernel_uint_t def) {
+ char *line = strstr(buf, key);
+ if(!line)
+ return def;
+
+ char *v = &line[key_len];
+ while(isspace(*v)) v++;
+
+ return str2ull(v, NULL);
+}
+
+static inline int read_proc_pid_limits(struct pid_stat *p, void *ptr) {
+ (void)ptr;
+
+#ifdef __FreeBSD__
+ return 0;
+#else
+ static char proc_pid_limits_buffer[MAX_PROC_PID_LIMITS + 1];
+ int ret = 0;
+
+ kernel_uint_t all_fds = pid_openfds_sum(p);
+ if(all_fds < p->limits.max_open_files / 2 && p->io_collected_usec > p->last_limits_collected_usec && p->io_collected_usec - p->last_limits_collected_usec <= 60 * USEC_PER_SEC)
+ // too frequent, we want to collect limits once per minute
+ goto cleanup;
+
+ if(unlikely(!p->limits_filename)) {
+ char filename[FILENAME_MAX + 1];
+ snprintfz(filename, FILENAME_MAX, "%s/proc/%d/limits", netdata_configured_host_prefix, p->pid);
+ p->limits_filename = strdupz(filename);
+ }
+
+ int fd = open(p->limits_filename, procfile_open_flags, 0666);
+ if(unlikely(fd == -1)) goto cleanup;
+
+ ssize_t bytes = read(fd, proc_pid_limits_buffer, MAX_PROC_PID_LIMITS);
+ close(fd);
+
+ if(bytes <= 0)
+ goto cleanup;
+
+ p->limits.max_open_files = get_proc_pid_limits_limit(proc_pid_limits_buffer, PROC_PID_LIMITS_MAX_OPEN_FILES_KEY, sizeof(PROC_PID_LIMITS_MAX_OPEN_FILES_KEY) - 1, 0);
+ p->last_limits_collected_usec = p->io_collected_usec;
+
+ ret = 1;
+
+cleanup:
+ if(p->limits.max_open_files)
+ p->openfds_limits_percent = (NETDATA_DOUBLE)all_fds * 100.0 / (NETDATA_DOUBLE)p->limits.max_open_files;
+ else
+ p->openfds_limits_percent = 0.0;
+
+ return ret;
+#endif
+}
+
static inline int read_proc_pid_status(struct pid_stat *p, void *ptr) {
p->status_vmsize = 0;
p->status_vmrss = 0;
@@ -1470,7 +1566,7 @@ static inline int read_proc_pid_stat(struct pid_stat *p, void *ptr) {
if(enable_guest_charts) {
enable_guest_charts = 0;
- info("Guest charts aren't supported by FreeBSD");
+ netdata_log_info("Guest charts aren't supported by FreeBSD");
}
#else
pid_incremental_rate(stat, p->minflt, str2kernel_uint_t(procfile_lineword(ff, 0, 9)));
@@ -1732,7 +1828,7 @@ cleanup:
int file_descriptor_compare(void* a, void* b) {
#ifdef NETDATA_INTERNAL_CHECKS
if(((struct file_descriptor *)a)->magic != 0x0BADCAFE || ((struct file_descriptor *)b)->magic != 0x0BADCAFE)
- error("Corrupted index data detected. Please report this.");
+ netdata_log_error("Corrupted index data detected. Please report this.");
#endif /* NETDATA_INTERNAL_CHECKS */
if(((struct file_descriptor *)a)->hash < ((struct file_descriptor *)b)->hash)
@@ -1776,7 +1872,7 @@ static inline void file_descriptor_not_used(int id)
#ifdef NETDATA_INTERNAL_CHECKS
if(all_files[id].magic != 0x0BADCAFE) {
- error("Ignoring request to remove empty file id %d.", id);
+ netdata_log_error("Ignoring request to remove empty file id %d.", id);
return;
}
#endif /* NETDATA_INTERNAL_CHECKS */
@@ -1790,7 +1886,7 @@ static inline void file_descriptor_not_used(int id)
debug_log(" >> slot %d is empty.", id);
if(unlikely(file_descriptor_remove(&all_files[id]) != (void *)&all_files[id]))
- error("INTERNAL ERROR: removal of unused fd from index, removed a different fd");
+ netdata_log_error("INTERNAL ERROR: removal of unused fd from index, removed a different fd");
#ifdef NETDATA_INTERNAL_CHECKS
all_files[id].magic = 0x00000000;
@@ -1799,9 +1895,14 @@ static inline void file_descriptor_not_used(int id)
}
}
else
- error("Request to decrease counter of fd %d (%s), while the use counter is 0", id, all_files[id].name);
+ netdata_log_error("Request to decrease counter of fd %d (%s), while the use counter is 0",
+ id,
+ all_files[id].name);
}
- else error("Request to decrease counter of fd %d, which is outside the array size (1 to %d)", id, all_files_size);
+ else
+ netdata_log_error("Request to decrease counter of fd %d, which is outside the array size (1 to %d)",
+ id,
+ all_files_size);
}
static inline void all_files_grow() {
@@ -1823,7 +1924,7 @@ static inline void all_files_grow() {
for(i = 0; i < all_files_size; i++) {
if(!all_files[i].count) continue;
if(unlikely(file_descriptor_add(&all_files[i]) != (void *)&all_files[i]))
- error("INTERNAL ERROR: duplicate indexing of fd during realloc.");
+ netdata_log_error("INTERNAL ERROR: duplicate indexing of fd during realloc.");
}
debug_log(" >> re-indexing done.");
@@ -1864,7 +1965,7 @@ static inline int file_descriptor_set_on_empty_slot(const char *name, uint32_t h
#ifdef NETDATA_INTERNAL_CHECKS
if(all_files[c].magic == 0x0BADCAFE && all_files[c].name && file_descriptor_find(all_files[c].name, all_files[c].hash))
- error("fd on position %d is not cleared properly. It still has %s in it.", c, all_files[c].name);
+ netdata_log_error("fd on position %d is not cleared properly. It still has %s in it.", c, all_files[c].name);
#endif /* NETDATA_INTERNAL_CHECKS */
debug_log(" >> %s fd position %d for %s (last name: %s)", all_files[c].name?"re-using":"using", c, name, all_files[c].name);
@@ -1895,7 +1996,7 @@ static inline int file_descriptor_set_on_empty_slot(const char *name, uint32_t h
all_files[c].magic = 0x0BADCAFE;
#endif /* NETDATA_INTERNAL_CHECKS */
if(unlikely(file_descriptor_add(&all_files[c]) != (void *)&all_files[c]))
- error("INTERNAL ERROR: duplicate indexing of fd.");
+ netdata_log_error("INTERNAL ERROR: duplicate indexing of fd.");
debug_log("using fd position %d (name: %s)", c, all_files[c].name);
@@ -2013,13 +2114,13 @@ static inline int read_pid_file_descriptors(struct pid_stat *p, void *ptr) {
mib[3] = p->pid;
if (unlikely(sysctl(mib, 4, NULL, &size, NULL, 0))) {
- error("sysctl error: Can't get file descriptors data size for pid %d", p->pid);
+ netdata_log_error("sysctl error: Can't get file descriptors data size for pid %d", p->pid);
return 0;
}
if (likely(size > 0))
fdsbuf = reallocz(fdsbuf, size);
if (unlikely(sysctl(mib, 4, fdsbuf, &size, NULL, 0))) {
- error("sysctl error: Can't get file descriptors data for pid %d", p->pid);
+ netdata_log_error("sysctl error: Can't get file descriptors data for pid %d", p->pid);
return 0;
}
@@ -2192,7 +2293,7 @@ static inline int read_pid_file_descriptors(struct pid_stat *p, void *ptr) {
// cannot read the link
if(debug_enabled || (p->target && p->target->debug_enabled))
- error("Cannot read link %s", p->fds[fdid].filename);
+ netdata_log_error("Cannot read link %s", p->fds[fdid].filename);
if(unlikely(p->fds[fdid].fd < 0)) {
file_descriptor_not_used(-p->fds[fdid].fd);
@@ -2454,7 +2555,7 @@ static inline void process_exited_processes() {
if(majflt) debug_find_lost_child(p, majflt, 2);
}
- p->keep = 1;
+ p->keep = true;
debug_log(" > remaining resources - KEEP - for another loop: %s (%d %s total resources: utime=" KERNEL_UINT_FORMAT " stime=" KERNEL_UINT_FORMAT " gtime=" KERNEL_UINT_FORMAT " minflt=" KERNEL_UINT_FORMAT " majflt=" KERNEL_UINT_FORMAT ")"
, p->comm
@@ -2469,7 +2570,7 @@ static inline void process_exited_processes() {
for(pp = p->parent; pp ; pp = pp->parent) {
if(pp->updated) break;
- pp->keep = 1;
+ pp->keep = true;
debug_log(" > - KEEP - parent for another loop: %s (%d %s)"
, pp->comm
@@ -2523,7 +2624,7 @@ static inline void link_all_processes_to_their_parents(void) {
}
else {
p->parent = NULL;
- error("pid %d %s states parent %d, but the later does not exist.", p->pid, p->comm, p->ppid);
+ netdata_log_error("pid %d %s states parent %d, but the later does not exist.", p->pid, p->comm, p->ppid);
}
}
}
@@ -2561,13 +2662,13 @@ static int compar_pid(const void *pid1, const void *pid2) {
static inline int collect_data_for_pid(pid_t pid, void *ptr) {
if(unlikely(pid < 0 || pid > pid_max)) {
- error("Invalid pid %d read (expected %d to %d). Ignoring process.", pid, 0, pid_max);
+ netdata_log_error("Invalid pid %d read (expected %d to %d). Ignoring process.", pid, 0, pid_max);
return 0;
}
struct pid_stat *p = get_pid_entry(pid);
if(unlikely(!p || p->read)) return 0;
- p->read = 1;
+ p->read = true;
// debug_log("Reading process %d (%s), sortlist %d", p->pid, p->comm, p->sortlist);
@@ -2580,7 +2681,7 @@ static inline int collect_data_for_pid(pid_t pid, void *ptr) {
// check its parent pid
if(unlikely(p->ppid < 0 || p->ppid > pid_max)) {
- error("Pid %d (command '%s') states invalid parent pid %d. Using 0.", pid, p->comm, p->ppid);
+ netdata_log_error("Pid %d (command '%s') states invalid parent pid %d. Using 0.", pid, p->comm, p->ppid);
p->ppid = 0;
}
@@ -2599,8 +2700,10 @@ static inline int collect_data_for_pid(pid_t pid, void *ptr) {
// --------------------------------------------------------------------
// /proc/<pid>/fd
- if(enable_file_charts)
- managed_log(p, PID_LOG_FDS, read_pid_file_descriptors(p, ptr));
+ if(enable_file_charts) {
+ managed_log(p, PID_LOG_FDS, read_pid_file_descriptors(p, ptr));
+ managed_log(p, PID_LOG_LIMITS, read_proc_pid_limits(p, ptr));
+ }
// --------------------------------------------------------------------
// done!
@@ -2609,8 +2712,8 @@ static inline int collect_data_for_pid(pid_t pid, void *ptr) {
debug_log("Read process %d (%s) sortlisted %d, but its parent %d (%s) sortlisted %d, is not read", p->pid, p->comm, p->sortlist, all_pids[p->ppid]->pid, all_pids[p->ppid]->comm, all_pids[p->ppid]->sortlist);
// mark it as updated
- p->updated = 1;
- p->keep = 0;
+ p->updated = true;
+ p->keep = false;
p->keeploops = 0;
return 1;
@@ -2632,7 +2735,7 @@ static int collect_data_for_all_processes(void) {
int mib[3] = { CTL_KERN, KERN_PROC, KERN_PROC_PROC };
if (unlikely(sysctl(mib, 3, NULL, &new_procbase_size, NULL, 0))) {
- error("sysctl error: Can't get processes data size");
+ netdata_log_error("sysctl error: Can't get processes data size");
return 0;
}
@@ -2652,7 +2755,7 @@ static int collect_data_for_all_processes(void) {
// get the processes from the system
if (unlikely(sysctl(mib, 3, procbase, &new_procbase_size, NULL, 0))) {
- error("sysctl error: Can't get processes data");
+ netdata_log_error("sysctl error: Can't get processes data");
return 0;
}
@@ -2667,9 +2770,9 @@ static int collect_data_for_all_processes(void) {
size_t slc = 0;
#endif
for(p = root_of_pids; p ; p = p->next) {
- p->read = 0; // mark it as not read, so that collect_data_for_pid() will read it
- p->updated = 0;
- p->merged = 0;
+ p->read = false; // mark it as not read, so that collect_data_for_pid() will read it
+ p->updated = false;
+ p->merged = false;
p->children_count = 0;
p->parent = NULL;
@@ -2680,7 +2783,7 @@ static int collect_data_for_all_processes(void) {
#if (ALL_PIDS_ARE_READ_INSTANTLY == 0)
if(unlikely(slc != all_pids_count)) {
- error("Internal error: I was thinking I had %zu processes in my arrays, but it seems there are %zu.", all_pids_count, slc);
+ netdata_log_error("Internal error: I was thinking I had %zu processes in my arrays, but it seems there are %zu.", all_pids_count, slc);
all_pids_count = slc;
}
@@ -2795,7 +2898,7 @@ static void cleanup_exited_pids(void) {
}
else {
if(unlikely(p->keep)) p->keeploops++;
- p->keep = 0;
+ p->keep = false;
p = p->next;
}
}
@@ -2811,7 +2914,7 @@ static void apply_apps_groups_targets_inheritance(void) {
if(unlikely(debug_enabled)) loops++;
found = 0;
for(p = root_of_pids; p ; p = p->next) {
- // if this process does not have a target
+ // if this process does not have a target,
// and it has a parent
// and its parent has a target
// then, set the parent's target to this process
@@ -2849,7 +2952,7 @@ static void apply_apps_groups_targets_inheritance(void) {
)) {
// mark it as merged
p->parent->children_count--;
- p->merged = 1;
+ p->merged = true;
// the parent inherits the child's target, if it does not have a target itself
if(unlikely(p->target && !p->parent->target)) {
@@ -2878,7 +2981,7 @@ static void apply_apps_groups_targets_inheritance(void) {
if(unlikely(debug_enabled)) loops++;
for(p = root_of_pids; p ; p = p->next) {
// if the process is not merged itself
- // then is is a top level process
+ // then it is a top level process
if(unlikely(!p->merged && !p->target))
p->target = apps_groups_default_target;
@@ -2959,6 +3062,8 @@ static size_t zero_all_targets(struct target *root) {
w->openfds.signalfds = 0;
w->openfds.eventpolls = 0;
w->openfds.other = 0;
+
+ w->max_open_files_percent = 0.0;
}
w->collected_starttime = 0;
@@ -3090,9 +3195,6 @@ static inline void aggregate_pid_fds_on_targets(struct pid_stat *p) {
aggregate_fd_on_target(fd, u);
aggregate_fd_on_target(fd, g);
}
-
- if (currentfds >= currentmaxfds)
- currentmaxfds = currentfds;
}
static inline void aggregate_pid_on_target(struct target *w, struct pid_stat *p, struct target *o) {
@@ -3104,10 +3206,13 @@ static inline void aggregate_pid_on_target(struct target *w, struct pid_stat *p,
}
if(unlikely(!w)) {
- error("pid %d %s was left without a target!", p->pid, p->comm);
+ netdata_log_error("pid %d %s was left without a target!", p->pid, p->comm);
return;
}
+ if(p->openfds_limits_percent > w->max_open_files_percent)
+ w->max_open_files_percent = p->openfds_limits_percent;
+
w->cutime += p->cutime;
w->cstime += p->cstime;
w->cgtime += p->cgtime;
@@ -3712,30 +3817,82 @@ static void send_collected_data_to_netdata(struct target *root, const char *type
send_END();
if(enable_file_charts) {
- send_BEGIN(type, "files", dt);
+ send_BEGIN(type, "fds_open_limit", dt);
for (w = root; w; w = w->next) {
if (unlikely(w->exposed && w->processes))
- send_SET(w->name, w->openfds.files);
+ send_SET(w->name, w->max_open_files_percent * 100.0);
}
- if (!strcmp("apps", type)){
- kernel_uint_t usedfdpercentage = (kernel_uint_t) ((currentmaxfds * 100) / sysconf(_SC_OPEN_MAX));
- fprintf(stdout, "VARIABLE fdperc = " KERNEL_UINT_FORMAT "\n", usedfdpercentage);
+ send_END();
+
+ send_BEGIN(type, "fds_open", dt);
+ for (w = root; w; w = w->next) {
+ if (unlikely(w->exposed && w->processes))
+ send_SET(w->name, pid_openfds_sum(w));
}
send_END();
- send_BEGIN(type, "sockets", dt);
+ send_BEGIN(type, "fds_files", dt);
+ for (w = root; w; w = w->next) {
+ if (unlikely(w->exposed && w->processes))
+ send_SET(w->name, w->openfds.files);
+ }
+ send_END();
+
+ send_BEGIN(type, "fds_sockets", dt);
for (w = root; w; w = w->next) {
if (unlikely(w->exposed && w->processes))
send_SET(w->name, w->openfds.sockets);
}
send_END();
- send_BEGIN(type, "pipes", dt);
+ send_BEGIN(type, "fds_pipes", dt);
for (w = root; w; w = w->next) {
if (unlikely(w->exposed && w->processes))
send_SET(w->name, w->openfds.pipes);
}
send_END();
+
+ send_BEGIN(type, "fds_inotifies", dt);
+ for (w = root; w; w = w->next) {
+ if (unlikely(w->exposed && w->processes))
+ send_SET(w->name, w->openfds.inotifies);
+ }
+ send_END();
+
+ send_BEGIN(type, "fds_eventfds", dt);
+ for (w = root; w; w = w->next) {
+ if (unlikely(w->exposed && w->processes))
+ send_SET(w->name, w->openfds.eventfds);
+ }
+ send_END();
+
+ send_BEGIN(type, "fds_timerfds", dt);
+ for (w = root; w; w = w->next) {
+ if (unlikely(w->exposed && w->processes))
+ send_SET(w->name, w->openfds.timerfds);
+ }
+ send_END();
+
+ send_BEGIN(type, "fds_signalfds", dt);
+ for (w = root; w; w = w->next) {
+ if (unlikely(w->exposed && w->processes))
+ send_SET(w->name, w->openfds.signalfds);
+ }
+ send_END();
+
+ send_BEGIN(type, "fds_eventpolls", dt);
+ for (w = root; w; w = w->next) {
+ if (unlikely(w->exposed && w->processes))
+ send_SET(w->name, w->openfds.eventpolls);
+ }
+ send_END();
+
+ send_BEGIN(type, "fds_other", dt);
+ for (w = root; w; w = w->next) {
+ if (unlikely(w->exposed && w->processes))
+ send_SET(w->name, w->openfds.other);
+ }
+ send_END();
}
}
@@ -3958,7 +4115,23 @@ static void send_charts_updates_to_netdata(struct target *root, const char *type
#endif
if(enable_file_charts) {
- fprintf(stdout, "CHART %s.files '' '%s Open Files' 'open files' disk %s.files stacked 20050 %d\n", type,
+ fprintf(stdout, "CHART %s.fds_open_limit '' '%s Open File Descriptors Limit' '%%' fds %s.fds_open_limit line 20050 %d\n", type,
+ title, type, update_every);
+ for (w = root; w; w = w->next) {
+ if (unlikely(w->exposed))
+ fprintf(stdout, "DIMENSION %s '' absolute 1 100\n", w->name);
+ }
+ APPS_PLUGIN_FUNCTIONS();
+
+ fprintf(stdout, "CHART %s.fds_open '' '%s Open File Descriptors' 'fds' fds %s.fds_open stacked 20051 %d\n", type,
+ title, type, update_every);
+ for (w = root; w; w = w->next) {
+ if (unlikely(w->exposed))
+ fprintf(stdout, "DIMENSION %s '' absolute 1 1\n", w->name);
+ }
+ APPS_PLUGIN_FUNCTIONS();
+
+ fprintf(stdout, "CHART %s.fds_files '' '%s Open Files' 'fds' fds %s.fds_files stacked 20052 %d\n", type,
title, type, update_every);
for (w = root; w; w = w->next) {
if (unlikely(w->exposed))
@@ -3966,7 +4139,7 @@ static void send_charts_updates_to_netdata(struct target *root, const char *type
}
APPS_PLUGIN_FUNCTIONS();
- fprintf(stdout, "CHART %s.sockets '' '%s Open Sockets' 'open sockets' net %s.sockets stacked 20051 %d\n",
+ fprintf(stdout, "CHART %s.fds_sockets '' '%s Open Sockets' 'fds' fds %s.fds_sockets stacked 20053 %d\n",
type, title, type, update_every);
for (w = root; w; w = w->next) {
if (unlikely(w->exposed))
@@ -3974,13 +4147,61 @@ static void send_charts_updates_to_netdata(struct target *root, const char *type
}
APPS_PLUGIN_FUNCTIONS();
- fprintf(stdout, "CHART %s.pipes '' '%s Pipes' 'open pipes' processes %s.pipes stacked 20053 %d\n", type,
+ fprintf(stdout, "CHART %s.fds_pipes '' '%s Pipes' 'fds' fds %s.fds_pipes stacked 20054 %d\n", type,
title, type, update_every);
for (w = root; w; w = w->next) {
if (unlikely(w->exposed))
fprintf(stdout, "DIMENSION %s '' absolute 1 1\n", w->name);
}
APPS_PLUGIN_FUNCTIONS();
+
+ fprintf(stdout, "CHART %s.fds_inotifies '' '%s iNotify File Descriptors' 'fds' fds %s.fds_inotifies stacked 20055 %d\n", type,
+ title, type, update_every);
+ for (w = root; w; w = w->next) {
+ if (unlikely(w->exposed))
+ fprintf(stdout, "DIMENSION %s '' absolute 1 1\n", w->name);
+ }
+ APPS_PLUGIN_FUNCTIONS();
+
+ fprintf(stdout, "CHART %s.fds_eventfds '' '%s Event File Descriptors' 'fds' fds %s.fds_eventfds stacked 20056 %d\n", type,
+ title, type, update_every);
+ for (w = root; w; w = w->next) {
+ if (unlikely(w->exposed))
+ fprintf(stdout, "DIMENSION %s '' absolute 1 1\n", w->name);
+ }
+ APPS_PLUGIN_FUNCTIONS();
+
+ fprintf(stdout, "CHART %s.fds_timerfds '' '%s Timer File Descriptors' 'fds' fds %s.fds_timerfds stacked 20057 %d\n", type,
+ title, type, update_every);
+ for (w = root; w; w = w->next) {
+ if (unlikely(w->exposed))
+ fprintf(stdout, "DIMENSION %s '' absolute 1 1\n", w->name);
+ }
+ APPS_PLUGIN_FUNCTIONS();
+
+ fprintf(stdout, "CHART %s.fds_signalfds '' '%s Signal File Descriptors' 'fds' fds %s.fds_signalfds stacked 20058 %d\n", type,
+ title, type, update_every);
+ for (w = root; w; w = w->next) {
+ if (unlikely(w->exposed))
+ fprintf(stdout, "DIMENSION %s '' absolute 1 1\n", w->name);
+ }
+ APPS_PLUGIN_FUNCTIONS();
+
+ fprintf(stdout, "CHART %s.fds_eventpolls '' '%s Event Poll File Descriptors' 'fds' fds %s.fds_eventpolls stacked 20059 %d\n", type,
+ title, type, update_every);
+ for (w = root; w; w = w->next) {
+ if (unlikely(w->exposed))
+ fprintf(stdout, "DIMENSION %s '' absolute 1 1\n", w->name);
+ }
+ APPS_PLUGIN_FUNCTIONS();
+
+ fprintf(stdout, "CHART %s.fds_other '' '%s Other File Descriptors' 'fds' fds %s.fds_other stacked 20060 %d\n", type,
+ title, type, update_every);
+ for (w = root; w; w = w->next) {
+ if (unlikely(w->exposed))
+ fprintf(stdout, "DIMENSION %s '' absolute 1 1\n", w->name);
+ }
+ APPS_PLUGIN_FUNCTIONS();
}
}
@@ -4122,6 +4343,10 @@ static void parse_args(int argc, char **argv)
enable_detailed_uptime_charts = 1;
continue;
}
+ if(strcmp("with-function-cmdline", argv[i]) == 0) {
+ enable_function_cmdline = 1;
+ continue;
+ }
if(strcmp("-h", argv[i]) == 0 || strcmp("--help", argv[i]) == 0) {
fprintf(stderr,
@@ -4139,6 +4364,11 @@ static void parse_args(int argc, char **argv)
"\n"
" debug enable debugging (lot of output)\n"
"\n"
+ " with-function-cmdline enable reporting the complete command line for processes\n"
+ " it includes the command and passed arguments\n"
+ " it may include sensitive data such as passwords and tokens\n"
+ " enabling this could be a security risk\n"
+ "\n"
" with-childs\n"
" without-childs enable / disable aggregating exited\n"
" children resources into parents\n"
@@ -4177,35 +4407,35 @@ static void parse_args(int argc, char **argv)
exit(1);
}
- error("Cannot understand option %s", argv[i]);
+ netdata_log_error("Cannot understand option %s", argv[i]);
exit(1);
}
if(freq > 0) update_every = freq;
if(read_apps_groups_conf(user_config_dir, "groups")) {
- info("Cannot read process groups configuration file '%s/apps_groups.conf'. Will try '%s/apps_groups.conf'", user_config_dir, stock_config_dir);
+ netdata_log_info("Cannot read process groups configuration file '%s/apps_groups.conf'. Will try '%s/apps_groups.conf'", user_config_dir, stock_config_dir);
if(read_apps_groups_conf(stock_config_dir, "groups")) {
- error("Cannot read process groups '%s/apps_groups.conf'. There are no internal defaults. Failing.", stock_config_dir);
+ netdata_log_error("Cannot read process groups '%s/apps_groups.conf'. There are no internal defaults. Failing.", stock_config_dir);
exit(1);
}
else
- info("Loaded config file '%s/apps_groups.conf'", stock_config_dir);
+ netdata_log_info("Loaded config file '%s/apps_groups.conf'", stock_config_dir);
}
else
- info("Loaded config file '%s/apps_groups.conf'", user_config_dir);
+ netdata_log_info("Loaded config file '%s/apps_groups.conf'", user_config_dir);
}
static int am_i_running_as_root() {
uid_t uid = getuid(), euid = geteuid();
if(uid == 0 || euid == 0) {
- if(debug_enabled) info("I am running with escalated privileges, uid = %u, euid = %u.", uid, euid);
+ if(debug_enabled) netdata_log_info("I am running with escalated privileges, uid = %u, euid = %u.", uid, euid);
return 1;
}
- if(debug_enabled) info("I am not running with escalated privileges, uid = %u, euid = %u.", uid, euid);
+ if(debug_enabled) netdata_log_info("I am not running with escalated privileges, uid = %u, euid = %u.", uid, euid);
return 0;
}
@@ -4213,40 +4443,40 @@ static int am_i_running_as_root() {
static int check_capabilities() {
cap_t caps = cap_get_proc();
if(!caps) {
- error("Cannot get current capabilities.");
+ netdata_log_error("Cannot get current capabilities.");
return 0;
}
else if(debug_enabled)
- info("Received my capabilities from the system.");
+ netdata_log_info("Received my capabilities from the system.");
int ret = 1;
cap_flag_value_t cfv = CAP_CLEAR;
if(cap_get_flag(caps, CAP_DAC_READ_SEARCH, CAP_EFFECTIVE, &cfv) == -1) {
- error("Cannot find if CAP_DAC_READ_SEARCH is effective.");
+ netdata_log_error("Cannot find if CAP_DAC_READ_SEARCH is effective.");
ret = 0;
}
else {
if(cfv != CAP_SET) {
- error("apps.plugin should run with CAP_DAC_READ_SEARCH.");
+ netdata_log_error("apps.plugin should run with CAP_DAC_READ_SEARCH.");
ret = 0;
}
else if(debug_enabled)
- info("apps.plugin runs with CAP_DAC_READ_SEARCH.");
+ netdata_log_info("apps.plugin runs with CAP_DAC_READ_SEARCH.");
}
cfv = CAP_CLEAR;
if(cap_get_flag(caps, CAP_SYS_PTRACE, CAP_EFFECTIVE, &cfv) == -1) {
- error("Cannot find if CAP_SYS_PTRACE is effective.");
+ netdata_log_error("Cannot find if CAP_SYS_PTRACE is effective.");
ret = 0;
}
else {
if(cfv != CAP_SET) {
- error("apps.plugin should run with CAP_SYS_PTRACE.");
+ netdata_log_error("apps.plugin should run with CAP_SYS_PTRACE.");
ret = 0;
}
else if(debug_enabled)
- info("apps.plugin runs with CAP_SYS_PTRACE.");
+ netdata_log_info("apps.plugin runs with CAP_SYS_PTRACE.");
}
cap_free(caps);
@@ -4356,32 +4586,6 @@ static void apps_plugin_function_processes_help(const char *transaction) {
pluginsd_function_result_end_to_stdout();
}
-#define add_table_field(wb, key, name, visible, type, visualization, transform, decimal_points, units, max, sort, sortable, sticky, unique_key, pointer_to, summary, range) do { \
- buffer_json_member_add_object(wb, key); \
- buffer_json_member_add_uint64(wb, "index", fields_added); \
- buffer_json_member_add_boolean(wb, "unique_key", unique_key); \
- buffer_json_member_add_string(wb, "name", name); \
- buffer_json_member_add_boolean(wb, "visible", visible); \
- buffer_json_member_add_string(wb, "type", type); \
- buffer_json_member_add_string_or_omit(wb, "units", (char*)(units)); \
- buffer_json_member_add_string(wb, "visualization", visualization); \
- buffer_json_member_add_object(wb, "value_options"); \
- buffer_json_member_add_string_or_omit(wb, "units", (char*)(units)); \
- buffer_json_member_add_string(wb, "transform", transform); \
- buffer_json_member_add_uint64(wb, "decimal_points", decimal_points); \
- buffer_json_object_close(wb); \
- if(!isnan((NETDATA_DOUBLE)(max))) \
- buffer_json_member_add_double(wb, "max", (NETDATA_DOUBLE)(max)); \
- buffer_json_member_add_string_or_omit(wb, "pointer_to", (char *)(pointer_to)); \
- buffer_json_member_add_string(wb, "sort", sort); \
- buffer_json_member_add_boolean(wb, "sortable", sortable); \
- buffer_json_member_add_boolean(wb, "sticky", sticky); \
- buffer_json_member_add_string(wb, "summary", summary); \
- buffer_json_member_add_string(wb, "filter", (range)?"range":"multiselect"); \
- buffer_json_object_close(wb); \
- fields_added++; \
-} while(0)
-
#define add_value_field_llu_with_max(wb, key, value) do { \
unsigned long long _tmp = (value); \
key ## _max = (rows == 0) ? (_tmp) : MAX(key ## _max, _tmp); \
@@ -4398,7 +4602,7 @@ static void apps_plugin_function_processes(const char *transaction, char *functi
struct pid_stat *p;
char *words[PLUGINSD_MAX_WORDS] = { NULL };
- size_t num_words = pluginsd_split_words(function, words, PLUGINSD_MAX_WORDS);
+ size_t num_words = quoted_strings_splitter_pluginsd(function, words, PLUGINSD_MAX_WORDS);
struct target *category = NULL, *user = NULL, *group = NULL;
const char *process_name = NULL;
@@ -4488,6 +4692,7 @@ static void apps_plugin_function_processes(const char *transaction, char *functi
, Shared_max = 0.0
, Swap_max = 0.0
, Memory_max = 0.0
+ , FDsLimitPercent_max = 0.0
;
unsigned long long
@@ -4553,7 +4758,7 @@ static void apps_plugin_function_processes(const char *transaction, char *functi
rows++;
- buffer_json_add_array_item_array(wb);
+ buffer_json_add_array_item_array(wb); // for each pid
// IMPORTANT!
// THE ORDER SHOULD BE THE SAME WITH THE FIELDS!
@@ -4564,10 +4769,10 @@ static void apps_plugin_function_processes(const char *transaction, char *functi
// cmd
buffer_json_add_array_item_string(wb, p->comm);
-#ifdef NETDATA_DEV_MODE
// cmdline
- buffer_json_add_array_item_string(wb, (p->cmdline && *p->cmdline) ? p->cmdline : p->comm);
-#endif
+ if (enable_function_cmdline) {
+ buffer_json_add_array_item_string(wb, (p->cmdline && *p->cmdline) ? p->cmdline : p->comm);
+ }
// ppid
buffer_json_add_array_item_uint64(wb, p->ppid);
@@ -4633,7 +4838,8 @@ static void apps_plugin_function_processes(const char *transaction, char *functi
add_value_field_llu_with_max(wb, TMajFlt, (p->majflt + p->cmajflt) / RATES_DETAIL);
// open file descriptors
- add_value_field_llu_with_max(wb, FDs, p->openfds.files + p->openfds.pipes + p->openfds.sockets + p->openfds.inotifies + p->openfds.eventfds + p->openfds.timerfds + p->openfds.signalfds + p->openfds.eventpolls + p->openfds.other);
+ add_value_field_ndd_with_max(wb, FDsLimitPercent, p->openfds_limits_percent);
+ add_value_field_llu_with_max(wb, FDs, pid_openfds_sum(p));
add_value_field_llu_with_max(wb, Files, p->openfds.files);
add_value_field_llu_with_max(wb, Pipes, p->openfds.pipes);
add_value_field_llu_with_max(wb, Sockets, p->openfds.sockets);
@@ -4644,99 +4850,311 @@ static void apps_plugin_function_processes(const char *transaction, char *functi
add_value_field_llu_with_max(wb, EvPollFDs, p->openfds.eventpolls);
add_value_field_llu_with_max(wb, OtherFDs, p->openfds.other);
+
// processes, threads, uptime
add_value_field_llu_with_max(wb, Processes, p->children_count);
add_value_field_llu_with_max(wb, Threads, p->num_threads);
add_value_field_llu_with_max(wb, Uptime, p->uptime);
- buffer_json_array_close(wb);
+ buffer_json_array_close(wb); // for each pid
}
- buffer_json_array_close(wb);
+ buffer_json_array_close(wb); // data
buffer_json_member_add_object(wb, "columns");
{
- int fields_added = 0;
+ int field_id = 0;
// IMPORTANT!
// THE ORDER SHOULD BE THE SAME WITH THE VALUES!
- add_table_field(wb, "PID", "Process ID", true, "integer", "value", "number", 0, NULL, NAN, "ascending", true, true, true, NULL, "count_unique", false);
- add_table_field(wb, "Cmd", "Process Name", true, "string", "value", "none", 0, NULL, NAN, "ascending", true, true, false, NULL, "count_unique", false);
+ // wb, key, name, visible, type, visualization, transform, decimal_points, units, max, sort, sortable, sticky, unique_key, pointer_to, summary, range
+ buffer_rrdf_table_add_field(wb, field_id++, "PID", "Process ID", RRDF_FIELD_TYPE_INTEGER,
+ RRDF_FIELD_VISUAL_VALUE, RRDF_FIELD_TRANSFORM_NUMBER, 0, NULL, NAN,
+ RRDF_FIELD_SORT_ASCENDING, NULL, RRDF_FIELD_SUMMARY_COUNT,
+ RRDF_FIELD_FILTER_MULTISELECT,
+ RRDF_FIELD_OPTS_VISIBLE | RRDF_FIELD_OPTS_STICKY |
+ RRDF_FIELD_OPTS_UNIQUE_KEY, NULL);
+
+ buffer_rrdf_table_add_field(wb, field_id++, "Cmd", "Process Name", RRDF_FIELD_TYPE_STRING,
+ RRDF_FIELD_VISUAL_VALUE, RRDF_FIELD_TRANSFORM_NONE, 0, NULL, NAN,
+ RRDF_FIELD_SORT_ASCENDING, NULL, RRDF_FIELD_SUMMARY_COUNT,
+ RRDF_FIELD_FILTER_MULTISELECT,
+ RRDF_FIELD_OPTS_VISIBLE | RRDF_FIELD_OPTS_STICKY, NULL);
+
+ if (enable_function_cmdline) {
+ buffer_rrdf_table_add_field(wb, field_id++, "CmdLine", "Command Line", RRDF_FIELD_TYPE_STRING,
+ RRDF_FIELD_VISUAL_VALUE, RRDF_FIELD_TRANSFORM_NONE, 0,
+ NULL, NAN, RRDF_FIELD_SORT_ASCENDING, NULL, RRDF_FIELD_SUMMARY_COUNT,
+ RRDF_FIELD_FILTER_MULTISELECT,
+ RRDF_FIELD_OPTS_NONE, NULL);
+ }
-#ifdef NETDATA_DEV_MODE
- add_table_field(wb, "CmdLine", "Command Line", false, "detail-string:Cmd", "value", "none", 0, NULL, NAN, "ascending", true, false, false, NULL, "count_unique", false);
-#endif
- add_table_field(wb, "PPID", "Parent Process ID", false, "integer", "value", "number", 0, NULL, NAN, "ascending", true, false, false, "PID", "count_unique", false);
- add_table_field(wb, "Category", "Category (apps_groups.conf)", true, "string", "value", "none", 0, NULL, NAN, "ascending", true, true, false, NULL, "count_unique", false);
- add_table_field(wb, "User", "User Owner", true, "string", "value", "none", 0, NULL, NAN, "ascending", true, false, false, NULL, "count_unique", false);
- add_table_field(wb, "Uid", "User ID", false, "integer", "value", "number", 0, NULL, NAN, "ascending", true, false, false, NULL, "count_unique", false);
- add_table_field(wb, "Group", "Group Owner", false, "string", "value", "none", 0, NULL, NAN, "ascending", true, false, false, NULL, "count_unique", false);
- add_table_field(wb, "Gid", "Group ID", false, "integer", "value", "number", 0, NULL, NAN, "ascending", true, false, false, NULL, "count_unique", false);
+ buffer_rrdf_table_add_field(wb, field_id++, "PPID", "Parent Process ID", RRDF_FIELD_TYPE_INTEGER,
+ RRDF_FIELD_VISUAL_VALUE, RRDF_FIELD_TRANSFORM_NUMBER, 0, NULL,
+ NAN, RRDF_FIELD_SORT_ASCENDING, "PID", RRDF_FIELD_SUMMARY_COUNT,
+ RRDF_FIELD_FILTER_MULTISELECT,
+ RRDF_FIELD_OPTS_NONE, NULL);
+ buffer_rrdf_table_add_field(wb, field_id++, "Category", "Category (apps_groups.conf)", RRDF_FIELD_TYPE_STRING,
+ RRDF_FIELD_VISUAL_VALUE,
+ RRDF_FIELD_TRANSFORM_NONE,
+ 0, NULL, NAN, RRDF_FIELD_SORT_ASCENDING, NULL, RRDF_FIELD_SUMMARY_COUNT,
+ RRDF_FIELD_FILTER_MULTISELECT,
+ RRDF_FIELD_OPTS_VISIBLE | RRDF_FIELD_OPTS_STICKY, NULL);
+ buffer_rrdf_table_add_field(wb, field_id++, "User", "User Owner", RRDF_FIELD_TYPE_STRING,
+ RRDF_FIELD_VISUAL_VALUE, RRDF_FIELD_TRANSFORM_NONE, 0, NULL, NAN,
+ RRDF_FIELD_SORT_ASCENDING, NULL, RRDF_FIELD_SUMMARY_COUNT,
+ RRDF_FIELD_FILTER_MULTISELECT,
+ RRDF_FIELD_OPTS_VISIBLE, NULL);
+ buffer_rrdf_table_add_field(wb, field_id++, "Uid", "User ID", RRDF_FIELD_TYPE_INTEGER, RRDF_FIELD_VISUAL_VALUE,
+ RRDF_FIELD_TRANSFORM_NUMBER, 0, NULL, NAN,
+ RRDF_FIELD_SORT_ASCENDING, NULL, RRDF_FIELD_SUMMARY_COUNT,
+ RRDF_FIELD_FILTER_MULTISELECT,
+ RRDF_FIELD_OPTS_NONE, NULL);
+ buffer_rrdf_table_add_field(wb, field_id++, "Group", "Group Owner", RRDF_FIELD_TYPE_STRING,
+ RRDF_FIELD_VISUAL_VALUE, RRDF_FIELD_TRANSFORM_NONE, 0, NULL, NAN,
+ RRDF_FIELD_SORT_ASCENDING, NULL, RRDF_FIELD_SUMMARY_COUNT,
+ RRDF_FIELD_FILTER_MULTISELECT,
+ RRDF_FIELD_OPTS_NONE, NULL);
+ buffer_rrdf_table_add_field(wb, field_id++, "Gid", "Group ID", RRDF_FIELD_TYPE_INTEGER, RRDF_FIELD_VISUAL_VALUE,
+ RRDF_FIELD_TRANSFORM_NUMBER, 0, NULL, NAN,
+ RRDF_FIELD_SORT_ASCENDING, NULL, RRDF_FIELD_SUMMARY_COUNT,
+ RRDF_FIELD_FILTER_MULTISELECT,
+ RRDF_FIELD_OPTS_NONE, NULL);
// CPU utilization
- add_table_field(wb, "CPU", "Total CPU Time (100% = 1 core)", true, "bar-with-integer", "bar", "number", 2, "%", CPU_max, "descending", true, false, false, NULL, "sum", true);
- add_table_field(wb, "UserCPU", "User CPU time (100% = 1 core)", false, "bar-with-integer", "bar", "number", 2, "%", UserCPU_max, "descending", true, false, false, NULL, "sum", true);
- add_table_field(wb, "SysCPU", "System CPU Time (100% = 1 core)", false, "bar-with-integer", "bar", "number", 2, "%", SysCPU_max, "descending", true, false, false, NULL, "sum", true);
- add_table_field(wb, "GuestCPU", "Guest CPU Time (100% = 1 core)", false, "bar-with-integer", "bar", "number", 2, "%", GuestCPU_max, "descending", true, false, false, NULL, "sum", true);
- add_table_field(wb, "CUserCPU", "Children User CPU Time (100% = 1 core)", false, "bar-with-integer", "bar", "number", 2, "%", CUserCPU_max, "descending", true, false, false, NULL, "sum", true);
- add_table_field(wb, "CSysCPU", "Children System CPU Time (100% = 1 core)", false, "bar-with-integer", "bar", "number", 2, "%", CSysCPU_max, "descending", true, false, false, NULL, "sum", true);
- add_table_field(wb, "CGuestCPU", "Children Guest CPU Time (100% = 1 core)", false, "bar-with-integer", "bar", "number", 2, "%", CGuestCPU_max, "descending", true, false, false, NULL, "sum", true);
+ buffer_rrdf_table_add_field(wb, field_id++, "CPU", "Total CPU Time (100% = 1 core)",
+ RRDF_FIELD_TYPE_BAR_WITH_INTEGER, RRDF_FIELD_VISUAL_BAR,
+ RRDF_FIELD_TRANSFORM_NUMBER, 2, "%", CPU_max, RRDF_FIELD_SORT_DESCENDING, NULL,
+ RRDF_FIELD_SUMMARY_SUM, RRDF_FIELD_FILTER_RANGE,
+ RRDF_FIELD_OPTS_VISIBLE, NULL);
+ buffer_rrdf_table_add_field(wb, field_id++, "UserCPU", "User CPU time (100% = 1 core)",
+ RRDF_FIELD_TYPE_BAR_WITH_INTEGER,
+ RRDF_FIELD_VISUAL_BAR, RRDF_FIELD_TRANSFORM_NUMBER, 2, "%", UserCPU_max,
+ RRDF_FIELD_SORT_DESCENDING, NULL, RRDF_FIELD_SUMMARY_SUM, RRDF_FIELD_FILTER_RANGE,
+ RRDF_FIELD_OPTS_NONE, NULL);
+ buffer_rrdf_table_add_field(wb, field_id++, "SysCPU", "System CPU Time (100% = 1 core)",
+ RRDF_FIELD_TYPE_BAR_WITH_INTEGER,
+ RRDF_FIELD_VISUAL_BAR, RRDF_FIELD_TRANSFORM_NUMBER, 2, "%", SysCPU_max,
+ RRDF_FIELD_SORT_DESCENDING, NULL, RRDF_FIELD_SUMMARY_SUM, RRDF_FIELD_FILTER_RANGE,
+ RRDF_FIELD_OPTS_NONE, NULL);
+ buffer_rrdf_table_add_field(wb, field_id++, "GuestCPU", "Guest CPU Time (100% = 1 core)",
+ RRDF_FIELD_TYPE_BAR_WITH_INTEGER,
+ RRDF_FIELD_VISUAL_BAR, RRDF_FIELD_TRANSFORM_NUMBER, 2, "%", GuestCPU_max,
+ RRDF_FIELD_SORT_DESCENDING, NULL, RRDF_FIELD_SUMMARY_SUM, RRDF_FIELD_FILTER_RANGE,
+ RRDF_FIELD_OPTS_NONE, NULL);
+ buffer_rrdf_table_add_field(wb, field_id++, "CUserCPU", "Children User CPU Time (100% = 1 core)",
+ RRDF_FIELD_TYPE_BAR_WITH_INTEGER, RRDF_FIELD_VISUAL_BAR,
+ RRDF_FIELD_TRANSFORM_NUMBER, 2, "%", CUserCPU_max, RRDF_FIELD_SORT_DESCENDING, NULL,
+ RRDF_FIELD_SUMMARY_SUM, RRDF_FIELD_FILTER_RANGE,
+ RRDF_FIELD_OPTS_NONE, NULL);
+ buffer_rrdf_table_add_field(wb, field_id++, "CSysCPU", "Children System CPU Time (100% = 1 core)",
+ RRDF_FIELD_TYPE_BAR_WITH_INTEGER, RRDF_FIELD_VISUAL_BAR,
+ RRDF_FIELD_TRANSFORM_NUMBER, 2, "%", CSysCPU_max, RRDF_FIELD_SORT_DESCENDING, NULL,
+ RRDF_FIELD_SUMMARY_SUM, RRDF_FIELD_FILTER_RANGE,
+ RRDF_FIELD_OPTS_NONE, NULL);
+ buffer_rrdf_table_add_field(wb, field_id++, "CGuestCPU", "Children Guest CPU Time (100% = 1 core)",
+ RRDF_FIELD_TYPE_BAR_WITH_INTEGER, RRDF_FIELD_VISUAL_BAR,
+ RRDF_FIELD_TRANSFORM_NUMBER, 2, "%", CGuestCPU_max, RRDF_FIELD_SORT_DESCENDING,
+ NULL,
+ RRDF_FIELD_SUMMARY_SUM, RRDF_FIELD_FILTER_RANGE, RRDF_FIELD_OPTS_NONE, NULL);
// CPU context switches
- add_table_field(wb, "vCtxSwitch", "Voluntary Context Switches", false, "bar-with-integer", "bar", "number", 2, "switches/s", VoluntaryCtxtSwitches_max, "descending", true, false, false, NULL, "sum", true);
- add_table_field(wb, "iCtxSwitch", "Involuntary Context Switches", false, "bar-with-integer", "bar", "number", 2, "switches/s", NonVoluntaryCtxtSwitches_max, "descending", true, false, false, NULL, "sum", true);
+ buffer_rrdf_table_add_field(wb, field_id++, "vCtxSwitch", "Voluntary Context Switches",
+ RRDF_FIELD_TYPE_BAR_WITH_INTEGER,
+ RRDF_FIELD_VISUAL_BAR, RRDF_FIELD_TRANSFORM_NUMBER, 2, "switches/s",
+ VoluntaryCtxtSwitches_max, RRDF_FIELD_SORT_DESCENDING, NULL,
+ RRDF_FIELD_SUMMARY_SUM, RRDF_FIELD_FILTER_RANGE, RRDF_FIELD_OPTS_NONE, NULL);
+ buffer_rrdf_table_add_field(wb, field_id++, "iCtxSwitch", "Involuntary Context Switches",
+ RRDF_FIELD_TYPE_BAR_WITH_INTEGER,
+ RRDF_FIELD_VISUAL_BAR, RRDF_FIELD_TRANSFORM_NUMBER, 2, "switches/s",
+ NonVoluntaryCtxtSwitches_max, RRDF_FIELD_SORT_DESCENDING, NULL,
+ RRDF_FIELD_SUMMARY_SUM, RRDF_FIELD_FILTER_RANGE, RRDF_FIELD_OPTS_NONE, NULL);
// memory
- if(MemTotal)
- add_table_field(wb, "Memory", "Memory Percentage", true, "bar-with-integer", "bar", "number", 2, "%", 100.0, "descending", true, false, false, NULL, "sum", true);
-
- add_table_field(wb, "Resident", "Resident Set Size", true, "bar-with-integer", "bar", "number", 2, "MiB", RSS_max, "descending", true, false, false, NULL, "sum", true);
- add_table_field(wb, "Shared", "Shared Pages", true, "bar-with-integer", "bar", "number", 2, "MiB", Shared_max, "descending", true, false, false, NULL, "sum", true);
- add_table_field(wb, "Virtual", "Virtual Memory Size", true, "bar-with-integer", "bar", "number", 2, "MiB", VMSize_max, "descending", true, false, false, NULL, "sum", true);
- add_table_field(wb, "Swap", "Swap Memory", false, "bar-with-integer", "bar", "number", 2, "MiB", Swap_max, "descending", true, false, false, NULL, "sum", true);
+ if (MemTotal)
+ buffer_rrdf_table_add_field(wb, field_id++, "Memory", "Memory Percentage", RRDF_FIELD_TYPE_BAR_WITH_INTEGER,
+ RRDF_FIELD_VISUAL_BAR,
+ RRDF_FIELD_TRANSFORM_NUMBER, 2, "%", 100.0, RRDF_FIELD_SORT_DESCENDING, NULL,
+ RRDF_FIELD_SUMMARY_SUM, RRDF_FIELD_FILTER_RANGE,
+ RRDF_FIELD_OPTS_VISIBLE, NULL);
+
+ buffer_rrdf_table_add_field(wb, field_id++, "Resident", "Resident Set Size", RRDF_FIELD_TYPE_BAR_WITH_INTEGER,
+ RRDF_FIELD_VISUAL_BAR,
+ RRDF_FIELD_TRANSFORM_NUMBER,
+ 2, "MiB", RSS_max, RRDF_FIELD_SORT_DESCENDING, NULL, RRDF_FIELD_SUMMARY_SUM,
+ RRDF_FIELD_FILTER_RANGE,
+ RRDF_FIELD_OPTS_VISIBLE, NULL);
+ buffer_rrdf_table_add_field(wb, field_id++, "Shared", "Shared Pages", RRDF_FIELD_TYPE_BAR_WITH_INTEGER,
+ RRDF_FIELD_VISUAL_BAR, RRDF_FIELD_TRANSFORM_NUMBER, 2,
+ "MiB", Shared_max, RRDF_FIELD_SORT_DESCENDING, NULL, RRDF_FIELD_SUMMARY_SUM,
+ RRDF_FIELD_FILTER_RANGE,
+ RRDF_FIELD_OPTS_VISIBLE, NULL);
+ buffer_rrdf_table_add_field(wb, field_id++, "Virtual", "Virtual Memory Size", RRDF_FIELD_TYPE_BAR_WITH_INTEGER,
+ RRDF_FIELD_VISUAL_BAR,
+ RRDF_FIELD_TRANSFORM_NUMBER, 2, "MiB", VMSize_max, RRDF_FIELD_SORT_DESCENDING, NULL,
+ RRDF_FIELD_SUMMARY_SUM, RRDF_FIELD_FILTER_RANGE,
+ RRDF_FIELD_OPTS_VISIBLE, NULL);
+ buffer_rrdf_table_add_field(wb, field_id++, "Swap", "Swap Memory", RRDF_FIELD_TYPE_BAR_WITH_INTEGER,
+ RRDF_FIELD_VISUAL_BAR, RRDF_FIELD_TRANSFORM_NUMBER, 2,
+ "MiB",
+ Swap_max, RRDF_FIELD_SORT_DESCENDING, NULL, RRDF_FIELD_SUMMARY_SUM,
+ RRDF_FIELD_FILTER_RANGE,
+ RRDF_FIELD_OPTS_NONE, NULL);
// Physical I/O
- add_table_field(wb, "PReads", "Physical I/O Reads", true, "bar-with-integer", "bar", "number", 2, "KiB/s", PReads_max, "descending", true, false, false, NULL, "sum", true);
- add_table_field(wb, "PWrites", "Physical I/O Writes", true, "bar-with-integer", "bar", "number", 2, "KiB/s", PWrites_max, "descending", true, false, false, NULL, "sum", true);
+ buffer_rrdf_table_add_field(wb, field_id++, "PReads", "Physical I/O Reads", RRDF_FIELD_TYPE_BAR_WITH_INTEGER,
+ RRDF_FIELD_VISUAL_BAR, RRDF_FIELD_TRANSFORM_NUMBER,
+ 2, "KiB/s", PReads_max, RRDF_FIELD_SORT_DESCENDING, NULL, RRDF_FIELD_SUMMARY_SUM,
+ RRDF_FIELD_FILTER_RANGE,
+ RRDF_FIELD_OPTS_VISIBLE, NULL);
+ buffer_rrdf_table_add_field(wb, field_id++, "PWrites", "Physical I/O Writes", RRDF_FIELD_TYPE_BAR_WITH_INTEGER,
+ RRDF_FIELD_VISUAL_BAR,
+ RRDF_FIELD_TRANSFORM_NUMBER, 2, "KiB/s", PWrites_max, RRDF_FIELD_SORT_DESCENDING,
+ NULL, RRDF_FIELD_SUMMARY_SUM, RRDF_FIELD_FILTER_RANGE,
+ RRDF_FIELD_OPTS_VISIBLE, NULL);
// Logical I/O
#ifndef __FreeBSD__
- add_table_field(wb, "LReads", "Logical I/O Reads", true, "bar-with-integer", "bar", "number", 2, "KiB/s", LReads_max, "descending", true, false, false, NULL, "sum", true);
- add_table_field(wb, "LWrites", "Logical I/O Writes", true, "bar-with-integer", "bar", "number", 2, "KiB/s", LWrites_max, "descending", true, false, false, NULL, "sum", true);
+ buffer_rrdf_table_add_field(wb, field_id++, "LReads", "Logical I/O Reads", RRDF_FIELD_TYPE_BAR_WITH_INTEGER,
+ RRDF_FIELD_VISUAL_BAR, RRDF_FIELD_TRANSFORM_NUMBER,
+ 2, "KiB/s", LReads_max, RRDF_FIELD_SORT_DESCENDING, NULL, RRDF_FIELD_SUMMARY_SUM,
+ RRDF_FIELD_FILTER_RANGE,
+ RRDF_FIELD_OPTS_VISIBLE, NULL);
+ buffer_rrdf_table_add_field(wb, field_id++, "LWrites", "Logical I/O Writes", RRDF_FIELD_TYPE_BAR_WITH_INTEGER,
+ RRDF_FIELD_VISUAL_BAR,
+ RRDF_FIELD_TRANSFORM_NUMBER,
+ 2, "KiB/s", LWrites_max, RRDF_FIELD_SORT_DESCENDING, NULL, RRDF_FIELD_SUMMARY_SUM,
+ RRDF_FIELD_FILTER_RANGE,
+ RRDF_FIELD_OPTS_VISIBLE, NULL);
#endif
// I/O calls
- add_table_field(wb, "RCalls", "I/O Read Calls", true, "bar-with-integer", "bar", "number", 2, "calls/s", RCalls_max, "descending", true, false, false, NULL, "sum", true);
- add_table_field(wb, "WCalls", "I/O Write Calls", true, "bar-with-integer", "bar", "number", 2, "calls/s", WCalls_max, "descending", true, false, false, NULL, "sum", true);
+ buffer_rrdf_table_add_field(wb, field_id++, "RCalls", "I/O Read Calls", RRDF_FIELD_TYPE_BAR_WITH_INTEGER,
+ RRDF_FIELD_VISUAL_BAR, RRDF_FIELD_TRANSFORM_NUMBER, 2,
+ "calls/s", RCalls_max, RRDF_FIELD_SORT_DESCENDING, NULL, RRDF_FIELD_SUMMARY_SUM,
+ RRDF_FIELD_FILTER_RANGE,
+ RRDF_FIELD_OPTS_VISIBLE, NULL);
+ buffer_rrdf_table_add_field(wb, field_id++, "WCalls", "I/O Write Calls", RRDF_FIELD_TYPE_BAR_WITH_INTEGER,
+ RRDF_FIELD_VISUAL_BAR, RRDF_FIELD_TRANSFORM_NUMBER, 2,
+ "calls/s", WCalls_max, RRDF_FIELD_SORT_DESCENDING, NULL, RRDF_FIELD_SUMMARY_SUM,
+ RRDF_FIELD_FILTER_RANGE,
+ RRDF_FIELD_OPTS_VISIBLE, NULL);
// minor page faults
- add_table_field(wb, "MinFlt", "Minor Page Faults/s", false, "bar-with-integer", "bar", "number", 2, "pgflts/s", MinFlt_max, "descending", true, false, false, NULL, "sum", true);
- add_table_field(wb, "CMinFlt", "Children Minor Page Faults/s", false, "bar-with-integer", "bar", "number", 2, "pgflts/s", CMinFlt_max, "descending", true, false, false, NULL, "sum", true);
- add_table_field(wb, "TMinFlt", "Total Minor Page Faults/s", false, "bar-with-integer", "bar", "number", 2, "pgflts/s", TMinFlt_max, "descending", true, false, false, NULL, "sum", true);
+ buffer_rrdf_table_add_field(wb, field_id++, "MinFlt", "Minor Page Faults/s", RRDF_FIELD_TYPE_BAR_WITH_INTEGER,
+ RRDF_FIELD_VISUAL_BAR,
+ RRDF_FIELD_TRANSFORM_NUMBER,
+ 2, "pgflts/s", MinFlt_max, RRDF_FIELD_SORT_DESCENDING, NULL, RRDF_FIELD_SUMMARY_SUM,
+ RRDF_FIELD_FILTER_RANGE,
+ RRDF_FIELD_OPTS_NONE, NULL);
+ buffer_rrdf_table_add_field(wb, field_id++, "CMinFlt", "Children Minor Page Faults/s",
+ RRDF_FIELD_TYPE_BAR_WITH_INTEGER,
+ RRDF_FIELD_VISUAL_BAR,
+ RRDF_FIELD_TRANSFORM_NUMBER, 2, "pgflts/s", CMinFlt_max, RRDF_FIELD_SORT_DESCENDING,
+ NULL, RRDF_FIELD_SUMMARY_SUM, RRDF_FIELD_FILTER_RANGE,
+ RRDF_FIELD_OPTS_NONE, NULL);
+ buffer_rrdf_table_add_field(wb, field_id++, "TMinFlt", "Total Minor Page Faults/s",
+ RRDF_FIELD_TYPE_BAR_WITH_INTEGER, RRDF_FIELD_VISUAL_BAR,
+ RRDF_FIELD_TRANSFORM_NUMBER, 2, "pgflts/s", TMinFlt_max, RRDF_FIELD_SORT_DESCENDING,
+ NULL, RRDF_FIELD_SUMMARY_SUM, RRDF_FIELD_FILTER_RANGE,
+ RRDF_FIELD_OPTS_NONE, NULL);
// major page faults
- add_table_field(wb, "MajFlt", "Major Page Faults/s", false, "bar-with-integer", "bar", "number", 2, "pgflts/s", MajFlt_max, "descending", true, false, false, NULL, "sum", true);
- add_table_field(wb, "CMajFlt", "Children Major Page Faults/s", false, "bar-with-integer", "bar", "number", 2, "pgflts/s", CMajFlt_max, "descending", true, false, false, NULL, "sum", true);
- add_table_field(wb, "TMajFlt", "Total Major Page Faults/s", true, "bar-with-integer", "bar", "number", 2, "pgflts/s", TMajFlt_max, "descending", true, false, false, NULL, "sum", true);
+ buffer_rrdf_table_add_field(wb, field_id++, "MajFlt", "Major Page Faults/s", RRDF_FIELD_TYPE_BAR_WITH_INTEGER,
+ RRDF_FIELD_VISUAL_BAR,
+ RRDF_FIELD_TRANSFORM_NUMBER,
+ 2, "pgflts/s", MajFlt_max, RRDF_FIELD_SORT_DESCENDING, NULL, RRDF_FIELD_SUMMARY_SUM,
+ RRDF_FIELD_FILTER_RANGE,
+ RRDF_FIELD_OPTS_NONE, NULL);
+ buffer_rrdf_table_add_field(wb, field_id++, "CMajFlt", "Children Major Page Faults/s",
+ RRDF_FIELD_TYPE_BAR_WITH_INTEGER,
+ RRDF_FIELD_VISUAL_BAR,
+ RRDF_FIELD_TRANSFORM_NUMBER, 2, "pgflts/s", CMajFlt_max, RRDF_FIELD_SORT_DESCENDING,
+ NULL, RRDF_FIELD_SUMMARY_SUM, RRDF_FIELD_FILTER_RANGE,
+ RRDF_FIELD_OPTS_NONE, NULL);
+ buffer_rrdf_table_add_field(wb, field_id++, "TMajFlt", "Total Major Page Faults/s",
+ RRDF_FIELD_TYPE_BAR_WITH_INTEGER, RRDF_FIELD_VISUAL_BAR,
+ RRDF_FIELD_TRANSFORM_NUMBER, 2, "pgflts/s", TMajFlt_max, RRDF_FIELD_SORT_DESCENDING,
+ NULL, RRDF_FIELD_SUMMARY_SUM, RRDF_FIELD_FILTER_RANGE,
+ RRDF_FIELD_OPTS_VISIBLE, NULL);
// open file descriptors
- add_table_field(wb, "FDs", "All Open File Descriptors", true, "bar-with-integer", "bar", "number", 0, "fds", FDs_max, "descending", true, false, false, NULL, "sum", true);
- add_table_field(wb, "Files", "Open Files", true, "bar-with-integer", "bar", "number", 0, "fds", Files_max, "descending", true, false, false, NULL, "sum", true);
- add_table_field(wb, "Pipes", "Open Pipes", true, "bar-with-integer", "bar", "number", 0, "fds", Pipes_max, "descending", true, false, false, NULL, "sum", true);
- add_table_field(wb, "Sockets", "Open Sockets", true, "bar-with-integer", "bar", "number", 0, "fds", Sockets_max, "descending", true, false, false, NULL, "sum", true);
- add_table_field(wb, "iNotiFDs", "Open iNotify Descriptors", false, "bar-with-integer", "bar", "number", 0, "fds", iNotiFDs_max, "descending", true, false, false, NULL, "sum", true);
- add_table_field(wb, "EventFDs", "Open Event Descriptors", false, "bar-with-integer", "bar", "number", 0, "fds", EventFDs_max, "descending", true, false, false, NULL, "sum", true);
- add_table_field(wb, "TimerFDs", "Open Timer Descriptors", false, "bar-with-integer", "bar", "number", 0, "fds", TimerFDs_max, "descending", true, false, false, NULL, "sum", true);
- add_table_field(wb, "SigFDs", "Open Signal Descriptors", false, "bar-with-integer", "bar", "number", 0, "fds", SigFDs_max, "descending", true, false, false, NULL, "sum", true);
- add_table_field(wb, "EvPollFDs", "Open Event Poll Descriptors", false, "bar-with-integer", "bar", "number", 0, "fds", EvPollFDs_max, "descending", true, false, false, NULL, "sum", true);
- add_table_field(wb, "OtherFDs", "Other Open Descriptors", false, "bar-with-integer", "bar", "number", 0, "fds", OtherFDs_max, "descending", true, false, false, NULL, "sum", true);
+ buffer_rrdf_table_add_field(wb, field_id++, "FDsLimitPercent", "Percentage of Open Descriptors vs Limits",
+ RRDF_FIELD_TYPE_BAR_WITH_INTEGER, RRDF_FIELD_VISUAL_BAR,
+ RRDF_FIELD_TRANSFORM_NUMBER, 2, "%", FDsLimitPercent_max, RRDF_FIELD_SORT_DESCENDING, NULL,
+ RRDF_FIELD_SUMMARY_MAX, RRDF_FIELD_FILTER_RANGE,
+ RRDF_FIELD_OPTS_NONE, NULL);
+ buffer_rrdf_table_add_field(wb, field_id++, "FDs", "All Open File Descriptors",
+ RRDF_FIELD_TYPE_BAR_WITH_INTEGER, RRDF_FIELD_VISUAL_BAR,
+ RRDF_FIELD_TRANSFORM_NUMBER, 0, "fds", FDs_max, RRDF_FIELD_SORT_DESCENDING, NULL,
+ RRDF_FIELD_SUMMARY_SUM, RRDF_FIELD_FILTER_RANGE,
+ RRDF_FIELD_OPTS_VISIBLE, NULL);
+ buffer_rrdf_table_add_field(wb, field_id++, "Files", "Open Files", RRDF_FIELD_TYPE_BAR_WITH_INTEGER,
+ RRDF_FIELD_VISUAL_BAR, RRDF_FIELD_TRANSFORM_NUMBER, 0,
+ "fds",
+ Files_max, RRDF_FIELD_SORT_DESCENDING, NULL, RRDF_FIELD_SUMMARY_SUM,
+ RRDF_FIELD_FILTER_RANGE,
+ RRDF_FIELD_OPTS_VISIBLE, NULL);
+ buffer_rrdf_table_add_field(wb, field_id++, "Pipes", "Open Pipes", RRDF_FIELD_TYPE_BAR_WITH_INTEGER,
+ RRDF_FIELD_VISUAL_BAR, RRDF_FIELD_TRANSFORM_NUMBER, 0,
+ "fds",
+ Pipes_max, RRDF_FIELD_SORT_DESCENDING, NULL, RRDF_FIELD_SUMMARY_SUM,
+ RRDF_FIELD_FILTER_RANGE,
+ RRDF_FIELD_OPTS_VISIBLE, NULL);
+ buffer_rrdf_table_add_field(wb, field_id++, "Sockets", "Open Sockets", RRDF_FIELD_TYPE_BAR_WITH_INTEGER,
+ RRDF_FIELD_VISUAL_BAR, RRDF_FIELD_TRANSFORM_NUMBER, 0,
+ "fds", Sockets_max, RRDF_FIELD_SORT_DESCENDING, NULL, RRDF_FIELD_SUMMARY_SUM,
+ RRDF_FIELD_FILTER_RANGE,
+ RRDF_FIELD_OPTS_VISIBLE, NULL);
+ buffer_rrdf_table_add_field(wb, field_id++, "iNotiFDs", "Open iNotify Descriptors",
+ RRDF_FIELD_TYPE_BAR_WITH_INTEGER, RRDF_FIELD_VISUAL_BAR,
+ RRDF_FIELD_TRANSFORM_NUMBER, 0, "fds", iNotiFDs_max, RRDF_FIELD_SORT_DESCENDING,
+ NULL, RRDF_FIELD_SUMMARY_SUM, RRDF_FIELD_FILTER_RANGE,
+ RRDF_FIELD_OPTS_NONE, NULL);
+ buffer_rrdf_table_add_field(wb, field_id++, "EventFDs", "Open Event Descriptors",
+ RRDF_FIELD_TYPE_BAR_WITH_INTEGER, RRDF_FIELD_VISUAL_BAR,
+ RRDF_FIELD_TRANSFORM_NUMBER, 0, "fds", EventFDs_max, RRDF_FIELD_SORT_DESCENDING,
+ NULL, RRDF_FIELD_SUMMARY_SUM, RRDF_FIELD_FILTER_RANGE,
+ RRDF_FIELD_OPTS_NONE, NULL);
+ buffer_rrdf_table_add_field(wb, field_id++, "TimerFDs", "Open Timer Descriptors",
+ RRDF_FIELD_TYPE_BAR_WITH_INTEGER, RRDF_FIELD_VISUAL_BAR,
+ RRDF_FIELD_TRANSFORM_NUMBER, 0, "fds", TimerFDs_max, RRDF_FIELD_SORT_DESCENDING,
+ NULL, RRDF_FIELD_SUMMARY_SUM, RRDF_FIELD_FILTER_RANGE,
+ RRDF_FIELD_OPTS_NONE, NULL);
+ buffer_rrdf_table_add_field(wb, field_id++, "SigFDs", "Open Signal Descriptors",
+ RRDF_FIELD_TYPE_BAR_WITH_INTEGER, RRDF_FIELD_VISUAL_BAR,
+ RRDF_FIELD_TRANSFORM_NUMBER, 0, "fds", SigFDs_max, RRDF_FIELD_SORT_DESCENDING, NULL,
+ RRDF_FIELD_SUMMARY_SUM, RRDF_FIELD_FILTER_RANGE,
+ RRDF_FIELD_OPTS_NONE, NULL);
+ buffer_rrdf_table_add_field(wb, field_id++, "EvPollFDs", "Open Event Poll Descriptors",
+ RRDF_FIELD_TYPE_BAR_WITH_INTEGER,
+ RRDF_FIELD_VISUAL_BAR, RRDF_FIELD_TRANSFORM_NUMBER, 0, "fds", EvPollFDs_max,
+ RRDF_FIELD_SORT_DESCENDING, NULL, RRDF_FIELD_SUMMARY_SUM, RRDF_FIELD_FILTER_RANGE,
+ RRDF_FIELD_OPTS_NONE, NULL);
+ buffer_rrdf_table_add_field(wb, field_id++, "OtherFDs", "Other Open Descriptors",
+ RRDF_FIELD_TYPE_BAR_WITH_INTEGER, RRDF_FIELD_VISUAL_BAR,
+ RRDF_FIELD_TRANSFORM_NUMBER, 0, "fds", OtherFDs_max, RRDF_FIELD_SORT_DESCENDING,
+ NULL, RRDF_FIELD_SUMMARY_SUM, RRDF_FIELD_FILTER_RANGE,
+ RRDF_FIELD_OPTS_NONE, NULL);
// processes, threads, uptime
- add_table_field(wb, "Processes", "Processes", true, "bar-with-integer", "bar", "number", 0, "processes", Processes_max, "descending", true, false, false, NULL, "sum", true);
- add_table_field(wb, "Threads", "Threads", true, "bar-with-integer", "bar", "number", 0, "threads", Threads_max, "descending", true, false, false, NULL, "sum", true);
- add_table_field(wb, "Uptime", "Uptime in seconds", true, "duration", "bar", "duration", 2, "seconds", Uptime_max, "descending", true, false, false, NULL, "max", true);
- }
- buffer_json_object_close(wb);
+ buffer_rrdf_table_add_field(wb, field_id++, "Processes", "Processes", RRDF_FIELD_TYPE_BAR_WITH_INTEGER,
+ RRDF_FIELD_VISUAL_BAR, RRDF_FIELD_TRANSFORM_NUMBER, 0,
+ "processes", Processes_max, RRDF_FIELD_SORT_DESCENDING, NULL,
+ RRDF_FIELD_SUMMARY_SUM, RRDF_FIELD_FILTER_RANGE,
+ RRDF_FIELD_OPTS_VISIBLE, NULL);
+ buffer_rrdf_table_add_field(wb, field_id++, "Threads", "Threads", RRDF_FIELD_TYPE_BAR_WITH_INTEGER,
+ RRDF_FIELD_VISUAL_BAR, RRDF_FIELD_TRANSFORM_NUMBER, 0,
+ "threads", Threads_max, RRDF_FIELD_SORT_DESCENDING, NULL, RRDF_FIELD_SUMMARY_SUM,
+ RRDF_FIELD_FILTER_RANGE,
+ RRDF_FIELD_OPTS_VISIBLE, NULL);
+ buffer_rrdf_table_add_field(wb, field_id++, "Uptime", "Uptime in seconds", RRDF_FIELD_TYPE_DURATION,
+ RRDF_FIELD_VISUAL_BAR, RRDF_FIELD_TRANSFORM_DURATION, 2,
+ "seconds", Uptime_max, RRDF_FIELD_SORT_DESCENDING, NULL, RRDF_FIELD_SUMMARY_MAX,
+ RRDF_FIELD_FILTER_RANGE,
+ RRDF_FIELD_OPTS_VISIBLE, NULL);
+ }
+ buffer_json_object_close(wb); // columns
buffer_json_member_add_string(wb, "default_sort_column", "CPU");
@@ -4953,6 +5371,20 @@ static void apps_plugin_function_processes(const char *transaction, char *functi
}
buffer_json_object_close(wb); // charts
+ buffer_json_member_add_array(wb, "default_charts");
+ {
+ buffer_json_add_array_item_array(wb);
+ buffer_json_add_array_item_string(wb, "CPU");
+ buffer_json_add_array_item_string(wb, "Category");
+ buffer_json_array_close(wb);
+
+ buffer_json_add_array_item_array(wb);
+ buffer_json_add_array_item_string(wb, "Memory");
+ buffer_json_add_array_item_string(wb, "Category");
+ buffer_json_array_close(wb);
+ }
+ buffer_json_array_close(wb);
+
buffer_json_member_add_object(wb, "group_by");
{
// group by PID
@@ -5026,7 +5458,7 @@ void *reader_main(void *arg __maybe_unused) {
while(!apps_plugin_exit && (s = fgets(buffer, PLUGINSD_LINE_MAX, stdin))) {
char *words[PLUGINSD_MAX_WORDS] = { NULL };
- size_t num_words = pluginsd_split_words(buffer, words, PLUGINSD_MAX_WORDS);
+ size_t num_words = quoted_strings_splitter_pluginsd(buffer, words, PLUGINSD_MAX_WORDS);
const char *keyword = get_word(words, num_words, 0);
@@ -5036,7 +5468,7 @@ void *reader_main(void *arg __maybe_unused) {
char *function = get_word(words, num_words, 3);
if(!transaction || !*transaction || !timeout_s || !*timeout_s || !function || !*function) {
- error("Received incomplete %s (transaction = '%s', timeout = '%s', function = '%s'). Ignoring it.",
+ netdata_log_error("Received incomplete %s (transaction = '%s', timeout = '%s', function = '%s'). Ignoring it.",
keyword,
transaction?transaction:"(unset)",
timeout_s?timeout_s:"(unset)",
@@ -5062,12 +5494,12 @@ void *reader_main(void *arg __maybe_unused) {
}
}
else
- error("Received unknown command: %s", keyword?keyword:"(unset)");
+ netdata_log_error("Received unknown command: %s", keyword?keyword:"(unset)");
}
if(!s || feof(stdin) || ferror(stdin)) {
apps_plugin_exit = true;
- error("Received error on stdin.");
+ netdata_log_error("Received error on stdin.");
}
exit(1);
@@ -5107,23 +5539,23 @@ int main(int argc, char **argv) {
user_config_dir = getenv("NETDATA_USER_CONFIG_DIR");
if(user_config_dir == NULL) {
- // info("NETDATA_CONFIG_DIR is not passed from netdata");
+ // netdata_log_info("NETDATA_CONFIG_DIR is not passed from netdata");
user_config_dir = CONFIG_DIR;
}
- // else info("Found NETDATA_USER_CONFIG_DIR='%s'", user_config_dir);
+ // else netdata_log_info("Found NETDATA_USER_CONFIG_DIR='%s'", user_config_dir);
stock_config_dir = getenv("NETDATA_STOCK_CONFIG_DIR");
if(stock_config_dir == NULL) {
- // info("NETDATA_CONFIG_DIR is not passed from netdata");
+ // netdata_log_info("NETDATA_CONFIG_DIR is not passed from netdata");
stock_config_dir = LIBCONFIG_DIR;
}
- // else info("Found NETDATA_USER_CONFIG_DIR='%s'", user_config_dir);
+ // else netdata_log_info("Found NETDATA_USER_CONFIG_DIR='%s'", user_config_dir);
#ifdef NETDATA_INTERNAL_CHECKS
if(debug_flags != 0) {
struct rlimit rl = { RLIM_INFINITY, RLIM_INFINITY };
if(setrlimit(RLIMIT_CORE, &rl) != 0)
- info("Cannot request unlimited core dumps for debugging... Proceeding anyway...");
+ netdata_log_info("Cannot request unlimited core dumps for debugging... Proceeding anyway...");
#ifdef HAVE_SYS_PRCTL_H
prctl(PR_SET_DUMPABLE, 1, 0, 0, 0);
#endif
@@ -5147,14 +5579,14 @@ int main(int argc, char **argv) {
if(!check_capabilities() && !am_i_running_as_root() && !check_proc_1_io()) {
uid_t uid = getuid(), euid = geteuid();
#ifdef HAVE_CAPABILITY
- error("apps.plugin should either run as root (now running with uid %u, euid %u) or have special capabilities. "
+ netdata_log_error("apps.plugin should either run as root (now running with uid %u, euid %u) or have special capabilities. "
"Without these, apps.plugin cannot report disk I/O utilization of other processes. "
"To enable capabilities run: sudo setcap cap_dac_read_search,cap_sys_ptrace+ep %s; "
"To enable setuid to root run: sudo chown root:netdata %s; sudo chmod 4750 %s; "
, uid, euid, argv[0], argv[0], argv[0]
);
#else
- error("apps.plugin should either run as root (now running with uid %u, euid %u) or have special capabilities. "
+ netdata_log_error("apps.plugin should either run as root (now running with uid %u, euid %u) or have special capabilities. "
"Without these, apps.plugin cannot report disk I/O utilization of other processes. "
"Your system does not support capabilities. "
"To enable setuid to root run: sudo chown root:netdata %s; sudo chmod 4750 %s; "
@@ -5163,7 +5595,7 @@ int main(int argc, char **argv) {
#endif
}
- info("started on pid %d", getpid());
+ netdata_log_info("started on pid %d", getpid());
snprintfz(all_user_ids.filename, FILENAME_MAX, "%s/etc/passwd", netdata_configured_host_prefix);
debug_log("passwd file: '%s'", all_user_ids.filename);
@@ -5215,14 +5647,13 @@ int main(int argc, char **argv) {
get_MemTotal();
if(!collect_data_for_all_processes()) {
- error("Cannot collect /proc data for running processes. Disabling apps.plugin...");
+ netdata_log_error("Cannot collect /proc data for running processes. Disabling apps.plugin...");
printf("DISABLE\n");
netdata_mutex_unlock(&mutex);
netdata_thread_cancel(reader_thread);
exit(1);
}
- currentmaxfds = 0;
calculate_netdata_statistics();
normalize_utilization(apps_groups_root_target);