@cryptotaxi247 / netdata-1 / commits / 169f03543

added systemd services charts, based on cgroups

Costa Tsaousis (ktsaou) committed Jan 15, 2017 at 15:14 UTC 169f035436e59644469ceb7cca02111878135524
3 files changed +161 -79
src/sys_fs_cgroup.c
+154 -78
@@ -8,10 +8,11 @@ static int cgroup_enable_cpuacct_usage = CONFIG_ONDEMAND_ONDEMAND;
8 static int cgroup_enable_memory = CONFIG_ONDEMAND_ONDEMAND;
9 static int cgroup_enable_devices = CONFIG_ONDEMAND_ONDEMAND;
10 static int cgroup_enable_blkio = CONFIG_ONDEMAND_ONDEMAND;
11 -static int cgroup_enable_systemd_services = CONFIG_ONDEMAND_NO;
11 +static int cgroup_enable_systemd_services = CONFIG_ONDEMAND_YES;
12 static int cgroup_enable_new_cgroups_detected_at_runtime = 1;
13 static int cgroup_check_for_new_every = 10;
14 static int cgroup_update_every = 1;
15 +
16 static char *cgroup_cpuacct_base = NULL;
17 static char *cgroup_blkio_base = NULL;
18 static char *cgroup_memory_base = NULL;
@@ -274,6 +275,7 @@ struct cgroup {
275 struct blkio io_merged; // operations
276 struct blkio io_queued; // operations
277
278 + // per cgroup charts
279 RRDSET *st_cpu;
280 RRDSET *st_cpu_per_core;
281 RRDSET *st_mem;
@@ -289,6 +291,10 @@ struct cgroup {
291 RRDSET *st_queued_ops;
292 RRDSET *st_merged_ops;
293
294 + // services
295 + RRDDIM *rd_cpu;
296 + RRDDIM *rd_mem_usage;
297 +
298 struct cgroup *next;
299
300 } *cgroup_root = NULL;
@@ -730,65 +736,24 @@ static char *cgroup_chart_id_strdupz(const char *s) {
736 void cgroup_get_chart_name(struct cgroup *cg) {
737 debug(D_CGROUP, "looking for the name of cgroup '%s' with chart id '%s' and title '%s'", cg->id, cg->chart_id, cg->chart_title);
738
733 - if(!netdata_simple_pattern_list_matches(disabled_cgroup_renames, cg->id) &&
734 - !netdata_simple_pattern_list_matches(disabled_cgroup_renames, cg->chart_id)) {
735 -
736 - pid_t cgroup_pid;
737 - char buffer[CGROUP_CHARTID_LINE_MAX + 1];
738 -
739 - snprintfz(buffer, CGROUP_CHARTID_LINE_MAX, "exec %s '%s'", cgroups_rename_script, cg->chart_id);
740 -
741 - debug(D_CGROUP, "executing command '%s' for cgroup '%s'", buffer, cg->id);
742 - FILE *fp = mypopen(buffer, &cgroup_pid);
743 - if(fp) {
744 - // debug(D_CGROUP, "reading from command '%s' for cgroup '%s'", buffer, cg->id);
745 - char *s = fgets(buffer, CGROUP_CHARTID_LINE_MAX, fp);
746 - // debug(D_CGROUP, "closing command for cgroup '%s'", cg->id);
747 - mypclose(fp, cgroup_pid);
748 - // debug(D_CGROUP, "closed command for cgroup '%s'", cg->id);
749 -
750 - if(s && *s && *s != '\n') {
751 - debug(D_CGROUP, "cgroup '%s' should be renamed to '%s'", cg->id, s);
739 + pid_t cgroup_pid;
740 + char buffer[CGROUP_CHARTID_LINE_MAX + 1];
741
753 - trim(s);
742 + snprintfz(buffer, CGROUP_CHARTID_LINE_MAX, "exec %s '%s'", cgroups_rename_script, cg->chart_id);
743
755 - freez(cg->chart_title);
756 - cg->chart_title = cgroup_title_strdupz(s);
744 + debug(D_CGROUP, "executing command '%s' for cgroup '%s'", buffer, cg->id);
745 + FILE *fp = mypopen(buffer, &cgroup_pid);
746 + if(fp) {
747 + // debug(D_CGROUP, "reading from command '%s' for cgroup '%s'", buffer, cg->id);
748 + char *s = fgets(buffer, CGROUP_CHARTID_LINE_MAX, fp);
749 + // debug(D_CGROUP, "closing command for cgroup '%s'", cg->id);
750 + mypclose(fp, cgroup_pid);
751 + // debug(D_CGROUP, "closed command for cgroup '%s'", cg->id);
752
758 - freez(cg->chart_id);
759 - cg->chart_id = cgroup_chart_id_strdupz(s);
760 - cg->hash_chart = simple_hash(cg->chart_id);
761 - }
762 - }
763 - else
764 - error("CGROUP: Cannot popen(\"%s\", \"r\").", buffer);
753 + if(s && *s && *s != '\n') {
754 + debug(D_CGROUP, "cgroup '%s' should be renamed to '%s'", cg->id, s);
755
766 - debug(D_CGROUP, "cgroup '%s' renamed to '%s' (title: '%s')", cg->id, cg->chart_id, cg->chart_title);
767 - }
768 - else
769 - debug(D_CGROUP, "cgroup '%s' will not be renamed - it matches the list of disabled cgroup renames (will be shown as '%s')", cg->id, cg->chart_id);
770 -
771 -
772 - if(cgroup_enable_systemd_services) {
773 - if(netdata_simple_pattern_list_matches(systemd_services_cgroups, cg->id) ||
774 - netdata_simple_pattern_list_matches(systemd_services_cgroups, cg->chart_id)) {
775 - debug(D_CGROUP, "cgroup '%s' with chart id '%s' (title: '%s') matches systemd services cgroups", cg->id, cg->chart_id, cg->chart_title);
776 -
777 - char buffer[CGROUP_CHARTID_LINE_MAX + 1];
778 - cg->options |= CGROUP_OPTIONS_SYSTEM_SLICE_SERVICE;
779 -
780 - strncpy(buffer, cg->id, CGROUP_CHARTID_LINE_MAX);
781 - char *s = buffer;
782 -
783 - // skip to the last slash
784 - size_t len = strlen(s);
785 - while(len--) if(unlikely(s[len] == '/')) break;
786 - if(len) s = &s[len + 1];
787 -
788 - // remove extension
789 - //len = strlen(s);
790 - //while(len--) if(unlikely(s[len] == '.')) break;
791 - //if(len) s[len] = '\0';
756 + trim(s);
757
758 freez(cg->chart_title);
759 cg->chart_title = cgroup_title_strdupz(s);
@@ -796,13 +761,10 @@ void cgroup_get_chart_name(struct cgroup *cg) {
761 freez(cg->chart_id);
762 cg->chart_id = cgroup_chart_id_strdupz(s);
763 cg->hash_chart = simple_hash(cg->chart_id);
799 - cg->enabled = 1;
800 -
801 - debug(D_CGROUP, "cgroup '%s' renamed to '%s' (title: '%s')", cg->id, cg->chart_id, cg->chart_title);
764 }
803 - else
804 - debug(D_CGROUP, "cgroup '%s' with chart id '%s' (title: '%s') does not match systemd services groups", cg->id, cg->chart_id, cg->chart_title);
765 }
766 + else
767 + error("CGROUP: Cannot popen(\"%s\", \"r\").", buffer);
768 }
769
770 struct cgroup *cgroup_add(const char *id) {
@@ -836,13 +798,65 @@ struct cgroup *cgroup_add(const char *id) {
798
799 cgroup_root_count++;
800
839 - // fix the name by calling the external script
840 - cgroup_get_chart_name(cg);
801 + // fix the chart_id and title by calling the external script
802 + if(!netdata_simple_pattern_list_matches(disabled_cgroup_renames, cg->id) &&
803 + !netdata_simple_pattern_list_matches(disabled_cgroup_renames, cg->chart_id)) {
804 +
805 + cgroup_get_chart_name(cg);
806 +
807 + debug(D_CGROUP, "cgroup '%s' renamed to '%s' (title: '%s')", cg->id, cg->chart_id, cg->chart_title);
808 + }
809 + else
810 + debug(D_CGROUP, "cgroup '%s' will not be renamed - it matches the list of disabled cgroup renames (will be shown as '%s')", cg->id, cg->chart_id);
811 +
812 + int user_configurable = 1;
813 +
814 + // check if this cgroup should be a systemd service
815 + if(cgroup_enable_systemd_services) {
816 + if(netdata_simple_pattern_list_matches(systemd_services_cgroups, cg->id) ||
817 + netdata_simple_pattern_list_matches(systemd_services_cgroups, cg->chart_id)) {
818 + debug(D_CGROUP, "cgroup '%s' with chart id '%s' (title: '%s') matches systemd services cgroups", cg->id, cg->chart_id, cg->chart_title);
819 +
820 + char buffer[CGROUP_CHARTID_LINE_MAX + 1];
821 + cg->options |= CGROUP_OPTIONS_SYSTEM_SLICE_SERVICE;
822 +
823 + strncpy(buffer, cg->id, CGROUP_CHARTID_LINE_MAX);
824 + char *s = buffer;
825 +
826 + //freez(cg->chart_id);
827 + //cg->chart_id = cgroup_chart_id_strdupz(s);
828 + //cg->hash_chart = simple_hash(cg->chart_id);
829 +
830 + // skip to the last slash
831 + size_t len = strlen(s);
832 + while(len--) if(unlikely(s[len] == '/')) break;
833 + if(len) s = &s[len + 1];
834
842 - char option[FILENAME_MAX + 1];
843 - snprintfz(option, FILENAME_MAX, "enable cgroup %s", cg->chart_title);
844 - cg->enabled = (char)config_get_boolean("plugin:cgroups", option, def);
835 + // remove extension
836 + len = strlen(s);
837 + while(len--) if(unlikely(s[len] == '.')) break;
838 + if(len) s[len] = '\0';
839
840 + freez(cg->chart_title);
841 + cg->chart_title = cgroup_title_strdupz(s);
842 +
843 + cg->enabled = 1;
844 + user_configurable = 0;
845 +
846 + debug(D_CGROUP, "cgroup '%s' renamed to '%s' (title: '%s')", cg->id, cg->chart_id, cg->chart_title);
847 + }
848 + else
849 + debug(D_CGROUP, "cgroup '%s' with chart id '%s' (title: '%s') does not match systemd services groups", cg->id, cg->chart_id, cg->chart_title);
850 + }
851 +
852 + if(user_configurable) {
853 + // allow the user to enable/disable this individualy
854 + char option[FILENAME_MAX + 1];
855 + snprintfz(option, FILENAME_MAX, "enable cgroup %s", cg->chart_title);
856 + cg->enabled = (char) config_get_boolean("plugin:cgroups", option, def);
857 + }
858 +
859 + // detect duplicate cgroups
860 if(cg->enabled) {
861 struct cgroup *t;
862 for (t = cgroup_root; t; t = t->next) {
@@ -1230,6 +1244,59 @@ void find_all_cgroups() {
1244
1245 #define CHART_TITLE_MAX 300
1246
1247 +void update_services_charts(int update_every, int do_cpu, int do_mem_usage) {
1248 + static RRDSET *st_cpu = NULL;
1249 + static RRDSET *st_mem_usage = NULL;
1250 +
1251 + // create the charts
1252 +
1253 + if(do_cpu) {
1254 + if(unlikely(!st_cpu)) {
1255 + char title[CHART_TITLE_MAX + 1];
1256 +
1257 + st_cpu = rrdset_find_bytype("services", "cpu");
1258 + if(!st_cpu) {
1259 + snprintfz(title, CHART_TITLE_MAX, "Systemd Services CPU utilization (%d%% = %d core%s)", (processors * 100), processors, (processors > 1) ? "s" : "");
1260 + st_cpu = rrdset_create("services", "cpu", NULL, "cpu", "services.cpu", title, "%", 30000, update_every, RRDSET_TYPE_STACKED);
1261 + }
1262 + }
1263 + else rrdset_next(st_cpu);
1264 + }
1265 +
1266 + if(do_mem_usage) {
1267 + if(unlikely(!st_mem_usage)) {
1268 + st_mem_usage = rrdset_find_bytype("services", "mem_usage");
1269 + if(!st_mem_usage)
1270 + st_mem_usage = rrdset_create("services", "mem_usage", NULL, "mem", "services.mem_usage", "Systemd Services RAM Usage", "MB", 30001, update_every, RRDSET_TYPE_STACKED);
1271 + }
1272 + else rrdset_next(st_mem_usage);
1273 + }
1274 +
1275 + // update the values
1276 + struct cgroup *cg;
1277 + for(cg = cgroup_root; cg ; cg = cg->next) {
1278 + if(!cg->available || !cg->enabled || !(cg->options & CGROUP_OPTIONS_SYSTEM_SLICE_SERVICE)) continue;
1279 +
1280 + if(do_cpu && cg->cpuacct_stat.updated) {
1281 + if(unlikely(!cg->rd_cpu))
1282 + cg->rd_cpu = rrddim_add(st_cpu, cg->chart_id, cg->chart_title, 100, hz, RRDDIM_INCREMENTAL);
1283 +
1284 + rrddim_set_by_pointer(st_cpu, cg->rd_cpu, cg->cpuacct_stat.user + cg->cpuacct_stat.system);
1285 + }
1286 +
1287 + if(do_mem_usage) {
1288 + if(unlikely(!cg->rd_mem_usage))
1289 + cg->rd_mem_usage = rrddim_add(st_mem_usage, cg->chart_id, cg->chart_title, 1, 1024 * 1024, RRDDIM_ABSOLUTE);
1290 +
1291 + rrddim_set_by_pointer(st_mem_usage, cg->rd_mem_usage, cg->memory.usage_in_bytes);
1292 + }
1293 + }
1294 +
1295 + // complete the iteration
1296 + if(do_cpu) rrdset_done(st_cpu);
1297 + if(do_mem_usage) rrdset_done(st_mem_usage);
1298 +}
1299 +
1300 static inline char *cgroup_chart_type(char *buffer, const char *id, size_t len) {
1301 if(buffer[0]) return buffer;
1302
@@ -1248,11 +1315,18 @@ void update_cgroup_charts(int update_every) {
1315 char type[RRD_ID_LENGTH_MAX + 1];
1316 char title[CHART_TITLE_MAX + 1];
1317
1251 - struct cgroup *cg;
1318 + int services_do_cpu = 0;
1319 + int services_do_mem_usage = 0;
1320
1321 + struct cgroup *cg;
1322 for(cg = cgroup_root; cg ; cg = cg->next) {
1254 - if(!cg->available || !cg->enabled || cg->options & CGROUP_OPTIONS_SYSTEM_SLICE_SERVICE)
1323 + if(!cg->available || !cg->enabled) continue;
1324 +
1325 + if(cgroup_enable_systemd_services && cg->options & CGROUP_OPTIONS_SYSTEM_SLICE_SERVICE) {
1326 + if(cg->cpuacct_stat.updated && (cg->cpuacct_stat.user || cg->cpuacct_stat.system)) services_do_cpu++;
1327 + if(cg->memory.usage_in_bytes_updated) services_do_mem_usage++;
1328 continue;
1329 + }
1330
1331 type[0] = '\0';
1332
@@ -1300,7 +1374,7 @@ void update_cgroup_charts(int update_every) {
1374 }
1375
1376 if(cg->memory.updated) {
1303 - if(cg->memory.cache + cg->memory.rss + cg->memory.rss_huge + cg->memory.mapped_file > 0) {
1377 + if(cg->memory.cache || cg->memory.rss || cg->memory.rss_huge || cg->memory.mapped_file) {
1378 if(unlikely(!cg->st_mem)) {
1379 cg->st_mem = rrdset_find_bytype(cgroup_chart_type(type, cg->chart_id, RRD_ID_LENGTH_MAX), "mem");
1380 if(!cg->st_mem) {
@@ -1344,7 +1418,7 @@ void update_cgroup_charts(int update_every) {
1418 rrddim_set(cg->st_writeback, "writeback", cg->memory.writeback);
1419 rrdset_done(cg->st_writeback);
1420
1347 - if(cg->memory.pgpgin + cg->memory.pgpgout > 0) {
1421 + if(cg->memory.pgpgin || cg->memory.pgpgout) {
1422 if(unlikely(!cg->st_mem_activity)) {
1423 cg->st_mem_activity = rrdset_find_bytype(cgroup_chart_type(type, cg->chart_id, RRD_ID_LENGTH_MAX), "mem_activity");
1424 if(!cg->st_mem_activity) {
@@ -1362,7 +1436,7 @@ void update_cgroup_charts(int update_every) {
1436 rrdset_done(cg->st_mem_activity);
1437 }
1438
1365 - if(cg->memory.pgfault + cg->memory.pgmajfault > 0) {
1439 + if(cg->memory.pgfault || cg->memory.pgmajfault) {
1440 if(unlikely(!cg->st_pgfaults)) {
1441 cg->st_pgfaults = rrdset_find_bytype(cgroup_chart_type(type, cg->chart_id, RRD_ID_LENGTH_MAX), "pgfaults");
1442 if(!cg->st_pgfaults) {
@@ -1399,7 +1473,7 @@ void update_cgroup_charts(int update_every) {
1473 rrdset_done(cg->st_mem_usage);
1474 }
1475
1402 - if(cg->memory.failcnt_updated && cg->memory.failcnt > 0) {
1476 + if(cg->memory.failcnt_updated && cg->memory.failcnt) {
1477 if(unlikely(!cg->st_mem_failcnt)) {
1478 cg->st_mem_failcnt = rrdset_find_bytype(cgroup_chart_type(type, cg->chart_id, RRD_ID_LENGTH_MAX), "mem_failcnt");
1479 if(!cg->st_mem_failcnt) {
@@ -1415,7 +1489,7 @@ void update_cgroup_charts(int update_every) {
1489 rrdset_done(cg->st_mem_failcnt);
1490 }
1491
1418 - if(cg->io_service_bytes.updated && cg->io_service_bytes.Read + cg->io_service_bytes.Write > 0) {
1492 + if(cg->io_service_bytes.updated && (cg->io_service_bytes.Read || cg->io_service_bytes.Write)) {
1493 if(unlikely(!cg->st_io)) {
1494 cg->st_io = rrdset_find_bytype(cgroup_chart_type(type, cg->chart_id, RRD_ID_LENGTH_MAX), "io");
1495 if(!cg->st_io) {
@@ -1433,7 +1507,7 @@ void update_cgroup_charts(int update_every) {
1507 rrdset_done(cg->st_io);
1508 }
1509
1436 - if(cg->io_serviced.updated && cg->io_serviced.Read + cg->io_serviced.Write > 0) {
1510 + if(cg->io_serviced.updated && (cg->io_serviced.Read || cg->io_serviced.Write)) {
1511 if(unlikely(!cg->st_serviced_ops)) {
1512 cg->st_serviced_ops = rrdset_find_bytype(cgroup_chart_type(type, cg->chart_id, RRD_ID_LENGTH_MAX), "serviced_ops");
1513 if(!cg->st_serviced_ops) {
@@ -1452,7 +1526,7 @@ void update_cgroup_charts(int update_every) {
1526 rrdset_done(cg->st_serviced_ops);
1527 }
1528
1455 - if(cg->throttle_io_service_bytes.updated && cg->throttle_io_service_bytes.Read + cg->throttle_io_service_bytes.Write > 0) {
1529 + if(cg->throttle_io_service_bytes.updated && (cg->throttle_io_service_bytes.Read || cg->throttle_io_service_bytes.Write)) {
1530 if(unlikely(!cg->st_throttle_io)) {
1531 cg->st_throttle_io = rrdset_find_bytype(cgroup_chart_type(type, cg->chart_id, RRD_ID_LENGTH_MAX), "throttle_io");
1532 if(!cg->st_throttle_io) {
@@ -1470,8 +1544,7 @@ void update_cgroup_charts(int update_every) {
1544 rrdset_done(cg->st_throttle_io);
1545 }
1546
1473 -
1474 - if(cg->throttle_io_serviced.updated && cg->throttle_io_serviced.Read + cg->throttle_io_serviced.Write > 0) {
1547 + if(cg->throttle_io_serviced.updated && (cg->throttle_io_serviced.Read || cg->throttle_io_serviced.Write)) {
1548 if(unlikely(!cg->st_throttle_serviced_ops)) {
1549 cg->st_throttle_serviced_ops = rrdset_find_bytype(cgroup_chart_type(type, cg->chart_id, RRD_ID_LENGTH_MAX), "throttle_serviced_ops");
1550 if(!cg->st_throttle_serviced_ops) {
@@ -1507,7 +1580,7 @@ void update_cgroup_charts(int update_every) {
1580 rrdset_done(cg->st_queued_ops);
1581 }
1582
1510 - if(cg->io_merged.updated && cg->io_merged.Read + cg->io_merged.Write > 0) {
1583 + if(cg->io_merged.updated && (cg->io_merged.Read || cg->io_merged.Write)) {
1584 if(unlikely(!cg->st_merged_ops)) {
1585 cg->st_merged_ops = rrdset_find_bytype(cgroup_chart_type(type, cg->chart_id, RRD_ID_LENGTH_MAX), "merged_ops");
1586 if(!cg->st_merged_ops) {
@@ -1527,6 +1600,9 @@ void update_cgroup_charts(int update_every) {
1600 }
1601
1602 debug(D_CGROUP, "done updating cgroups charts");
1603 +
1604 + if(cgroup_enable_systemd_services && services_do_cpu)
1605 + update_services_charts(update_every, services_do_cpu, services_do_mem_usage);
1606 }
1607
1608 // ----------------------------------------------------------------------------
web/dashboard_info.js
+6
@@ -11,6 +11,12 @@ netdataDashboard.menu = {
11 info: 'Overview of the key system metrics.'
12 },
13
14 + 'services': {
15 + title: 'Systemd Services',
16 + icon: '<i class="fa fa-cogs" aria-hidden="true"></i>',
17 + info: 'Resources utilization of systemd services.'
18 + },
19 +
20 'ap': {
21 title: 'Access Points',
22 icon: '<i class="fa fa-wifi" aria-hidden="true"></i>',
web/index.html
+1 -1
@@ -2632,7 +2632,7 @@
2632 });
2633
2634 NETDATA.requiredJs.push({
2635 - url: NETDATA.serverDefault + 'dashboard_info.js?v20161226-1',
2635 + url: NETDATA.serverDefault + 'dashboard_info.js?v20170115-1',
2636 async: false,
2637 isAlreadyLoaded: function() { return false; }
2638 });