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