@cryptotaxi247 / netdata-1 / commits / b1dfe19b4

cgroups are now on their own thread; cgroup names are controlled by plugins.d/cgroup-name.sh which uses /etc/netdata/cgroups-names.conf to pick up unique ID (chart names) for the containers

Costa Tsaousis (ktsaou) committed Apr 25, 2016 at 01:33 UTC b1dfe19b4f139a7e213d078dab8dd430040851b2
9 files changed +182 -47
plugins.d/Makefile.am
+1
@@ -8,6 +8,7 @@ dist_plugins_DATA = \
8 $(NULL)
9
10 dist_plugins_SCRIPTS = \
11 + cgroup-name.sh \
12 charts.d.dryrun-helper.sh \
13 charts.d.plugin \
14 node.d.plugin \
plugins.d/cgroup-name.sh new
+38
@@ -0,0 +1,38 @@
1 +#!/bin/bash
2 +
3 +export PATH="${PATH}:/sbin:/usr/sbin:/usr/local/sbin"
4 +
5 +NETDATA_CONFIG_DIR="${NETDATA_CONFIG_DIR-/etc/netdata}"
6 +CONFIG="${NETDATA_CONFIG_DIR}/cgroups-names.conf"
7 +CGROUP="${1}"
8 +NAME=
9 +
10 +if [ -z "${CGROUP}" ]
11 + then
12 + echo >&2 "${0}: called without a cgroup name. Nothing to do."
13 + exit 1
14 +fi
15 +
16 +if [ -f "${CONFIG}" ]
17 + then
18 + NAME="$(cat "${CONFIG}" | grep "^${CGROUP}" | cut -d ' ' -f 2)"
19 + if [ -z "${NAME}" ]
20 + then
21 + echo >&2 "${0}: cannot find cgroup '${CGROUP}' in '${CONFIG}'."
22 + fi
23 +else
24 + echo >&2 "${0}: configuration file '${CONFIG}' is not available."
25 +fi
26 +
27 +if [ -z "${NAME}" ]
28 + then
29 + if [ ${#CGROUP} -gt 12 ]
30 + then
31 + NAME="${CGROUP:0:12}"
32 + else
33 + NAME="${CGROUP}"
34 + fi
35 +fi
36 +
37 +echo >&2 "${0}: cgroup '${CGROUP}' is named as '${NAME}'"
38 +echo "${NAME}"
src/apps_plugin.c
+2 -8
@@ -2387,12 +2387,6 @@ void parse_args(int argc, char **argv)
2387 }
2388 }
2389
2390 -unsigned long long sutime() {
2391 - struct timeval now;
2392 - gettimeofday(&now, NULL);
2393 - return now.tv_sec * 1000000ULL + now.tv_usec;
2394 -}
2395 -
2390 int main(int argc, char **argv)
2391 {
2392 // debug_flags = D_PROCFILE;
@@ -2456,11 +2450,11 @@ int main(int argc, char **argv)
2450 for(;1; counter++) {
2451 #ifndef PROFILING_MODE
2452 // delay until it is our time to run
2459 - while((sunow = sutime()) < sunext)
2453 + while((sunow = timems()) < sunext)
2454 usleep((useconds_t)(sunext - sunow));
2455
2456 // find the next time we need to run
2463 - while(sutime() > sunext)
2457 + while(timems() > sunext)
2458 sunext += update_every * 1000000ULL;
2459 #endif /* PROFILING_MODE */
2460
src/common.c
+7
@@ -20,6 +20,13 @@
20 char *global_host_prefix = "";
21 int enable_ksm = 1;
22
23 +// time(NULL) in milliseconds
24 +unsigned long long timems(void) {
25 + struct timeval now;
26 + gettimeofday(&now, NULL);
27 + return now.tv_sec * 1000000ULL + now.tv_usec;
28 +}
29 +
30 unsigned char netdata_map_chart_names[256] = {
31 [0] = '\0', //
32 [1] = '_', //
src/common.h
+2
@@ -37,6 +37,8 @@ extern void get_HZ(void);
37
38 extern pid_t gettid(void);
39
40 +extern unsigned long long timems(void);
41 +
42 /* fix for alpine linux */
43 #ifndef RUSAGE_THREAD
44 #ifdef RUSAGE_CHILDREN
src/main.c
+3 -1
@@ -36,7 +36,8 @@
36 #include "plugin_nfacct.h"
37
38 #include "main.h"
39 -#include "../config.h"
39 +
40 +extern void *cgroups_main(void *ptr);
41
42 int netdata_exit = 0;
43
@@ -84,6 +85,7 @@ struct netdata_static_thread static_threads[] = {
85 {"tc", "plugins", "tc", 1, NULL, NULL, tc_main},
86 {"idlejitter", "plugins", "idlejitter", 1, NULL, NULL, cpuidlejitter_main},
87 {"proc", "plugins", "proc", 1, NULL, NULL, proc_main},
88 + {"cgroups", "plugins", "cgroups", 1, NULL, NULL, cgroups_main},
89
90 #ifdef INTERNAL_PLUGIN_NFACCT
91 // nfacct requires root access
src/plugin_proc.c
+19 -35
@@ -15,12 +15,6 @@
15 #include "plugin_proc.h"
16 #include "main.h"
17
18 -unsigned long long sutime() {
19 - struct timeval now;
20 - gettimeofday(&now, NULL);
21 - return now.tv_sec * 1000000ULL + now.tv_usec;
22 -}
23 -
18 void *proc_main(void *ptr)
19 {
20 if(ptr) { ; }
@@ -58,7 +52,6 @@ void *proc_main(void *ptr)
52 int vdo_proc_loadavg = !config_get_boolean("plugin:proc", "/proc/loadavg", 1);
53 int vdo_sys_kernel_mm_ksm = !config_get_boolean("plugin:proc", "/sys/kernel/mm/ksm", 1);
54 int vdo_cpu_netdata = !config_get_boolean("plugin:proc", "netdata server resources", 1);
61 - int vdo_sys_fs_cgroup = !config_get_boolean("plugin:proc", "cgroups", 1);
55
56 // keep track of the time each module was called
57 unsigned long long sutime_proc_net_dev = 0ULL;
@@ -78,7 +71,6 @@ void *proc_main(void *ptr)
71 unsigned long long sutime_proc_softirqs = 0ULL;
72 unsigned long long sutime_proc_loadavg = 0ULL;
73 unsigned long long sutime_sys_kernel_mm_ksm = 0ULL;
81 - unsigned long long sutime_sys_fs_cgroup = 0ULL;
74
75 // the next time we will run - aligned properly
76 unsigned long long sunext = (time(NULL) - (time(NULL) % rrd_update_every) + rrd_update_every) * 1000000ULL;
@@ -90,11 +82,11 @@ void *proc_main(void *ptr)
82 if(unlikely(netdata_exit)) break;
83
84 // delay until it is our time to run
93 - while((sunow = sutime()) < sunext)
85 + while((sunow = timems()) < sunext)
86 usleep((useconds_t)(sunext - sunow));
87
88 // find the next time we need to run
97 - while(sutime() > sunext)
89 + while(timems() > sunext)
90 sunext += rrd_update_every * 1000000ULL;
91
92 if(unlikely(netdata_exit)) break;
@@ -104,7 +96,7 @@ void *proc_main(void *ptr)
96 if(!vdo_sys_kernel_mm_ksm) {
97 debug(D_PROCNETDEV_LOOP, "PROCNETDEV: calling do_sys_kernel_mm_ksm().");
98
107 - sunow = sutime();
99 + sunow = timems();
100 vdo_sys_kernel_mm_ksm = do_sys_kernel_mm_ksm(rrd_update_every, (sutime_sys_kernel_mm_ksm > 0)?sunow - sutime_sys_kernel_mm_ksm:0ULL);
101 sutime_sys_kernel_mm_ksm = sunow;
102 }
@@ -112,7 +104,7 @@ void *proc_main(void *ptr)
104
105 if(!vdo_proc_loadavg) {
106 debug(D_PROCNETDEV_LOOP, "PROCNETDEV: calling do_proc_loadavg().");
115 - sunow = sutime();
107 + sunow = timems();
108 vdo_proc_loadavg = do_proc_loadavg(rrd_update_every, (sutime_proc_loadavg > 0)?sunow - sutime_proc_loadavg:0ULL);
109 sutime_proc_loadavg = sunow;
110 }
@@ -120,7 +112,7 @@ void *proc_main(void *ptr)
112
113 if(!vdo_proc_interrupts) {
114 debug(D_PROCNETDEV_LOOP, "PROCNETDEV: calling do_proc_interrupts().");
123 - sunow = sutime();
115 + sunow = timems();
116 vdo_proc_interrupts = do_proc_interrupts(rrd_update_every, (sutime_proc_interrupts > 0)?sunow - sutime_proc_interrupts:0ULL);
117 sutime_proc_interrupts = sunow;
118 }
@@ -128,7 +120,7 @@ void *proc_main(void *ptr)
120
121 if(!vdo_proc_softirqs) {
122 debug(D_PROCNETDEV_LOOP, "PROCNETDEV: calling do_proc_softirqs().");
131 - sunow = sutime();
123 + sunow = timems();
124 vdo_proc_softirqs = do_proc_softirqs(rrd_update_every, (sutime_proc_softirqs > 0)?sunow - sutime_proc_softirqs:0ULL);
125 sutime_proc_softirqs = sunow;
126 }
@@ -136,7 +128,7 @@ void *proc_main(void *ptr)
128
129 if(!vdo_proc_sys_kernel_random_entropy_avail) {
130 debug(D_PROCNETDEV_LOOP, "PROCNETDEV: calling do_proc_sys_kernel_random_entropy_avail().");
139 - sunow = sutime();
131 + sunow = timems();
132 vdo_proc_sys_kernel_random_entropy_avail = do_proc_sys_kernel_random_entropy_avail(rrd_update_every, (sutime_proc_sys_kernel_random_entropy_avail > 0)?sunow - sutime_proc_sys_kernel_random_entropy_avail:0ULL);
133 sutime_proc_sys_kernel_random_entropy_avail = sunow;
134 }
@@ -144,7 +136,7 @@ void *proc_main(void *ptr)
136
137 if(!vdo_proc_net_dev) {
138 debug(D_PROCNETDEV_LOOP, "PROCNETDEV: calling do_proc_net_dev().");
147 - sunow = sutime();
139 + sunow = timems();
140 vdo_proc_net_dev = do_proc_net_dev(rrd_update_every, (sutime_proc_net_dev > 0)?sunow - sutime_proc_net_dev:0ULL);
141 sutime_proc_net_dev = sunow;
142 }
@@ -152,7 +144,7 @@ void *proc_main(void *ptr)
144
145 if(!vdo_proc_diskstats) {
146 debug(D_PROCNETDEV_LOOP, "PROCNETDEV: calling do_proc_diskstats().");
155 - sunow = sutime();
147 + sunow = timems();
148 vdo_proc_diskstats = do_proc_diskstats(rrd_update_every, (sutime_proc_diskstats > 0)?sunow - sutime_proc_diskstats:0ULL);
149 sutime_proc_diskstats = sunow;
150 }
@@ -160,7 +152,7 @@ void *proc_main(void *ptr)
152
153 if(!vdo_proc_net_snmp) {
154 debug(D_PROCNETDEV_LOOP, "PROCNETDEV: calling do_proc_net_snmp().");
163 - sunow = sutime();
155 + sunow = timems();
156 vdo_proc_net_snmp = do_proc_net_snmp(rrd_update_every, (sutime_proc_net_snmp > 0)?sunow - sutime_proc_net_snmp:0ULL);
157 sutime_proc_net_snmp = sunow;
158 }
@@ -168,7 +160,7 @@ void *proc_main(void *ptr)
160
161 if(!vdo_proc_net_snmp6) {
162 debug(D_PROCNETDEV_LOOP, "PROCNETDEV: calling do_proc_net_snmp6().");
171 - sunow = sutime();
163 + sunow = timems();
164 vdo_proc_net_snmp6 = do_proc_net_snmp6(rrd_update_every, (sutime_proc_net_snmp6 > 0)?sunow - sutime_proc_net_snmp6:0ULL);
165 sutime_proc_net_snmp6 = sunow;
166 }
@@ -176,7 +168,7 @@ void *proc_main(void *ptr)
168
169 if(!vdo_proc_net_netstat) {
170 debug(D_PROCNETDEV_LOOP, "PROCNETDEV: calling do_proc_net_netstat().");
179 - sunow = sutime();
171 + sunow = timems();
172 vdo_proc_net_netstat = do_proc_net_netstat(rrd_update_every, (sutime_proc_net_netstat > 0)?sunow - sutime_proc_net_netstat:0ULL);
173 sutime_proc_net_netstat = sunow;
174 }
@@ -184,7 +176,7 @@ void *proc_main(void *ptr)
176
177 if(!vdo_proc_net_stat_conntrack) {
178 debug(D_PROCNETDEV_LOOP, "PROCNETDEV: calling do_proc_net_stat_conntrack().");
187 - sunow = sutime();
179 + sunow = timems();
180 vdo_proc_net_stat_conntrack = do_proc_net_stat_conntrack(rrd_update_every, (sutime_proc_net_stat_conntrack > 0)?sunow - sutime_proc_net_stat_conntrack:0ULL);
181 sutime_proc_net_stat_conntrack = sunow;
182 }
@@ -192,7 +184,7 @@ void *proc_main(void *ptr)
184
185 if(!vdo_proc_net_ip_vs_stats) {
186 debug(D_PROCNETDEV_LOOP, "PROCNETDEV: calling vdo_proc_net_ip_vs_stats().");
195 - sunow = sutime();
187 + sunow = timems();
188 vdo_proc_net_ip_vs_stats = do_proc_net_ip_vs_stats(rrd_update_every, (sutime_proc_net_ip_vs_stats > 0)?sunow - sutime_proc_net_ip_vs_stats:0ULL);
189 sutime_proc_net_ip_vs_stats = sunow;
190 }
@@ -200,7 +192,7 @@ void *proc_main(void *ptr)
192
193 if(!vdo_proc_net_stat_synproxy) {
194 debug(D_PROCNETDEV_LOOP, "PROCNETDEV: calling vdo_proc_net_stat_synproxy().");
203 - sunow = sutime();
195 + sunow = timems();
196 vdo_proc_net_stat_synproxy = do_proc_net_stat_synproxy(rrd_update_every, (sutime_proc_net_stat_synproxy > 0)?sunow - sutime_proc_net_stat_synproxy:0ULL);
197 sutime_proc_net_stat_synproxy = sunow;
198 }
@@ -208,7 +200,7 @@ void *proc_main(void *ptr)
200
201 if(!vdo_proc_stat) {
202 debug(D_PROCNETDEV_LOOP, "PROCNETDEV: calling do_proc_stat().");
211 - sunow = sutime();
203 + sunow = timems();
204 vdo_proc_stat = do_proc_stat(rrd_update_every, (sutime_proc_stat > 0)?sunow - sutime_proc_stat:0ULL);
205 sutime_proc_stat = sunow;
206 }
@@ -216,7 +208,7 @@ void *proc_main(void *ptr)
208
209 if(!vdo_proc_meminfo) {
210 debug(D_PROCNETDEV_LOOP, "PROCNETDEV: calling vdo_proc_meminfo().");
219 - sunow = sutime();
211 + sunow = timems();
212 vdo_proc_meminfo = do_proc_meminfo(rrd_update_every, (sutime_proc_meminfo > 0)?sunow - sutime_proc_meminfo:0ULL);
213 sutime_proc_meminfo = sunow;
214 }
@@ -224,7 +216,7 @@ void *proc_main(void *ptr)
216
217 if(!vdo_proc_vmstat) {
218 debug(D_PROCNETDEV_LOOP, "PROCNETDEV: calling vdo_proc_vmstat().");
227 - sunow = sutime();
219 + sunow = timems();
220 vdo_proc_vmstat = do_proc_vmstat(rrd_update_every, (sutime_proc_vmstat > 0)?sunow - sutime_proc_vmstat:0ULL);
221 sutime_proc_vmstat = sunow;
222 }
@@ -232,20 +224,12 @@ void *proc_main(void *ptr)
224
225 if(!vdo_proc_net_rpc_nfsd) {
226 debug(D_PROCNETDEV_LOOP, "PROCNETDEV: calling do_proc_net_rpc_nfsd().");
235 - sunow = sutime();
227 + sunow = timems();
228 vdo_proc_net_rpc_nfsd = do_proc_net_rpc_nfsd(rrd_update_every, (sutime_proc_net_rpc_nfsd > 0)?sunow - sutime_proc_net_rpc_nfsd:0ULL);
229 sutime_proc_net_rpc_nfsd = sunow;
230 }
231 if(unlikely(netdata_exit)) break;
232
241 - if(!vdo_sys_fs_cgroup) {
242 - debug(D_PROCNETDEV_LOOP, "PROCNETDEV: calling do_sys_fs_cgroup().");
243 - sunow = sutime();
244 - vdo_sys_fs_cgroup = do_sys_fs_cgroup(rrd_update_every, (sutime_sys_fs_cgroup > 0)?sunow - sutime_sys_fs_cgroup:0ULL);
245 - sutime_sys_fs_cgroup = sunow;
246 - }
247 - if(unlikely(netdata_exit)) break;
248 -
233 // END -- the job is done
234
235 // --------------------------------------------------------------------
src/plugin_proc.h
-1
@@ -20,6 +20,5 @@ extern int do_proc_softirqs(int update_every, unsigned long long dt);
20 extern int do_sys_kernel_mm_ksm(int update_every, unsigned long long dt);
21 extern int do_proc_loadavg(int update_every, unsigned long long dt);
22 extern int do_proc_net_stat_synproxy(int update_every, unsigned long long dt);
23 -extern int do_sys_fs_cgroup(int update_every, unsigned long long dt);
23
24 #endif /* NETDATA_PLUGIN_PROC_H */
src/sys_fs_cgroup.c
+110 -2
@@ -14,6 +14,8 @@
14 #include "procfile.h"
15 #include "log.h"
16 #include "rrd.h"
17 +#include "main.h"
18 +#include "popen.h"
19
20 // ----------------------------------------------------------------------------
21 // cgroup globals
@@ -545,6 +547,33 @@ void read_all_cgroups(struct cgroup *cg) {
547 // ----------------------------------------------------------------------------
548 // add/remove/find cgroup objects
549
550 +#define CGROUP_NAME_LINE_MAX 1024
551 +
552 +void cgroup_get_name(struct cgroup *cg) {
553 + pid_t cgroup_pid;
554 + char buffer[CGROUP_NAME_LINE_MAX + 1];
555 +
556 + snprintf(buffer, CGROUP_NAME_LINE_MAX, "exec %s '%s'",
557 + config_get("plugin:cgroups", "script to get cgroup names", PLUGINS_DIR "/cgroup-name.sh"), cg->name);
558 +
559 + FILE *fp = mypopen(buffer, &cgroup_pid);
560 + if(!fp) {
561 + error("CGROUP: Cannot popen(\"%s\", \"r\").", buffer);
562 + return;
563 + }
564 + char *s = fgets(buffer, CGROUP_NAME_LINE_MAX, fp);
565 + mypclose(fp, cgroup_pid);
566 +
567 + if(s && *s && *s != '\n') {
568 + trim(s);
569 + netdata_fix_chart_name(s);
570 + free(cg->name);
571 + cg->name = strdup(s);
572 + if(!cg->name)
573 + fatal("CGROUP: Cannot allocate memory for name cgroup %s name: '%s'", cg->id, s);
574 + }
575 +}
576 +
577 struct cgroup *cgroup_add(const char *id) {
578 if(cgroup_root_count >= cgroup_root_max) {
579 info("Maximum number of cgroups reached (%d). Not adding cgroup '%s'", cgroup_root_count, id);
@@ -595,6 +624,9 @@ struct cgroup *cgroup_add(const char *id) {
624 cgroup_root_count++;
625
626 // fprintf(stderr, " > added cgroup No %d, with id '%s' (%u) and name '%s'\n", cgroup_root_count, cg->id, cg->hash, cg->name);
627 +
628 + // fix the name by calling the external script
629 + cgroup_get_name(cg);
630 }
631 else fatal("Cannot allocate memory for cgroup '%s'", id);
632
@@ -808,9 +840,9 @@ void update_cgroup_charts(int update_every) {
840 if(cg->id[0] == '\0')
841 strcpy(type, "cgroup_host");
842 else if(cg->id[0] == '/')
811 - snprintf(type, RRD_ID_LENGTH_MAX, "cgroup%s", cg->id);
843 + snprintf(type, RRD_ID_LENGTH_MAX, "cgroup_%s", cg->name);
844 else
813 - snprintf(type, RRD_ID_LENGTH_MAX, "cgroup_%s", cg->id);
845 + snprintf(type, RRD_ID_LENGTH_MAX, "cgroup_%s", cg->name);
846
847 netdata_fix_chart_id(type);
848
@@ -1061,3 +1093,79 @@ int do_sys_fs_cgroup(int update_every, unsigned long long dt) {
1093
1094 return 0;
1095 }
1096 +
1097 +void *cgroups_main(void *ptr)
1098 +{
1099 + if(ptr) { ; }
1100 +
1101 + info("CGROUP Plugin thread created with task id %d", gettid());
1102 +
1103 + if(pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, NULL) != 0)
1104 + error("Cannot set pthread cancel type to DEFERRED.");
1105 +
1106 + if(pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL) != 0)
1107 + error("Cannot set pthread cancel state to ENABLE.");
1108 +
1109 + struct rusage thread;
1110 +
1111 + // when ZERO, attempt to do it
1112 + int vdo_sys_fs_cgroup = 0;
1113 + int vdo_cpu_netdata = !config_get_boolean("plugin:cgroups", "netdata server resources", 1);
1114 +
1115 + // keep track of the time each module was called
1116 + unsigned long long sutime_sys_fs_cgroup = 0ULL;
1117 +
1118 + // the next time we will run - aligned properly
1119 + unsigned long long sunext = (time(NULL) - (time(NULL) % rrd_update_every) + rrd_update_every) * 1000000ULL;
1120 + unsigned long long sunow;
1121 +
1122 + RRDSET *stcpu_thread = NULL;
1123 +
1124 + for(;1;) {
1125 + if(unlikely(netdata_exit)) break;
1126 +
1127 + // delay until it is our time to run
1128 + while((sunow = timems()) < sunext)
1129 + usleep((useconds_t)(sunext - sunow));
1130 +
1131 + // find the next time we need to run
1132 + while(timems() > sunext)
1133 + sunext += rrd_update_every * 1000000ULL;
1134 +
1135 + if(unlikely(netdata_exit)) break;
1136 +
1137 + // BEGIN -- the job to be done
1138 +
1139 + if(!vdo_sys_fs_cgroup) {
1140 + debug(D_PROCNETDEV_LOOP, "PROCNETDEV: calling do_sys_fs_cgroup().");
1141 + sunow = timems();
1142 + vdo_sys_fs_cgroup = do_sys_fs_cgroup(rrd_update_every, (sutime_sys_fs_cgroup > 0)?sunow - sutime_sys_fs_cgroup:0ULL);
1143 + sutime_sys_fs_cgroup = sunow;
1144 + }
1145 + if(unlikely(netdata_exit)) break;
1146 +
1147 + // END -- the job is done
1148 +
1149 + // --------------------------------------------------------------------
1150 +
1151 + if(!vdo_cpu_netdata) {
1152 + getrusage(RUSAGE_THREAD, &thread);
1153 +
1154 + if(!stcpu_thread) stcpu_thread = rrdset_find("netdata.plugin_cgroups_cpu");
1155 + if(!stcpu_thread) {
1156 + stcpu_thread = rrdset_create("netdata", "plugin_cgroups_cpu", NULL, "proc.internal", NULL, "NetData CGroups Plugin CPU usage", "milliseconds/s", 131000, rrd_update_every, RRDSET_TYPE_STACKED);
1157 +
1158 + rrddim_add(stcpu_thread, "user", NULL, 1, 1000, RRDDIM_INCREMENTAL);
1159 + rrddim_add(stcpu_thread, "system", NULL, 1, 1000, RRDDIM_INCREMENTAL);
1160 + }
1161 + else rrdset_next(stcpu_thread);
1162 +
1163 + rrddim_set(stcpu_thread, "user" , thread.ru_utime.tv_sec * 1000000ULL + thread.ru_utime.tv_usec);
1164 + rrddim_set(stcpu_thread, "system", thread.ru_stime.tv_sec * 1000000ULL + thread.ru_stime.tv_usec);
1165 + rrdset_done(stcpu_thread);
1166 + }
1167 + }
1168 +
1169 + pthread_exit(NULL);
1170 + return NULL;
1171 +}