@cryptotaxi247 / netdata-1 / commits / 16583a1b6

apps.plugin now reads /proc/PID/status; fixes #3405

Costa Tsaousis (ktsaou) committed Feb 17, 2018 at 14:46 UTC 16583a1b64004b0230c965f91d996a8a8d205c08
4 files changed +241 -139
src/Makefile.am
+5
@@ -248,6 +248,11 @@ if FREEBSD
248 apps_plugin_SOURCES += \
249 plugin_freebsd.h \
250 $(NULL)
251 +else
252 +apps_plugin_SOURCES += \
253 + adaptive_resortable_list.c \
254 + adaptive_resortable_list.h \
255 + $(NULL)
256 endif
257
258 apps_plugin_LDADD = \
src/adaptive_resortable_list.c
+14 -6
@@ -96,9 +96,14 @@ void arl_begin(ARL_BASE *base) {
96 }
97 #endif
98
99 - if(unlikely(base->added || base->iteration % base->rechecks) == 1) {
99 + if(unlikely(base->iteration > 0 && (base->added || (base->iteration % base->rechecks) == 0))) {
100 + int wanted_equals_expected = ((base->iteration % base->rechecks) == 0);
101 +
102 + // fprintf(stderr, "\n\narl_begin() rechecking, added %zu, iteration %zu, rechecks %zu, wanted_equals_expected %d\n\n\n", base->added, base->iteration, base->rechecks, wanted_equals_expected);
103 +
104 base->added = 0;
101 - base->wanted = 0;
105 + base->wanted = (wanted_equals_expected)?base->expected:0;
106 +
107 ARL_ENTRY *e = base->head;
108 while(e) {
109 if(e->flags & ARL_ENTRY_FLAG_FOUND) {
@@ -107,7 +112,7 @@ void arl_begin(ARL_BASE *base) {
112 e->flags &= ~ARL_ENTRY_FLAG_FOUND;
113
114 // count it in wanted
110 - if(e->flags & ARL_ENTRY_FLAG_EXPECTED)
115 + if(!wanted_equals_expected && e->flags & ARL_ENTRY_FLAG_EXPECTED)
116 base->wanted++;
117
118 }
@@ -155,10 +160,11 @@ void arl_begin(ARL_BASE *base) {
160
161 // register an expected keyword to the ARL
162 // together with its destination ( i.e. the output of the processor() )
158 -ARL_ENTRY *arl_expect(ARL_BASE *base, const char *keyword, void *dst) {
163 +ARL_ENTRY *arl_expect_custom(ARL_BASE *base, const char *keyword, void (*processor)(const char *name, uint32_t hash, const char *value, void *dst), void *dst) {
164 ARL_ENTRY *e = callocz(1, sizeof(ARL_ENTRY));
165 e->name = strdupz(keyword);
166 e->hash = simple_hash(e->name);
167 + e->processor = (processor)?processor:base->processor;
168 e->dst = dst;
169 e->flags = ARL_ENTRY_FLAG_EXPECTED;
170 e->prev = NULL;
@@ -198,7 +204,7 @@ int arl_find_or_create_and_relink(ARL_BASE *base, const char *s, const char *val
204
205 // run the processor for it
206 if(unlikely(e->dst)) {
201 - base->processor(e->name, hash, value, e->dst);
207 + e->processor(e->name, hash, value, e->dst);
208 base->found++;
209 }
210
@@ -254,8 +260,10 @@ int arl_find_or_create_and_relink(ARL_BASE *base, const char *s, const char *val
260 if(unlikely(!base->next_keyword))
261 base->next_keyword = base->head;
262
257 - if(unlikely(base->found == base->wanted))
263 + if(unlikely(base->found == base->wanted)) {
264 + // fprintf(stderr, "FOUND ALL WANTED 1: found = %zu, wanted = %zu, expected %zu\n", base->found, base->wanted, base->expected);
265 return 1;
266 + }
267
268 return 0;
269 }
src/adaptive_resortable_list.h
+9 -3
@@ -51,6 +51,9 @@ typedef struct arl_entry {
51
52 uint8_t flags; // ARL_ENTRY_FLAG_*
53
54 + // the processor to do the job
55 + void (*processor)(const char *name, uint32_t hash, const char *value, void *dst);
56 +
57 // double linked list for fast re-linkings
58 struct arl_entry *prev, *next;
59 } ARL_ENTRY;
@@ -102,7 +105,8 @@ extern void arl_free(ARL_BASE *arl_base);
105
106 // register an expected keyword to the ARL
107 // together with its destination ( i.e. the output of the processor() )
105 -extern ARL_ENTRY *arl_expect(ARL_BASE *base, const char *keyword, void *dst);
108 +extern ARL_ENTRY *arl_expect_custom(ARL_BASE *base, const char *keyword, void (*processor)(const char *name, uint32_t hash, const char *value, void *dst), void *dst);
109 +#define arl_expect(base, keyword, dst) arl_expect_custom(base, keyword, NULL, dst)
110
111 // an internal call to complete the check() call
112 extern int arl_find_or_create_and_relink(ARL_BASE *base, const char *s, const char *value);
@@ -138,7 +142,7 @@ static inline int arl_check(ARL_BASE *base, const char *keyword, const char *val
142
143 // execute the processor
144 if(unlikely(e->dst)) {
141 - base->processor(e->name, e->hash, value, e->dst);
145 + e->processor(e->name, e->hash, value, e->dst);
146 base->found++;
147 }
148
@@ -148,8 +152,10 @@ static inline int arl_check(ARL_BASE *base, const char *keyword, const char *val
152 base->next_keyword = base->head;
153
154 // stop if we collected all the values for this iteration
151 - if(unlikely(base->found == base->wanted))
155 + if(unlikely(base->found == base->wanted)) {
156 + // fprintf(stderr, "FOUND ALL WANTED 2: found = %zu, wanted = %zu, expected %zu\n", base->found, base->wanted, base->expected);
157 return 1;
158 + }
159
160 return 0;
161 }
src/apps_plugin.c
+213 -130
@@ -162,13 +162,12 @@ struct target {
162 kernel_uint_t num_threads;
163 // kernel_uint_t rss;
164
165 - kernel_uint_t statm_size;
166 - kernel_uint_t statm_resident;
167 - kernel_uint_t statm_share;
168 - // kernel_uint_t statm_text;
169 - // kernel_uint_t statm_lib;
170 - // kernel_uint_t statm_data;
171 - // kernel_uint_t statm_dirty;
165 + kernel_uint_t status_vmsize;
166 + kernel_uint_t status_vmrss;
167 + kernel_uint_t status_vmshared;
168 + kernel_uint_t status_rssfile;
169 + kernel_uint_t status_rssshmem;
170 + kernel_uint_t status_vmswap;
171
172 kernel_uint_t io_logical_bytes_read;
173 kernel_uint_t io_logical_bytes_written;
@@ -287,13 +286,13 @@ struct pid_stat {
286 uid_t uid;
287 gid_t gid;
288
290 - kernel_uint_t statm_size;
291 - kernel_uint_t statm_resident;
292 - kernel_uint_t statm_share;
293 - // kernel_uint_t statm_text;
294 - // kernel_uint_t statm_lib;
295 - // kernel_uint_t statm_data;
296 - // kernel_uint_t statm_dirty;
289 + kernel_uint_t status_vmsize;
290 + kernel_uint_t status_vmrss;
291 + kernel_uint_t status_vmshared;
292 + kernel_uint_t status_rssfile;
293 + kernel_uint_t status_rssshmem;
294 + kernel_uint_t status_vmswap;
295 + ARL_BASE *status_arl;
296
297 kernel_uint_t io_logical_bytes_read_raw;
298 kernel_uint_t io_logical_bytes_written_raw;
@@ -337,7 +336,7 @@ struct pid_stat {
336 char *fds_dirname; // the full directory name in /proc/PID/fd
337
338 char *stat_filename;
340 - char *statm_filename;
339 + char *status_filename;
340 char *io_filename;
341 char *cmdline_filename;
342
@@ -346,10 +345,13 @@ struct pid_stat {
345 struct pid_stat *next;
346 };
347
348 +size_t pagesize;
349 +size_t kb_per_page;
350 +
351 // log each problem once per process
352 // log flood protection flags (log_thrown)
353 #define PID_LOG_IO 0x00000001
352 -#define PID_LOG_STATM 0x00000002
354 +#define PID_LOG_STATUS 0x00000002
355 #define PID_LOG_CMDLINE 0x00000004
356 #define PID_LOG_FDS 0x00000008
357 #define PID_LOG_STAT 0x00000010
@@ -694,7 +696,8 @@ static inline void del_pid_entry(pid_t pid) {
696 freez(p->fds);
697 freez(p->fds_dirname);
698 freez(p->stat_filename);
697 - freez(p->statm_filename);
699 + freez(p->status_filename);
700 + arl_free(p->status_arl);
701 freez(p->io_filename);
702 freez(p->cmdline_filename);
703 freez(p->cmdline);
@@ -722,11 +725,11 @@ static inline int managed_log(struct pid_stat *p, uint32_t log, int status) {
725 #endif
726 break;
727
725 - case PID_LOG_STATM:
728 + case PID_LOG_STATUS:
729 #ifdef __FreeBSD__
727 - error("Cannot fetch process %d memory info (command '%s')", p->pid, p->comm);
730 + error("Cannot fetch process %d status info (command '%s')", p->pid, p->comm);
731 #else
729 - error("Cannot process %s/proc/%d/statm (command '%s')", netdata_configured_host_prefix, p->pid, p->comm);
732 + error("Cannot process %s/proc/%d/status (command '%s')", netdata_configured_host_prefix, p->pid, p->comm);
733 #endif
734 break;
735
@@ -848,37 +851,6 @@ cleanup:
851 return 0;
852 }
853
851 -static inline int read_proc_pid_ownership(struct pid_stat *p, void *ptr) {
852 - (void)ptr;
853 -#ifdef __FreeBSD__
854 - struct kinfo_proc *proc_info = (struct kinfo_proc *)ptr;
855 -
856 - p->uid = proc_info->ki_uid;
857 - p->gid = proc_info->ki_groups[0];
858 -
859 - return 1;
860 -#else
861 - if(unlikely(!p->stat_filename)) {
862 - error("pid %d does not have a stat_filename", p->pid);
863 - return 0;
864 - }
865 -
866 - // ----------------------------------------
867 - // read uid and gid
868 -
869 - struct stat st;
870 - if(stat(p->stat_filename, &st) != 0) {
871 - error("Cannot stat file '%s'", p->stat_filename);
872 - return 1;
873 - }
874 -
875 - p->uid = st.st_uid;
876 - p->gid = st.st_gid;
877 -
878 - return 1;
879 -#endif
880 -}
881 -
854 // ----------------------------------------------------------------------------
855 // macro to calculate the incremental rate of a value
856 // each parameter is accessed only ONCE - so it is safe to pass function calls
@@ -895,6 +867,156 @@ static inline int read_proc_pid_ownership(struct pid_stat *p, void *ptr) {
867 incremental_rate(var, var##_raw, value, p->type##_collected_usec, p->last_##type##_collected_usec)
868
869
870 +// ----------------------------------------------------------------------------
871 +
872 +#ifndef __FreeBSD__
873 +struct arl_callback_ptr {
874 + struct pid_stat *p;
875 + procfile *ff;
876 + size_t line;
877 +};
878 +
879 +void arl_callback_status_uid(const char *name, uint32_t hash, const char *value, void *dst) {
880 + (void)name; (void)hash; (void)value;
881 + struct arl_callback_ptr *aptr = (struct arl_callback_ptr *)dst;
882 + if(unlikely(procfile_linewords(aptr->ff, aptr->line) < 5)) return;
883 +
884 + //const char *real_uid = procfile_lineword(aptr->ff, aptr->line, 1);
885 + const char *effective_uid = procfile_lineword(aptr->ff, aptr->line, 2);
886 + //const char *saved_uid = procfile_lineword(aptr->ff, aptr->line, 3);
887 + //const char *filesystem_uid = procfile_lineword(aptr->ff, aptr->line, 4);
888 +
889 + if(likely(effective_uid && *effective_uid))
890 + aptr->p->uid = (uid_t)str2l(effective_uid);
891 +}
892 +
893 +void arl_callback_status_gid(const char *name, uint32_t hash, const char *value, void *dst) {
894 + (void)name; (void)hash; (void)value;
895 + struct arl_callback_ptr *aptr = (struct arl_callback_ptr *)dst;
896 + if(unlikely(procfile_linewords(aptr->ff, aptr->line) < 5)) return;
897 +
898 + //const char *real_gid = procfile_lineword(aptr->ff, aptr->line, 1);
899 + const char *effective_gid = procfile_lineword(aptr->ff, aptr->line, 2);
900 + //const char *saved_gid = procfile_lineword(aptr->ff, aptr->line, 3);
901 + //const char *filesystem_gid = procfile_lineword(aptr->ff, aptr->line, 4);
902 +
903 + if(likely(effective_gid && *effective_gid))
904 + aptr->p->gid = (uid_t)str2l(effective_gid);
905 +}
906 +
907 +void arl_callback_status_vmsize(const char *name, uint32_t hash, const char *value, void *dst) {
908 + (void)name; (void)hash; (void)value;
909 + struct arl_callback_ptr *aptr = (struct arl_callback_ptr *)dst;
910 + if(unlikely(procfile_linewords(aptr->ff, aptr->line) < 3)) return;
911 +
912 + aptr->p->status_vmsize = str2kernel_uint_t(procfile_lineword(aptr->ff, aptr->line, 1)) / kb_per_page;
913 +}
914 +
915 +void arl_callback_status_vmswap(const char *name, uint32_t hash, const char *value, void *dst) {
916 + (void)name; (void)hash; (void)value;
917 + struct arl_callback_ptr *aptr = (struct arl_callback_ptr *)dst;
918 + if(unlikely(procfile_linewords(aptr->ff, aptr->line) < 3)) return;
919 +
920 + aptr->p->status_vmswap = str2kernel_uint_t(procfile_lineword(aptr->ff, aptr->line, 1)) / kb_per_page;
921 +}
922 +
923 +void arl_callback_status_vmrss(const char *name, uint32_t hash, const char *value, void *dst) {
924 + (void)name; (void)hash; (void)value;
925 + struct arl_callback_ptr *aptr = (struct arl_callback_ptr *)dst;
926 + if(unlikely(procfile_linewords(aptr->ff, aptr->line) < 3)) return;
927 +
928 + aptr->p->status_vmrss = str2kernel_uint_t(procfile_lineword(aptr->ff, aptr->line, 1)) / kb_per_page;
929 +}
930 +
931 +void arl_callback_status_rssfile(const char *name, uint32_t hash, const char *value, void *dst) {
932 + (void)name; (void)hash; (void)value;
933 + struct arl_callback_ptr *aptr = (struct arl_callback_ptr *)dst;
934 + if(unlikely(procfile_linewords(aptr->ff, aptr->line) < 3)) return;
935 +
936 + aptr->p->status_rssfile = str2kernel_uint_t(procfile_lineword(aptr->ff, aptr->line, 1)) / kb_per_page;
937 +}
938 +
939 +void arl_callback_status_rssshmem(const char *name, uint32_t hash, const char *value, void *dst) {
940 + (void)name; (void)hash; (void)value;
941 + struct arl_callback_ptr *aptr = (struct arl_callback_ptr *)dst;
942 + if(unlikely(procfile_linewords(aptr->ff, aptr->line) < 3)) return;
943 +
944 + aptr->p->status_rssshmem = str2kernel_uint_t(procfile_lineword(aptr->ff, aptr->line, 1)) / kb_per_page;
945 +}
946 +#endif // !__FreeBSD__
947 +
948 +static inline int read_proc_pid_status(struct pid_stat *p, void *ptr) {
949 + p->status_vmsize = 0;
950 + p->status_vmrss = 0;
951 + p->status_vmshared = 0;
952 + p->status_rssfile = 0;
953 + p->status_rssshmem = 0;
954 + p->status_vmswap = 0;
955 +
956 +#ifdef __FreeBSD__
957 + struct kinfo_proc *proc_info = (struct kinfo_proc *)ptr;
958 +
959 + p->uid = proc_info->ki_uid;
960 + p->gid = proc_info->ki_groups[0];
961 + p->status_vmsize = proc_info->ki_size / pagesize;
962 + p->status_vmrss = proc_info->ki_rssize;
963 + // FIXME: what about shared and swap memory on FreeBSD?
964 + return 1;
965 +#else
966 + (void)ptr;
967 +
968 + static struct arl_callback_ptr arl_ptr;
969 + static procfile *ff = NULL;
970 +
971 + if(unlikely(!p->status_arl)) {
972 + p->status_arl = arl_create("/proc/pid/status", NULL, 60);
973 + arl_expect_custom(p->status_arl, "Uid", arl_callback_status_uid, &arl_ptr);
974 + arl_expect_custom(p->status_arl, "Gid", arl_callback_status_gid, &arl_ptr);
975 + arl_expect_custom(p->status_arl, "VmSize", arl_callback_status_vmsize, &arl_ptr);
976 + arl_expect_custom(p->status_arl, "VmRSS", arl_callback_status_vmrss, &arl_ptr);
977 + arl_expect_custom(p->status_arl, "RssFile", arl_callback_status_rssfile, &arl_ptr);
978 + arl_expect_custom(p->status_arl, "RssShmem", arl_callback_status_rssshmem, &arl_ptr);
979 + arl_expect_custom(p->status_arl, "VmSwap", arl_callback_status_vmswap, &arl_ptr);
980 + }
981 +
982 + if(unlikely(!p->status_filename)) {
983 + char filename[FILENAME_MAX + 1];
984 + snprintfz(filename, FILENAME_MAX, "%s/proc/%d/status", netdata_configured_host_prefix, p->pid);
985 + p->status_filename = strdupz(filename);
986 + }
987 +
988 + ff = procfile_reopen(ff, p->status_filename, (!ff)?" \t:,-()/":NULL, PROCFILE_FLAG_NO_ERROR_ON_FILE_IO);
989 + if(unlikely(!ff)) return 0;
990 +
991 + ff = procfile_readall(ff);
992 + if(unlikely(!ff)) return 0;
993 +
994 + calls_counter++;
995 +
996 + // let ARL use this pid
997 + arl_ptr.p = p;
998 + arl_ptr.ff = ff;
999 +
1000 + size_t lines = procfile_lines(ff), l;
1001 + arl_begin(p->status_arl);
1002 +
1003 + for(l = 0; l < lines ;l++) {
1004 + // fprintf(stderr, "CHECK: line %zu of %zu, key '%s' = '%s'\n", l, lines, procfile_lineword(ff, l, 0), procfile_lineword(ff, l, 1));
1005 + arl_ptr.line = l;
1006 + if(unlikely(arl_check(p->status_arl,
1007 + procfile_lineword(ff, l, 0),
1008 + procfile_lineword(ff, l, 1)))) break;
1009 + }
1010 +
1011 + p->status_vmshared = p->status_rssfile + p->status_rssshmem;
1012 +
1013 + // 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);
1014 +
1015 + return 1;
1016 +#endif
1017 +}
1018 +
1019 +
1020 // ----------------------------------------------------------------------------
1021
1022 static inline int read_proc_pid_stat(struct pid_stat *p, void *ptr) {
@@ -1061,57 +1183,6 @@ cleanup:
1183 return 0;
1184 }
1185
1064 -static inline int read_proc_pid_statm(struct pid_stat *p, void *ptr) {
1065 - (void)ptr;
1066 -#ifdef __FreeBSD__
1067 - struct kinfo_proc *proc_info = (struct kinfo_proc *)ptr;
1068 -#else
1069 - static procfile *ff = NULL;
1070 -
1071 - if(unlikely(!p->statm_filename)) {
1072 - char filename[FILENAME_MAX + 1];
1073 - snprintfz(filename, FILENAME_MAX, "%s/proc/%d/statm", netdata_configured_host_prefix, p->pid);
1074 - p->statm_filename = strdupz(filename);
1075 - }
1076 -
1077 - ff = procfile_reopen(ff, p->statm_filename, NULL, PROCFILE_FLAG_NO_ERROR_ON_FILE_IO);
1078 - if(unlikely(!ff)) goto cleanup;
1079 -
1080 - ff = procfile_readall(ff);
1081 - if(unlikely(!ff)) goto cleanup;
1082 -#endif
1083 -
1084 - calls_counter++;
1085 -
1086 -#ifdef __FreeBSD__
1087 - p->statm_size = proc_info->ki_size / sysconf(_SC_PAGESIZE);
1088 - p->statm_resident = proc_info->ki_rssize;
1089 - p->statm_share = 0; // do we have to use ru_ixrss here?
1090 -#else
1091 - p->statm_size = str2kernel_uint_t(procfile_lineword(ff, 0, 0));
1092 - p->statm_resident = str2kernel_uint_t(procfile_lineword(ff, 0, 1));
1093 - p->statm_share = str2kernel_uint_t(procfile_lineword(ff, 0, 2));
1094 - // p->statm_text = str2kernel_uint_t(procfile_lineword(ff, 0, 3));
1095 - // p->statm_lib = str2kernel_uint_t(procfile_lineword(ff, 0, 4));
1096 - // p->statm_data = str2kernel_uint_t(procfile_lineword(ff, 0, 5));
1097 - // p->statm_dirty = str2kernel_uint_t(procfile_lineword(ff, 0, 6));
1098 -#endif
1099 -
1100 - return 1;
1101 -
1102 -#ifndef __FreeBSD__
1103 -cleanup:
1104 - p->statm_size = 0;
1105 - p->statm_resident = 0;
1106 - p->statm_share = 0;
1107 - // p->statm_text = 0;
1108 - // p->statm_lib = 0;
1109 - // p->statm_data = 0;
1110 - // p->statm_dirty = 0;
1111 - return 0;
1112 -#endif
1113 -}
1114 -
1186 static inline int read_proc_pid_io(struct pid_stat *p, void *ptr) {
1187 (void)ptr;
1188 #ifdef __FreeBSD__
@@ -1995,7 +2066,7 @@ static inline void link_all_processes_to_their_parents(void) {
2066 // 1. read all files in /proc
2067 // 2. for each numeric directory:
2068 // i. read /proc/pid/stat
1998 -// ii. read /proc/pid/statm
2069 +// ii. read /proc/pid/status
2070 // iii. read /proc/pid/io (requires root access)
2071 // iii. read the entries in directory /proc/pid/fd (requires root access)
2072 // for each entry:
@@ -2040,8 +2111,6 @@ static inline int collect_data_for_pid(pid_t pid, void *ptr) {
2111 // there is no reason to proceed if we cannot get its status
2112 return 0;
2113
2043 - read_proc_pid_ownership(p, ptr);
2044 -
2114 // check its parent pid
2115 if(unlikely(p->ppid < 0 || p->ppid > pid_max)) {
2116 error("Pid %d (command '%s') states invalid parent pid %d. Using 0.", pid, p->comm, p->ppid);
@@ -2054,10 +2123,10 @@ static inline int collect_data_for_pid(pid_t pid, void *ptr) {
2123 managed_log(p, PID_LOG_IO, read_proc_pid_io(p, ptr));
2124
2125 // --------------------------------------------------------------------
2057 - // /proc/<pid>/statm
2126 + // /proc/<pid>/status
2127
2059 - if(unlikely(!managed_log(p, PID_LOG_STATM, read_proc_pid_statm(p, ptr))))
2060 - // there is no reason to proceed if we cannot get its memory status
2128 + if(unlikely(!managed_log(p, PID_LOG_STATUS, read_proc_pid_status(p, ptr))))
2129 + // there is no reason to proceed if we cannot get its status
2130 return 0;
2131
2132 // --------------------------------------------------------------------
@@ -2387,13 +2456,12 @@ static size_t zero_all_targets(struct target *root) {
2456 // w->rss = 0;
2457 w->processes = 0;
2458
2390 - w->statm_size = 0;
2391 - w->statm_resident = 0;
2392 - w->statm_share = 0;
2393 - // w->statm_text = 0;
2394 - // w->statm_lib = 0;
2395 - // w->statm_data = 0;
2396 - // w->statm_dirty = 0;
2459 + w->status_vmsize = 0;
2460 + w->status_vmrss = 0;
2461 + w->status_vmshared = 0;
2462 + w->status_rssfile = 0;
2463 + w->status_rssshmem = 0;
2464 + w->status_vmswap = 0;
2465
2466 w->io_logical_bytes_read = 0;
2467 w->io_logical_bytes_written = 0;
@@ -2539,13 +2607,12 @@ static inline void aggregate_pid_on_target(struct target *w, struct pid_stat *p,
2607
2608 // w->rss += p->rss;
2609
2542 - w->statm_size += p->statm_size;
2543 - w->statm_resident += p->statm_resident;
2544 - w->statm_share += p->statm_share;
2545 - // w->statm_text += p->statm_text;
2546 - // w->statm_lib += p->statm_lib;
2547 - // w->statm_data += p->statm_data;
2548 - // w->statm_dirty += p->statm_dirty;
2610 + w->status_vmsize += p->status_vmsize;
2611 + w->status_vmrss += p->status_vmrss;
2612 + w->status_vmshared += p->status_vmshared;
2613 + w->status_rssfile += p->status_rssfile;
2614 + w->status_rssshmem += p->status_rssshmem;
2615 + w->status_vmswap += p->status_vmswap;
2616
2617 w->io_logical_bytes_read += p->io_logical_bytes_read;
2618 w->io_logical_bytes_written += p->io_logical_bytes_written;
@@ -2978,14 +3045,21 @@ static void send_collected_data_to_netdata(struct target *root, const char *type
3045 send_BEGIN(type, "mem", dt);
3046 for (w = root; w ; w = w->next) {
3047 if(unlikely(w->exposed))
2981 - send_SET(w->name, (w->statm_resident > w->statm_share)?(w->statm_resident - w->statm_share):0ULL);
3048 + send_SET(w->name, (w->status_vmrss > w->status_vmshared)?(w->status_vmrss - w->status_vmshared):0ULL);
3049 }
3050 send_END();
3051
3052 send_BEGIN(type, "vmem", dt);
3053 for (w = root; w ; w = w->next) {
3054 if(unlikely(w->exposed))
2988 - send_SET(w->name, w->statm_size);
3055 + send_SET(w->name, w->status_vmsize);
3056 + }
3057 + send_END();
3058 +
3059 + send_BEGIN(type, "swap", dt);
3060 + for (w = root; w ; w = w->next) {
3061 + if(unlikely(w->exposed))
3062 + send_SET(w->name, w->status_vmswap);
3063 }
3064 send_END();
3065
@@ -3090,22 +3164,22 @@ static void send_charts_updates_to_netdata(struct target *root, const char *type
3164 fprintf(stdout, "CHART %s.mem '' '%s Real Memory (w/o shared)' 'MB' mem %s.mem stacked 20003 %d\n", type, title, type, update_every);
3165 for (w = root; w ; w = w->next) {
3166 if(unlikely(w->exposed))
3093 - fprintf(stdout, "DIMENSION %s '' absolute %ld %ld\n", w->name, sysconf(_SC_PAGESIZE), 1024L*1024L);
3167 + fprintf(stdout, "DIMENSION %s '' absolute %zu %ld\n", w->name, pagesize, 1024L*1024L);
3168 }
3169
3096 - fprintf(stdout, "CHART %s.vmem '' '%s Virtual Memory Size' 'MB' mem %s.vmem stacked 20004 %d\n", type, title, type, update_every);
3170 + fprintf(stdout, "CHART %s.vmem '' '%s Virtual Memory Size' 'MB' mem %s.vmem stacked 20005 %d\n", type, title, type, update_every);
3171 for (w = root; w ; w = w->next) {
3172 if(unlikely(w->exposed))
3099 - fprintf(stdout, "DIMENSION %s '' absolute %ld %ld\n", w->name, sysconf(_SC_PAGESIZE), 1024L*1024L);
3173 + fprintf(stdout, "DIMENSION %s '' absolute %zu %ld\n", w->name, pagesize, 1024L*1024L);
3174 }
3175
3102 - fprintf(stdout, "CHART %s.threads '' '%s Threads' 'threads' processes %s.threads stacked 20005 %d\n", type, title, type, update_every);
3176 + fprintf(stdout, "CHART %s.threads '' '%s Threads' 'threads' processes %s.threads stacked 20006 %d\n", type, title, type, update_every);
3177 for (w = root; w ; w = w->next) {
3178 if(unlikely(w->exposed))
3179 fprintf(stdout, "DIMENSION %s '' absolute 1 1\n", w->name);
3180 }
3181
3108 - fprintf(stdout, "CHART %s.processes '' '%s Processes' 'processes' processes %s.processes stacked 20004 %d\n", type, title, type, update_every);
3182 + fprintf(stdout, "CHART %s.processes '' '%s Processes' 'processes' processes %s.processes stacked 20007 %d\n", type, title, type, update_every);
3183 for (w = root; w ; w = w->next) {
3184 if(unlikely(w->exposed))
3185 fprintf(stdout, "DIMENSION %s '' absolute 1 1\n", w->name);
@@ -3131,7 +3205,13 @@ static void send_charts_updates_to_netdata(struct target *root, const char *type
3205 }
3206 }
3207
3134 - 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);
3208 + fprintf(stdout, "CHART %s.swap '' '%s Swap Memory' 'MB' swap %s.swap stacked 20011 %d\n", type, title, type, update_every);
3209 + for (w = root; w ; w = w->next) {
3210 + if(unlikely(w->exposed))
3211 + fprintf(stdout, "DIMENSION %s '' absolute %zu %ld\n", w->name, pagesize, 1024L*1024L);
3212 + }
3213 +
3214 + 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);
3215 for (w = root; w ; w = w->next) {
3216 if(unlikely(w->exposed))
3217 fprintf(stdout, "DIMENSION %s '' absolute 1 %llu\n", w->name, RATES_DETAIL);
@@ -3422,6 +3502,9 @@ static int check_capabilities() {
3502 int main(int argc, char **argv) {
3503 // debug_flags = D_PROCFILE;
3504
3505 + pagesize = (size_t)sysconf(_SC_PAGESIZE);
3506 + kb_per_page = pagesize / 1024;
3507 +
3508 // set the name for logging
3509 program_name = "apps.plugin";
3510