diff options
author | Federico Ceratto <federico.ceratto@gmail.com> | 2018-03-27 21:28:21 +0000 |
---|---|---|
committer | Federico Ceratto <federico.ceratto@gmail.com> | 2018-03-27 21:28:21 +0000 |
commit | d4dd00f58a502c9ca4b63e36ce6bc7a9945dc63c (patch) | |
tree | faac99f51f182bb8c0a03e95e393d421ac9ddf42 /src/apps_plugin.c | |
parent | New upstream version 1.9.0+dfsg (diff) | |
download | netdata-d4dd00f58a502c9ca4b63e36ce6bc7a9945dc63c.tar.xz netdata-d4dd00f58a502c9ca4b63e36ce6bc7a9945dc63c.zip |
New upstream version 1.10.0+dfsgupstream/1.10.0+dfsg
Diffstat (limited to 'src/apps_plugin.c')
-rw-r--r-- | src/apps_plugin.c | 443 |
1 files changed, 283 insertions, 160 deletions
diff --git a/src/apps_plugin.c b/src/apps_plugin.c index 3ac79777b..8595da6c2 100644 --- a/src/apps_plugin.c +++ b/src/apps_plugin.c @@ -162,13 +162,12 @@ struct target { kernel_uint_t num_threads; // kernel_uint_t rss; - kernel_uint_t statm_size; - kernel_uint_t statm_resident; - kernel_uint_t statm_share; - // kernel_uint_t statm_text; - // kernel_uint_t statm_lib; - // kernel_uint_t statm_data; - // kernel_uint_t statm_dirty; + kernel_uint_t status_vmsize; + kernel_uint_t status_vmrss; + kernel_uint_t status_vmshared; + kernel_uint_t status_rssfile; + kernel_uint_t status_rssshmem; + kernel_uint_t status_vmswap; kernel_uint_t io_logical_bytes_read; kernel_uint_t io_logical_bytes_written; @@ -287,13 +286,15 @@ struct pid_stat { uid_t uid; gid_t gid; - kernel_uint_t statm_size; - kernel_uint_t statm_resident; - kernel_uint_t statm_share; - // kernel_uint_t statm_text; - // kernel_uint_t statm_lib; - // kernel_uint_t statm_data; - // kernel_uint_t statm_dirty; + kernel_uint_t status_vmsize; + kernel_uint_t status_vmrss; + kernel_uint_t status_vmshared; + kernel_uint_t status_rssfile; + kernel_uint_t status_rssshmem; + kernel_uint_t status_vmswap; +#ifndef __FreeBSD__ + ARL_BASE *status_arl; +#endif kernel_uint_t io_logical_bytes_read_raw; kernel_uint_t io_logical_bytes_written_raw; @@ -337,7 +338,7 @@ struct pid_stat { char *fds_dirname; // the full directory name in /proc/PID/fd char *stat_filename; - char *statm_filename; + char *status_filename; char *io_filename; char *cmdline_filename; @@ -346,10 +347,12 @@ struct pid_stat { struct pid_stat *next; }; +size_t pagesize; + // log each problem once per process // log flood protection flags (log_thrown) #define PID_LOG_IO 0x00000001 -#define PID_LOG_STATM 0x00000002 +#define PID_LOG_STATUS 0x00000002 #define PID_LOG_CMDLINE 0x00000004 #define PID_LOG_FDS 0x00000008 #define PID_LOG_STAT 0x00000010 @@ -694,7 +697,10 @@ static inline void del_pid_entry(pid_t pid) { freez(p->fds); freez(p->fds_dirname); freez(p->stat_filename); - freez(p->statm_filename); + freez(p->status_filename); +#ifndef __FreeBSD__ + arl_free(p->status_arl); +#endif freez(p->io_filename); freez(p->cmdline_filename); freez(p->cmdline); @@ -715,19 +721,35 @@ static inline int managed_log(struct pid_stat *p, uint32_t log, int status) { p->log_thrown |= log; switch(log) { case PID_LOG_IO: + #ifdef __FreeBSD__ + 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); + #endif break; - case PID_LOG_STATM: - error("Cannot process %s/proc/%d/statm (command '%s')", netdata_configured_host_prefix, p->pid, p->comm); + case PID_LOG_STATUS: + #ifdef __FreeBSD__ + 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); + #endif break; case PID_LOG_CMDLINE: + #ifdef __FreeBSD__ + 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); + #endif break; case PID_LOG_FDS: + #ifdef __FreeBSD__ + 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); + #endif break; case PID_LOG_STAT: @@ -832,51 +854,170 @@ cleanup: return 0; } -static inline int read_proc_pid_ownership(struct pid_stat *p, void *ptr) { - (void)ptr; +// ---------------------------------------------------------------------------- +// macro to calculate the incremental rate of a value +// each parameter is accessed only ONCE - so it is safe to pass function calls +// or other macros as parameters + +#define incremental_rate(rate_variable, last_kernel_variable, new_kernel_value, collected_usec, last_collected_usec) { \ + kernel_uint_t _new_tmp = new_kernel_value; \ + (rate_variable) = (_new_tmp - (last_kernel_variable)) * (USEC_PER_SEC * RATES_DETAIL) / ((collected_usec) - (last_collected_usec)); \ + (last_kernel_variable) = _new_tmp; \ + } + +// the same macro for struct pid members +#define pid_incremental_rate(type, var, value) \ + incremental_rate(var, var##_raw, value, p->type##_collected_usec, p->last_##type##_collected_usec) + + +// ---------------------------------------------------------------------------- + +#ifndef __FreeBSD__ +struct arl_callback_ptr { + struct pid_stat *p; + procfile *ff; + size_t line; +}; + +void arl_callback_status_uid(const char *name, uint32_t hash, const char *value, void *dst) { + (void)name; (void)hash; (void)value; + struct arl_callback_ptr *aptr = (struct arl_callback_ptr *)dst; + if(unlikely(procfile_linewords(aptr->ff, aptr->line) < 5)) return; + + //const char *real_uid = procfile_lineword(aptr->ff, aptr->line, 1); + const char *effective_uid = procfile_lineword(aptr->ff, aptr->line, 2); + //const char *saved_uid = procfile_lineword(aptr->ff, aptr->line, 3); + //const char *filesystem_uid = procfile_lineword(aptr->ff, aptr->line, 4); + + if(likely(effective_uid && *effective_uid)) + aptr->p->uid = (uid_t)str2l(effective_uid); +} + +void arl_callback_status_gid(const char *name, uint32_t hash, const char *value, void *dst) { + (void)name; (void)hash; (void)value; + struct arl_callback_ptr *aptr = (struct arl_callback_ptr *)dst; + if(unlikely(procfile_linewords(aptr->ff, aptr->line) < 5)) return; + + //const char *real_gid = procfile_lineword(aptr->ff, aptr->line, 1); + const char *effective_gid = procfile_lineword(aptr->ff, aptr->line, 2); + //const char *saved_gid = procfile_lineword(aptr->ff, aptr->line, 3); + //const char *filesystem_gid = procfile_lineword(aptr->ff, aptr->line, 4); + + if(likely(effective_gid && *effective_gid)) + aptr->p->gid = (uid_t)str2l(effective_gid); +} + +void arl_callback_status_vmsize(const char *name, uint32_t hash, const char *value, void *dst) { + (void)name; (void)hash; (void)value; + struct arl_callback_ptr *aptr = (struct arl_callback_ptr *)dst; + if(unlikely(procfile_linewords(aptr->ff, aptr->line) < 3)) return; + + aptr->p->status_vmsize = str2kernel_uint_t(procfile_lineword(aptr->ff, aptr->line, 1)); +} + +void arl_callback_status_vmswap(const char *name, uint32_t hash, const char *value, void *dst) { + (void)name; (void)hash; (void)value; + struct arl_callback_ptr *aptr = (struct arl_callback_ptr *)dst; + if(unlikely(procfile_linewords(aptr->ff, aptr->line) < 3)) return; + + aptr->p->status_vmswap = str2kernel_uint_t(procfile_lineword(aptr->ff, aptr->line, 1)); +} + +void arl_callback_status_vmrss(const char *name, uint32_t hash, const char *value, void *dst) { + (void)name; (void)hash; (void)value; + struct arl_callback_ptr *aptr = (struct arl_callback_ptr *)dst; + if(unlikely(procfile_linewords(aptr->ff, aptr->line) < 3)) return; + + aptr->p->status_vmrss = str2kernel_uint_t(procfile_lineword(aptr->ff, aptr->line, 1)); +} + +void arl_callback_status_rssfile(const char *name, uint32_t hash, const char *value, void *dst) { + (void)name; (void)hash; (void)value; + struct arl_callback_ptr *aptr = (struct arl_callback_ptr *)dst; + if(unlikely(procfile_linewords(aptr->ff, aptr->line) < 3)) return; + + aptr->p->status_rssfile = str2kernel_uint_t(procfile_lineword(aptr->ff, aptr->line, 1)); +} + +void arl_callback_status_rssshmem(const char *name, uint32_t hash, const char *value, void *dst) { + (void)name; (void)hash; (void)value; + struct arl_callback_ptr *aptr = (struct arl_callback_ptr *)dst; + if(unlikely(procfile_linewords(aptr->ff, aptr->line) < 3)) return; + + aptr->p->status_rssshmem = str2kernel_uint_t(procfile_lineword(aptr->ff, aptr->line, 1)); +} +#endif // !__FreeBSD__ + +static inline int read_proc_pid_status(struct pid_stat *p, void *ptr) { + p->status_vmsize = 0; + p->status_vmrss = 0; + p->status_vmshared = 0; + p->status_rssfile = 0; + p->status_rssshmem = 0; + p->status_vmswap = 0; + #ifdef __FreeBSD__ struct kinfo_proc *proc_info = (struct kinfo_proc *)ptr; - p->uid = proc_info->ki_uid; - p->gid = proc_info->ki_groups[0]; - + p->uid = proc_info->ki_uid; + p->gid = proc_info->ki_groups[0]; + p->status_vmsize = proc_info->ki_size / 1024; // in kB + p->status_vmrss = proc_info->ki_rssize * pagesize / 1024; // in kB + // FIXME: what about shared and swap memory on FreeBSD? return 1; #else - if(unlikely(!p->stat_filename)) { - error("pid %d does not have a stat_filename", p->pid); - return 0; - } + (void)ptr; - // ---------------------------------------- - // read uid and gid + static struct arl_callback_ptr arl_ptr; + static procfile *ff = NULL; - struct stat st; - if(stat(p->stat_filename, &st) != 0) { - error("Cannot stat file '%s'", p->stat_filename); - return 1; + if(unlikely(!p->status_arl)) { + p->status_arl = arl_create("/proc/pid/status", NULL, 60); + arl_expect_custom(p->status_arl, "Uid", arl_callback_status_uid, &arl_ptr); + arl_expect_custom(p->status_arl, "Gid", arl_callback_status_gid, &arl_ptr); + arl_expect_custom(p->status_arl, "VmSize", arl_callback_status_vmsize, &arl_ptr); + arl_expect_custom(p->status_arl, "VmRSS", arl_callback_status_vmrss, &arl_ptr); + arl_expect_custom(p->status_arl, "RssFile", arl_callback_status_rssfile, &arl_ptr); + arl_expect_custom(p->status_arl, "RssShmem", arl_callback_status_rssshmem, &arl_ptr); + arl_expect_custom(p->status_arl, "VmSwap", arl_callback_status_vmswap, &arl_ptr); } - p->uid = st.st_uid; - p->gid = st.st_gid; + if(unlikely(!p->status_filename)) { + char filename[FILENAME_MAX + 1]; + snprintfz(filename, FILENAME_MAX, "%s/proc/%d/status", netdata_configured_host_prefix, p->pid); + p->status_filename = strdupz(filename); + } - return 1; -#endif -} + ff = procfile_reopen(ff, p->status_filename, (!ff)?" \t:,-()/":NULL, PROCFILE_FLAG_NO_ERROR_ON_FILE_IO); + if(unlikely(!ff)) return 0; -// ---------------------------------------------------------------------------- -// macro to calculate the incremental rate of a value -// each parameter is accessed only ONCE - so it is safe to pass function calls -// or other macros as parameters + ff = procfile_readall(ff); + if(unlikely(!ff)) return 0; -#define incremental_rate(rate_variable, last_kernel_variable, new_kernel_value, collected_usec, last_collected_usec) { \ - kernel_uint_t _new_tmp = new_kernel_value; \ - rate_variable = (_new_tmp - last_kernel_variable) * (USEC_PER_SEC * RATES_DETAIL) / (collected_usec - last_collected_usec); \ - last_kernel_variable = _new_tmp; \ + calls_counter++; + + // let ARL use this pid + arl_ptr.p = p; + arl_ptr.ff = ff; + + size_t lines = procfile_lines(ff), l; + arl_begin(p->status_arl); + + for(l = 0; l < lines ;l++) { + // fprintf(stderr, "CHECK: line %zu of %zu, key '%s' = '%s'\n", l, lines, procfile_lineword(ff, l, 0), procfile_lineword(ff, l, 1)); + arl_ptr.line = l; + if(unlikely(arl_check(p->status_arl, + procfile_lineword(ff, l, 0), + procfile_lineword(ff, l, 1)))) break; } -// the same macro for struct pid members -#define pid_incremental_rate(type, var, value) \ - incremental_rate(var, var##_raw, value, p->type##_collected_usec, p->last_##type##_collected_usec) + p->status_vmshared = p->status_rssfile + p->status_rssshmem; + + // fprintf(stderr, "%s uid %d, gid %d, VmSize %zu, VmRSS %zu, RssFile %zu, RssShmem %zu, shared %zu\n", p->comm, (int)p->uid, (int)p->gid, p->status_vmsize, p->status_vmrss, p->status_rssfile, p->status_rssshmem, p->status_vmshared); + + return 1; +#endif +} // ---------------------------------------------------------------------------- @@ -930,7 +1071,7 @@ static inline int read_proc_pid_stat(struct pid_stat *p, void *ptr) { // p->flags = str2uint64_t(procfile_lineword(ff, 0, 8)); #endif - if(strcmp(p->comm, comm)) { + if(strcmp(p->comm, comm) != 0) { if(unlikely(debug)) { if(p->comm[0]) fprintf(stderr, "apps.plugin: \tpid %d (%s) changed name to '%s'\n", p->pid, p->comm, comm); @@ -955,7 +1096,7 @@ static inline int read_proc_pid_stat(struct pid_stat *p, void *ptr) { pid_incremental_rate(stat, p->utime, (kernel_uint_t)proc_info->ki_rusage.ru_utime.tv_sec * 100 + proc_info->ki_rusage.ru_utime.tv_usec / 10000); pid_incremental_rate(stat, p->stime, (kernel_uint_t)proc_info->ki_rusage.ru_stime.tv_sec * 100 + proc_info->ki_rusage.ru_stime.tv_usec / 10000); pid_incremental_rate(stat, p->cutime, (kernel_uint_t)proc_info->ki_rusage_ch.ru_utime.tv_sec * 100 + proc_info->ki_rusage_ch.ru_utime.tv_usec / 10000); - pid_incremental_rate(stat, p->cstime, (kernel_uint_t)proc_info->ki_rusage_ch.ru_stime.tv_sec * 100 + proc_info->ki_rusage_ch.ru_utime.tv_usec / 10000); + pid_incremental_rate(stat, p->cstime, (kernel_uint_t)proc_info->ki_rusage_ch.ru_stime.tv_sec * 100 + proc_info->ki_rusage_ch.ru_stime.tv_usec / 10000); p->num_threads = proc_info->ki_numthreads; @@ -1045,57 +1186,6 @@ cleanup: return 0; } -static inline int read_proc_pid_statm(struct pid_stat *p, void *ptr) { - (void)ptr; -#ifdef __FreeBSD__ - struct kinfo_proc *proc_info = (struct kinfo_proc *)ptr; -#else - static procfile *ff = NULL; - - if(unlikely(!p->statm_filename)) { - char filename[FILENAME_MAX + 1]; - snprintfz(filename, FILENAME_MAX, "%s/proc/%d/statm", netdata_configured_host_prefix, p->pid); - p->statm_filename = strdupz(filename); - } - - ff = procfile_reopen(ff, p->statm_filename, NULL, PROCFILE_FLAG_NO_ERROR_ON_FILE_IO); - if(unlikely(!ff)) goto cleanup; - - ff = procfile_readall(ff); - if(unlikely(!ff)) goto cleanup; -#endif - - calls_counter++; - -#ifdef __FreeBSD__ - p->statm_size = proc_info->ki_size / sysconf(_SC_PAGESIZE); - p->statm_resident = proc_info->ki_rssize; - p->statm_share = 0; // do we have to use ru_ixrss here? -#else - p->statm_size = str2kernel_uint_t(procfile_lineword(ff, 0, 0)); - p->statm_resident = str2kernel_uint_t(procfile_lineword(ff, 0, 1)); - p->statm_share = str2kernel_uint_t(procfile_lineword(ff, 0, 2)); - // p->statm_text = str2kernel_uint_t(procfile_lineword(ff, 0, 3)); - // p->statm_lib = str2kernel_uint_t(procfile_lineword(ff, 0, 4)); - // p->statm_data = str2kernel_uint_t(procfile_lineword(ff, 0, 5)); - // p->statm_dirty = str2kernel_uint_t(procfile_lineword(ff, 0, 6)); -#endif - - return 1; - -#ifndef __FreeBSD__ -cleanup: - p->statm_size = 0; - p->statm_resident = 0; - p->statm_share = 0; - // p->statm_text = 0; - // p->statm_lib = 0; - // p->statm_data = 0; - // p->statm_dirty = 0; - return 0; -#endif -} - static inline int read_proc_pid_io(struct pid_stat *p, void *ptr) { (void)ptr; #ifdef __FreeBSD__ @@ -1979,7 +2069,7 @@ static inline void link_all_processes_to_their_parents(void) { // 1. read all files in /proc // 2. for each numeric directory: // i. read /proc/pid/stat -// ii. read /proc/pid/statm +// ii. read /proc/pid/status // iii. read /proc/pid/io (requires root access) // iii. read the entries in directory /proc/pid/fd (requires root access) // for each entry: @@ -1992,7 +2082,7 @@ static inline void link_all_processes_to_their_parents(void) { // to avoid filling up all disk space // if debug is enabled, all errors are printed -#ifndef __FreeBSD__ +#if (ALL_PIDS_ARE_READ_INSTANTLY == 0) static int compar_pid(const void *pid1, const void *pid2) { struct pid_stat *p1 = all_pids[*((pid_t *)pid1)]; @@ -2006,8 +2096,8 @@ static int compar_pid(const void *pid1, const void *pid2) { #endif static inline int collect_data_for_pid(pid_t pid, void *ptr) { - if(unlikely(pid < INIT_PID || pid > pid_max)) { - error("Invalid pid %d read (expected %d to %d). Ignoring process.", pid, INIT_PID, pid_max); + if(unlikely(pid < 0 || pid > pid_max)) { + error("Invalid pid %d read (expected %d to %d). Ignoring process.", pid, 0, pid_max); return 0; } @@ -2024,8 +2114,6 @@ static inline int collect_data_for_pid(pid_t pid, void *ptr) { // there is no reason to proceed if we cannot get its status return 0; - read_proc_pid_ownership(p, 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); @@ -2038,10 +2126,10 @@ static inline int collect_data_for_pid(pid_t pid, void *ptr) { managed_log(p, PID_LOG_IO, read_proc_pid_io(p, ptr)); // -------------------------------------------------------------------- - // /proc/<pid>/statm + // /proc/<pid>/status - if(unlikely(!managed_log(p, PID_LOG_STATM, read_proc_pid_statm(p, ptr)))) - // there is no reason to proceed if we cannot get its memory status + if(unlikely(!managed_log(p, PID_LOG_STATUS, read_proc_pid_status(p, ptr)))) + // there is no reason to proceed if we cannot get its status return 0; // -------------------------------------------------------------------- @@ -2069,28 +2157,46 @@ static int collect_data_for_all_processes(void) { #ifdef __FreeBSD__ int i, procnum; - size_t procbase_size; - static struct kinfo_proc *procbase; - int mib[3]; + static size_t procbase_size = 0; + static struct kinfo_proc *procbase = NULL; - mib[0] = CTL_KERN; - mib[1] = KERN_PROC; - mib[2] = KERN_PROC_PROC; - if (unlikely(sysctl(mib, 3, NULL, &procbase_size, NULL, 0))) { + size_t new_procbase_size; + + 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"); return 0; } - procbase = reallocz(procbase, procbase_size); - if (unlikely(sysctl(mib, 3, procbase, &procbase_size, NULL, 0))) { + + // give it some air for processes that may be started + // during this little time. + new_procbase_size += 100 * sizeof(struct kinfo_proc); + + // increase the buffer if needed + if(new_procbase_size > procbase_size) { + procbase_size = new_procbase_size; + procbase = reallocz(procbase, procbase_size); + } + + // sysctl() gets from new_procbase_size the buffer size + // and also returns to it the amount of data filled in + new_procbase_size = procbase_size; + + // 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"); return 0; } - procnum = procbase_size / sizeof(struct kinfo_proc); + + // based on the amount of data filled in + // calculate the number of processes we got + procnum = new_procbase_size / sizeof(struct kinfo_proc); + #endif if(all_pids_count) { -#ifndef __FreeBSD__ +#if (ALL_PIDS_ARE_READ_INSTANTLY == 0) size_t slc = 0; #endif for(p = root_of_pids; p ; p = p->next) { @@ -2107,7 +2213,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 more.", 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); all_pids_count = slc; } @@ -2130,7 +2236,7 @@ static int collect_data_for_all_processes(void) { } #ifdef __FreeBSD__ - for (i = INIT_PID; i < procnum - INIT_PID; ++i) { + for (i = 0 ; i < procnum ; ++i) { pid_t pid = procbase[i].ki_pid; collect_data_for_pid(pid, &procbase[i]); } @@ -2258,21 +2364,17 @@ static void apply_apps_groups_targets_inheritance(void) { if(unlikely(!p->sortlist && !p->children_count)) p->sortlist = sortlist++; - // if this process does not have any children - // and is not already merged - // and has a parent - // and its parent has children - // and the target of this process and its parent is the same, or the parent does not have a target - // and its parent is not init - // then, mark them as merged. if(unlikely( - !p->children_count - && !p->merged - && p->parent - && p->parent->children_count + !p->children_count // if this process does not have any children + && !p->merged // and is not already merged + && p->parent // and has a parent + && p->parent->children_count // and its parent has children + // and the target of this process and its parent is the same, + // or the parent does not have a target && (p->target == p->parent->target || !p->parent->target) - && p->ppid != INIT_PID + && p->ppid != INIT_PID // and its parent is not init )) { + // mark it as merged p->parent->children_count--; p->merged = 1; @@ -2296,6 +2398,10 @@ static void apply_apps_groups_targets_inheritance(void) { if(all_pids[INIT_PID]) all_pids[INIT_PID]->target = apps_groups_default_target; + // pid 0 goes always to default target + if(all_pids[0]) + all_pids[0]->target = apps_groups_default_target; + // give a default target on all top level processes if(unlikely(debug)) loops++; for(p = root_of_pids; p ; p = p->next) { @@ -2353,13 +2459,12 @@ static size_t zero_all_targets(struct target *root) { // w->rss = 0; w->processes = 0; - w->statm_size = 0; - w->statm_resident = 0; - w->statm_share = 0; - // w->statm_text = 0; - // w->statm_lib = 0; - // w->statm_data = 0; - // w->statm_dirty = 0; + w->status_vmsize = 0; + w->status_vmrss = 0; + w->status_vmshared = 0; + w->status_rssfile = 0; + w->status_rssshmem = 0; + w->status_vmswap = 0; w->io_logical_bytes_read = 0; w->io_logical_bytes_written = 0; @@ -2505,13 +2610,12 @@ static inline void aggregate_pid_on_target(struct target *w, struct pid_stat *p, // w->rss += p->rss; - w->statm_size += p->statm_size; - w->statm_resident += p->statm_resident; - w->statm_share += p->statm_share; - // w->statm_text += p->statm_text; - // w->statm_lib += p->statm_lib; - // w->statm_data += p->statm_data; - // w->statm_dirty += p->statm_dirty; + w->status_vmsize += p->status_vmsize; + w->status_vmrss += p->status_vmrss; + w->status_vmshared += p->status_vmshared; + w->status_rssfile += p->status_rssfile; + w->status_rssshmem += p->status_rssshmem; + w->status_vmswap += p->status_vmswap; w->io_logical_bytes_read += p->io_logical_bytes_read; w->io_logical_bytes_written += p->io_logical_bytes_written; @@ -2944,17 +3048,26 @@ static void send_collected_data_to_netdata(struct target *root, const char *type send_BEGIN(type, "mem", dt); for (w = root; w ; w = w->next) { if(unlikely(w->exposed)) - send_SET(w->name, (w->statm_resident > w->statm_share)?(w->statm_resident - w->statm_share):0ULL); + send_SET(w->name, (w->status_vmrss > w->status_vmshared)?(w->status_vmrss - w->status_vmshared):0ULL); } send_END(); send_BEGIN(type, "vmem", dt); for (w = root; w ; w = w->next) { if(unlikely(w->exposed)) - send_SET(w->name, w->statm_size); + send_SET(w->name, w->status_vmsize); } send_END(); +#ifndef __FreeBSD__ + send_BEGIN(type, "swap", dt); + for (w = root; w ; w = w->next) { + if(unlikely(w->exposed)) + send_SET(w->name, w->status_vmswap); + } + send_END(); +#endif + send_BEGIN(type, "minor_faults", dt); for (w = root; w ; w = w->next) { if(unlikely(w->exposed)) @@ -3056,22 +3169,22 @@ static void send_charts_updates_to_netdata(struct target *root, const char *type fprintf(stdout, "CHART %s.mem '' '%s Real Memory (w/o shared)' 'MB' mem %s.mem stacked 20003 %d\n", type, title, type, update_every); for (w = root; w ; w = w->next) { if(unlikely(w->exposed)) - fprintf(stdout, "DIMENSION %s '' absolute %ld %ld\n", w->name, sysconf(_SC_PAGESIZE), 1024L*1024L); + fprintf(stdout, "DIMENSION %s '' absolute %ld %ld\n", w->name, 1L, 1024L); } - fprintf(stdout, "CHART %s.vmem '' '%s Virtual Memory Size' 'MB' mem %s.vmem stacked 20004 %d\n", type, title, type, update_every); + fprintf(stdout, "CHART %s.vmem '' '%s Virtual Memory Size' 'MB' mem %s.vmem stacked 20005 %d\n", type, title, type, update_every); for (w = root; w ; w = w->next) { if(unlikely(w->exposed)) - fprintf(stdout, "DIMENSION %s '' absolute %ld %ld\n", w->name, sysconf(_SC_PAGESIZE), 1024L*1024L); + fprintf(stdout, "DIMENSION %s '' absolute %ld %ld\n", w->name, 1L, 1024L); } - fprintf(stdout, "CHART %s.threads '' '%s Threads' 'threads' processes %s.threads stacked 20005 %d\n", type, title, type, update_every); + fprintf(stdout, "CHART %s.threads '' '%s Threads' 'threads' processes %s.threads stacked 20006 %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); } - fprintf(stdout, "CHART %s.processes '' '%s Processes' 'processes' processes %s.processes stacked 20004 %d\n", type, title, type, update_every); + fprintf(stdout, "CHART %s.processes '' '%s Processes' 'processes' processes %s.processes stacked 20007 %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); @@ -3097,7 +3210,15 @@ static void send_charts_updates_to_netdata(struct target *root, const char *type } } - fprintf(stdout, "CHART %s.major_faults '' '%s Major Page Faults (swap read)' 'page faults/s' swap %s.major_faults stacked 20010 %d\n", type, title, type, update_every); +#ifndef __FreeBSD__ + fprintf(stdout, "CHART %s.swap '' '%s Swap Memory' 'MB' swap %s.swap stacked 20011 %d\n", type, title, type, update_every); + for (w = root; w ; w = w->next) { + if(unlikely(w->exposed)) + fprintf(stdout, "DIMENSION %s '' absolute %ld %ld\n", w->name, 1L, 1024L); + } +#endif + + fprintf(stdout, "CHART %s.major_faults '' '%s Major Page Faults (swap read)' 'page faults/s' swap %s.major_faults stacked 20012 %d\n", type, title, type, update_every); for (w = root; w ; w = w->next) { if(unlikely(w->exposed)) fprintf(stdout, "DIMENSION %s '' absolute 1 %llu\n", w->name, RATES_DETAIL); @@ -3388,6 +3509,8 @@ static int check_capabilities() { int main(int argc, char **argv) { // debug_flags = D_PROCFILE; + pagesize = (size_t)sysconf(_SC_PAGESIZE); + // set the name for logging program_name = "apps.plugin"; @@ -3469,7 +3592,7 @@ int main(int argc, char **argv) { #warning "compiling for profiling" static int profiling_count=0; profiling_count++; - if(unlikely(profiling_count > 1000)) exit(0); + if(unlikely(profiling_count > 2000)) exit(0); usec_t dt = update_every * USEC_PER_SEC; #else usec_t dt = heartbeat_next(&hb, step); |