@cryptotaxi247 / netdata-1 / commits / aca22d233

collect systemd service cgroups

Costa Tsaousis (ktsaou) committed Jan 15, 2017 at 01:49 UTC aca22d23303a934afa417a5a6d030fa256319b0a
2 files changed +366 -267
src/common.c
+16 -15
@@ -1199,7 +1199,7 @@ struct simple_pattern {
1199 };
1200
1201 NETDATA_SIMPLE_PATTERN *netdata_simple_pattern_list_create(const char *list, NETDATA_SIMPLE_PREFIX_MODE default_mode) {
1202 - struct simple_pattern *root = NULL;
1202 + struct simple_pattern *root = NULL, *last = NULL;
1203
1204 if(unlikely(!list || !*list)) return root;
1205
@@ -1237,36 +1237,37 @@ NETDATA_SIMPLE_PATTERN *netdata_simple_pattern_list_create(const char *list, NET
1237 if(len >= 2 && *s == '*' && s[len - 1] == '*') {
1238 s[len - 1] = '\0';
1239 s++;
1240 - len -= 2;
1240 mode = NETDATA_SIMPLE_PATTERN_MODE_SUBSTRING;
1241 }
1242 else if(len >= 1 && *s == '*') {
1243 s++;
1245 - len--;
1244 mode = NETDATA_SIMPLE_PATTERN_MODE_SUFFIX;
1245 }
1246 else if(len >= 1 && s[len - 1] == '*') {
1247 s[len - 1] = '\0';
1250 - len--;
1248 mode = NETDATA_SIMPLE_PATTERN_MODE_PREFIX;
1249 }
1250 else
1251 mode = default_mode;
1252
1256 - if(len) {
1257 - if(*s == '*')
1258 - error("simple pattern '%s' includes '%s' that is invalid", a, s);
1259 -
1260 - // allocate the structure
1261 - struct simple_pattern *m = mallocz(sizeof(struct simple_pattern));
1253 + // allocate the structure
1254 + struct simple_pattern *m = callocz(1, sizeof(struct simple_pattern));
1255 + if(*s) {
1256 m->match = strdup(s);
1257 m->len = strlen(m->match);
1258 m->mode = mode;
1265 - m->next = root;
1266 - root = m;
1259 }
1268 - else
1269 - error("simple pattern '%s' includes invalid matches", a);
1260 + else {
1261 + m->mode = NETDATA_SIMPLE_PATTERN_MODE_SUBSTRING;
1262 + }
1263 +
1264 + // link it at the end
1265 + if(unlikely(!root))
1266 + root = last = m;
1267 + else {
1268 + last->next = m;
1269 + last = m;
1270 + }
1271
1272 // prepare for next loop
1273 s = n;
@@ -1287,7 +1288,7 @@ int netdata_simple_pattern_list_matches(NETDATA_SIMPLE_PATTERN *list, const char
1288 if(m->len <= len) {
1289 switch(m->mode) {
1290 case NETDATA_SIMPLE_PATTERN_MODE_SUBSTRING:
1290 - if(unlikely(strstr(str, m->match)))
1291 + if(unlikely(!m->len || strstr(str, m->match)))
1292 return 1;
1293 break;
1294
src/sys_fs_cgroup.c
+350 -252
@@ -21,6 +21,10 @@ static int cgroup_max_depth = 0;
21
22 static NETDATA_SIMPLE_PATTERN *disabled_cgroups_patterns = NULL;
23 static NETDATA_SIMPLE_PATTERN *disabled_cgroup_paths = NULL;
24 +static NETDATA_SIMPLE_PATTERN *disabled_cgroup_renames = NULL;
25 +static NETDATA_SIMPLE_PATTERN *systemd_services_cgroups = NULL;
26 +
27 +static char *cgroups_rename_script = PLUGINS_DIR "/cgroup-name.sh";
28
29 void read_cgroup_plugin_configuration() {
30 cgroup_check_for_new_every = (int)config_get_number("plugin:cgroups", "check for new cgroups every", cgroup_check_for_new_every);
@@ -80,27 +84,46 @@ void read_cgroup_plugin_configuration() {
84
85 disabled_cgroups_patterns = netdata_simple_pattern_list_create(
86 config_get("plugin:cgroups", "disable by default cgroups matching",
83 - " lxc docker libvirt qemu systemd "
84 - " system system.slice "
85 - " machine machine.slice "
86 - " user user.slice "
87 - " init.scope "
87 + " / /lxc /docker /libvirt /qemu /systemd "
88 + " /system /system.slice "
89 + " /machine /machine.slice "
90 + " /user /user.slice "
91 + " /init.scope "
92 " *.swap "
93 " *.slice "
94 " *.user "
95 " *.mount "
96 " *.partition "
93 - " */ns " // lxc/*/ns #1397
97 + " */ns " // /lxc/*/ns #1397
98 ), NETDATA_SIMPLE_PATTERN_MODE_EXACT);
99
100 disabled_cgroup_paths = netdata_simple_pattern_list_create(
97 - config_get("plugin:cgroups", "disable by default cgroup paths matching",
98 - " system "
99 - " systemd "
100 - " user.slice "
101 - " user "
102 - " init.scope "
103 - " *-qemu "
101 + config_get("plugin:cgroups", "do not search for cgroups in paths matching",
102 + " /system "
103 + " /systemd "
104 + " /user.slice "
105 + " /user "
106 + " /init.scope "
107 + " *-qemu " // #345
108 + ), NETDATA_SIMPLE_PATTERN_MODE_EXACT);
109 +
110 + cgroups_rename_script = config_get("plugin:cgroups", "script to get cgroup names", cgroups_rename_script);
111 +
112 + disabled_cgroup_renames = netdata_simple_pattern_list_create(
113 + config_get("plugin:cgroups", "do not run script to rename cgroups matching",
114 + " / "
115 + " *.service "
116 + " *.slice "
117 + " *.scope "
118 + " *.swap "
119 + " *.mount "
120 + " *.partition "
121 + " *.user "
122 + ), NETDATA_SIMPLE_PATTERN_MODE_EXACT);
123 +
124 + systemd_services_cgroups = netdata_simple_pattern_list_create(
125 + config_get("plugin:cgroups", "cgroups to match as systemd services",
126 + " *.service "
127 ), NETDATA_SIMPLE_PATTERN_MODE_EXACT);
128
129 mountinfo_free(root);
@@ -200,8 +223,8 @@ struct cpuacct_usage {
223 unsigned long long *cpu_percpu;
224 };
225
203 -#define CGROUP_OPTIONS_DISABLED_DUPLICATE 0x00000001
204 -#define CGROUP_OPTIONS_PART_OF_GROUP 0x00000002
226 +#define CGROUP_OPTIONS_DISABLED_DUPLICATE 0x00000001
227 +#define CGROUP_OPTIONS_SYSTEM_SLICE_SERVICE 0x00000002
228
229 struct cgroup {
230 uint32_t options;
@@ -231,6 +254,21 @@ struct cgroup {
254 struct blkio io_merged; // operations
255 struct blkio io_queued; // operations
256
257 + RRDSET *st_cpu;
258 + RRDSET *st_cpu_per_core;
259 + RRDSET *st_mem;
260 + RRDSET *st_writeback;
261 + RRDSET *st_mem_activity;
262 + RRDSET *st_pgfaults;
263 + RRDSET *st_mem_usage;
264 + RRDSET *st_mem_failcnt;
265 + RRDSET *st_io;
266 + RRDSET *st_serviced_ops;
267 + RRDSET *st_throttle_io;
268 + RRDSET *st_throttle_serviced_ops;
269 + RRDSET *st_queued_ops;
270 + RRDSET *st_merged_ops;
271 +
272 struct cgroup *next;
273
274 } *cgroup_root = NULL;
@@ -647,80 +685,122 @@ void read_all_cgroups(struct cgroup *root) {
685
686 #define CGROUP_CHARTID_LINE_MAX 1024
687
650 -void cgroup_get_chart_id(struct cgroup *cg) {
651 - debug(D_CGROUP, "getting the name of cgroup '%s'", cg->id);
688 +static char *cgroup_title_strdupz(const char *s) {
689 + if(!s || !*s) s = "/";
690 +
691 + if(*s == '/' && s[1] != '\0') s++;
692 +
693 + char *r = strdupz(s);
694 + netdata_fix_chart_name(r);
695 +
696 + return r;
697 +}
698 +
699 +static char *cgroup_chart_id_strdupz(const char *s) {
700 + if(!s || !*s) s = "/";
701 +
702 + if(*s == '/' && s[1] != '\0') s++;
703 +
704 + char *r = strdupz(s);
705 + netdata_fix_chart_id(r);
706
653 - pid_t cgroup_pid;
654 - char buffer[CGROUP_CHARTID_LINE_MAX + 1];
707 + return r;
708 +}
709 +
710 +void cgroup_get_chart_name(struct cgroup *cg) {
711 + 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);
712 +
713 + if(!netdata_simple_pattern_list_matches(disabled_cgroup_renames, cg->id) &&
714 + !netdata_simple_pattern_list_matches(disabled_cgroup_renames, cg->chart_id)) {
715 +
716 + pid_t cgroup_pid;
717 + char buffer[CGROUP_CHARTID_LINE_MAX + 1];
718 +
719 + snprintfz(buffer, CGROUP_CHARTID_LINE_MAX, "exec %s '%s'", cgroups_rename_script, cg->chart_id);
720
656 - snprintfz(buffer, CGROUP_CHARTID_LINE_MAX, "exec %s '%s'",
657 - config_get("plugin:cgroups", "script to get cgroup names", PLUGINS_DIR "/cgroup-name.sh"), cg->chart_id);
721 + debug(D_CGROUP, "executing command '%s' for cgroup '%s'", buffer, cg->id);
722 + FILE *fp = mypopen(buffer, &cgroup_pid);
723 + if(fp) {
724 + // debug(D_CGROUP, "reading from command '%s' for cgroup '%s'", buffer, cg->id);
725 + char *s = fgets(buffer, CGROUP_CHARTID_LINE_MAX, fp);
726 + // debug(D_CGROUP, "closing command for cgroup '%s'", cg->id);
727 + mypclose(fp, cgroup_pid);
728 + // debug(D_CGROUP, "closed command for cgroup '%s'", cg->id);
729
659 - debug(D_CGROUP, "executing command '%s' for cgroup '%s'", buffer, cg->id);
660 - FILE *fp = mypopen(buffer, &cgroup_pid);
661 - if(!fp) {
662 - error("CGROUP: Cannot popen(\"%s\", \"r\").", buffer);
663 - return;
730 + if(s && *s && *s != '\n') {
731 + debug(D_CGROUP, "cgroup '%s' should be renamed to '%s'", cg->id, s);
732 +
733 + trim(s);
734 +
735 + freez(cg->chart_title);
736 + cg->chart_title = cgroup_title_strdupz(s);
737 +
738 + freez(cg->chart_id);
739 + cg->chart_id = cgroup_chart_id_strdupz(s);
740 + cg->hash_chart = simple_hash(cg->chart_id);
741 + }
742 + }
743 + else
744 + error("CGROUP: Cannot popen(\"%s\", \"r\").", buffer);
745 +
746 + debug(D_CGROUP, "cgroup '%s' renamed to '%s' (title: '%s')", cg->id, cg->chart_id, cg->chart_title);
747 }
665 - debug(D_CGROUP, "reading from command '%s' for cgroup '%s'", buffer, cg->id);
666 - char *s = fgets(buffer, CGROUP_CHARTID_LINE_MAX, fp);
667 - debug(D_CGROUP, "closing command for cgroup '%s'", cg->id);
668 - mypclose(fp, cgroup_pid);
669 - debug(D_CGROUP, "closed command for cgroup '%s'", cg->id);
748 + else
749 + 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);
750 +
751 +
752 + if(netdata_simple_pattern_list_matches(systemd_services_cgroups, cg->id) ||
753 + netdata_simple_pattern_list_matches(systemd_services_cgroups, cg->chart_id)) {
754 + debug(D_CGROUP, "cgroup '%s' with chart id '%s' (title: '%s') matches systemd services cgroups", cg->id, cg->chart_id, cg->chart_title);
755
671 - if(s && *s && *s != '\n') {
672 - debug(D_CGROUP, "cgroup '%s' should be renamed to '%s'", cg->id, s);
756 + char buffer[CGROUP_CHARTID_LINE_MAX + 1];
757 + cg->options |= CGROUP_OPTIONS_SYSTEM_SLICE_SERVICE;
758
674 - trim(s);
759 + strncpy(buffer, cg->id, CGROUP_CHARTID_LINE_MAX);
760 + char *s = buffer;
761 +
762 + // skip to the last slash
763 + size_t len = strlen(s);
764 + while(len--) if(unlikely(s[len] == '/')) break;
765 + if(len) s = &s[len+1];
766 +
767 + // remove extension
768 + //len = strlen(s);
769 + //while(len--) if(unlikely(s[len] == '.')) break;
770 + //if(len) s[len] = '\0';
771
772 freez(cg->chart_title);
677 - cg->chart_title = strdupz(s);
678 - netdata_fix_chart_name(cg->chart_title);
773 + cg->chart_title = cgroup_title_strdupz(s);
774
775 freez(cg->chart_id);
681 - cg->chart_id = strdupz(s);
682 - netdata_fix_chart_id(cg->chart_id);
776 + cg->chart_id = cgroup_chart_id_strdupz(s);
777 cg->hash_chart = simple_hash(cg->chart_id);
778
779 debug(D_CGROUP, "cgroup '%s' renamed to '%s' (title: '%s')", cg->id, cg->chart_id, cg->chart_title);
780 }
687 - else debug(D_CGROUP, "cgroup '%s' is not to be renamed (will be shown as '%s')", cg->id, cg->chart_id);
781 + else
782 + 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);
783 }
784
785 struct cgroup *cgroup_add(const char *id) {
691 - debug(D_CGROUP, "adding cgroup with id '%s'", id);
786 + if(!id || !*id) id = "/";
787 + debug(D_CGROUP, "adding to list, cgroup with id '%s'", id);
788
789 if(cgroup_root_count >= cgroup_root_max) {
790 info("Maximum number of cgroups reached (%d). Not adding cgroup '%s'", cgroup_root_count, id);
791 return NULL;
792 }
793
698 - int def = cgroup_enable_new_cgroups_detected_at_runtime;
699 - const char *chart_id = id;
700 - if(!*chart_id) {
701 - chart_id = "/";
702 -
703 - // disable by default the root cgroup
704 - def = 0;
705 - }
706 - else {
707 - if(*chart_id == '/') chart_id++;
708 - if(netdata_simple_pattern_list_matches(disabled_cgroups_patterns, chart_id))
709 - def = 0;
710 - }
711 -
712 - debug(D_CGROUP, "cgroup with id '%s' (chart_id '%s') is (by default) %s", id, chart_id, (def)?"enabled":"disabled");
713 -
794 + int def = netdata_simple_pattern_list_matches(disabled_cgroups_patterns, id)?0:cgroup_enable_new_cgroups_detected_at_runtime;
795 struct cgroup *cg = callocz(1, sizeof(struct cgroup));
796
797 cg->id = strdupz(id);
798 cg->hash = simple_hash(cg->id);
799
719 - cg->chart_id = strdupz(chart_id);
720 - netdata_fix_chart_id(cg->chart_id);
721 - cg->hash_chart = simple_hash(cg->chart_id);
800 + cg->chart_title = cgroup_title_strdupz(id);
801
723 - cg->chart_title = strdupz(chart_id);
802 + cg->chart_id = cgroup_chart_id_strdupz(id);
803 + cg->hash_chart = simple_hash(cg->chart_id);
804
805 if(!cgroup_root)
806 cgroup_root = cg;
@@ -734,9 +814,7 @@ struct cgroup *cgroup_add(const char *id) {
814 cgroup_root_count++;
815
816 // fix the name by calling the external script
737 - cgroup_get_chart_id(cg);
738 -
739 - debug(D_CGROUP, "adding cgroup '%s' ('%s') with chart id '%s' ('%s')", cg->id, id, cg->chart_id, chart_id);
817 + cgroup_get_chart_name(cg);
818
819 char option[FILENAME_MAX + 1];
820 snprintfz(option, FILENAME_MAX, "enable cgroup %s", cg->chart_title);
@@ -768,7 +846,7 @@ struct cgroup *cgroup_add(const char *id) {
846 }
847 }
848
771 - debug(D_CGROUP, "Added cgroup '%s' with chart id '%s' and title '%s' as %s (default was %s)", cg->id, cg->chart_id, cg->chart_title, (cg->enabled)?"enabled":"disabled", (def)?"enabled":"disabled");
849 + debug(D_CGROUP, "ADDED CGROUP: '%s' with chart id '%s' and title '%s' as %s (default was %s)", cg->id, cg->chart_id, cg->chart_title, (cg->enabled)?"enabled":"disabled", (def)?"enabled":"disabled");
850
851 return cg;
852 }
@@ -816,7 +894,7 @@ struct cgroup *cgroup_find(const char *id) {
894 break;
895 }
896
819 - debug(D_CGROUP, "cgroup_find('%s') %s", id, (cg)?"found":"not found");
897 + debug(D_CGROUP, "cgroup '%s' %s in memory", id, (cg)?"found":"not found");
898 return cg;
899 }
900
@@ -842,7 +920,7 @@ void found_subdir_in_dir(const char *dir) {
920 return;
921 }
922 }
845 - debug(D_CGROUP, "will add dir '%s' as cgroup", dir);
923 + // debug(D_CGROUP, "will add dir '%s' as cgroup", dir);
924 cg = cgroup_add(dir);
925 }
926
@@ -850,13 +928,16 @@ void found_subdir_in_dir(const char *dir) {
928 }
929
930 int find_dir_in_subdirs(const char *base, const char *this, void (*callback)(const char *)) {
853 - debug(D_CGROUP, "searching for directories in '%s'", base);
931 + if(!this) this = base;
932 + debug(D_CGROUP, "searching for directories in '%s' (base '%s')", this?this:"", base);
933 +
934 + size_t dirlen = strlen(this), baselen = strlen(base);
935
936 int ret = -1;
937 int enabled = -1;
857 - if(!this) this = base;
858 - size_t dirlen = strlen(this), baselen = strlen(base);
938 +
939 const char *relative_path = &this[baselen];
940 + if(!*relative_path) relative_path = "/";
941
942 DIR *dir = opendir(this);
943 if(!dir) {
@@ -876,16 +957,12 @@ int find_dir_in_subdirs(const char *base, const char *this, void (*callback)(con
957 ))
958 continue;
959
879 - debug(D_CGROUP, "examining '%s/%s'", this, de->d_name);
880 -
960 if(de->d_type == DT_DIR) {
961 if(enabled == -1) {
962 const char *r = relative_path;
963 if(*r == '\0') r = "/";
885 - else if (*r == '/') r++;
964
965 // do not decent in directories we are not interested
888 - // https://github.com/firehol/netdata/issues/345
966 int def = 1;
967 if(netdata_simple_pattern_list_matches(disabled_cgroup_paths, r))
968 def = 0;
@@ -1130,6 +1207,18 @@ void find_all_cgroups() {
1207
1208 #define CHART_TITLE_MAX 300
1209
1210 +static inline char *cgroup_chart_type(char *buffer, const char *id, size_t len) {
1211 + if(buffer[0]) return buffer;
1212 +
1213 + if(id[0] == '\0' || (id[0] == '/' && id[1] == '\0'))
1214 + strncpy(buffer, "cgroup_root", len);
1215 + else
1216 + snprintfz(buffer, len, "cgroup_%s", id);
1217 +
1218 + netdata_fix_chart_id(buffer);
1219 + return buffer;
1220 +}
1221 +
1222 void update_cgroup_charts(int update_every) {
1223 debug(D_CGROUP, "updating cgroups charts");
1224
@@ -1137,271 +1226,280 @@ void update_cgroup_charts(int update_every) {
1226 char title[CHART_TITLE_MAX + 1];
1227
1228 struct cgroup *cg;
1140 - RRDSET *st;
1229
1230 for(cg = cgroup_root; cg ; cg = cg->next) {
1143 - if(!cg->available || !cg->enabled || cg->options & CGROUP_OPTIONS_PART_OF_GROUP)
1231 + if(!cg->available || !cg->enabled || cg->options & CGROUP_OPTIONS_SYSTEM_SLICE_SERVICE)
1232 continue;
1233
1146 - if(cg->id[0] == '\0')
1147 - strcpy(type, "cgroup_root");
1148 - //else if(cg->id[0] == '/')
1149 - // snprintfz(type, RRD_ID_LENGTH_MAX, "cgroup_%s", cg->chart_id);
1150 - else
1151 - snprintfz(type, RRD_ID_LENGTH_MAX, "cgroup_%s", cg->chart_id);
1152 -
1153 - netdata_fix_chart_id(type);
1234 + type[0] = '\0';
1235
1236 if(cg->cpuacct_stat.updated) {
1156 - st = rrdset_find_bytype(type, "cpu");
1157 - if(!st) {
1158 - snprintfz(title, CHART_TITLE_MAX, "CPU Usage (%d%% = %d core%s) for cgroup %s", (processors * 100), processors, (processors>1)?"s":"", cg->chart_title);
1159 - st = rrdset_create(type, "cpu", NULL, "cpu", "cgroup.cpu", title, "%", 40000, update_every, RRDSET_TYPE_STACKED);
1160 -
1161 - rrddim_add(st, "user", NULL, 100, hz, RRDDIM_INCREMENTAL);
1162 - rrddim_add(st, "system", NULL, 100, hz, RRDDIM_INCREMENTAL);
1237 + if(unlikely(!cg->st_cpu)) {
1238 + cg->st_cpu = rrdset_find_bytype(cgroup_chart_type(type, cg->id, RRD_ID_LENGTH_MAX), "cpu");
1239 + if(!cg->st_cpu) {
1240 + snprintfz(title, CHART_TITLE_MAX, "CPU Usage (%d%% = %d core%s) for cgroup %s", (processors * 100), processors, (processors > 1) ? "s" : "", cg->chart_title);
1241 + cg->st_cpu = rrdset_create(type, "cpu", NULL, "cpu", "cgroup.cpu", title, "%", 40000, update_every, RRDSET_TYPE_STACKED);
1242 +
1243 + rrddim_add(cg->st_cpu, "user", NULL, 100, hz, RRDDIM_INCREMENTAL);
1244 + rrddim_add(cg->st_cpu, "system", NULL, 100, hz, RRDDIM_INCREMENTAL);
1245 + }
1246 }
1164 - else rrdset_next(st);
1247 + else rrdset_next(cg->st_cpu);
1248
1166 - rrddim_set(st, "user", cg->cpuacct_stat.user);
1167 - rrddim_set(st, "system", cg->cpuacct_stat.system);
1168 - rrdset_done(st);
1249 + rrddim_set(cg->st_cpu, "user", cg->cpuacct_stat.user);
1250 + rrddim_set(cg->st_cpu, "system", cg->cpuacct_stat.system);
1251 + rrdset_done(cg->st_cpu);
1252 }
1253
1254 if(cg->cpuacct_usage.updated) {
1255 char id[RRD_ID_LENGTH_MAX + 1];
1256 unsigned int i;
1257
1175 - st = rrdset_find_bytype(type, "cpu_per_core");
1176 - if(!st) {
1177 - snprintfz(title, CHART_TITLE_MAX, "CPU Usage (%d%% = %d core%s) Per Core for cgroup %s", (processors * 100), processors, (processors>1)?"s":"", cg->chart_title);
1178 - st = rrdset_create(type, "cpu_per_core", NULL, "cpu", "cgroup.cpu_per_core", title, "%", 40100, update_every, RRDSET_TYPE_STACKED);
1258 + if(unlikely(!cg->st_cpu_per_core)) {
1259 + cg->st_cpu_per_core = rrdset_find_bytype(cgroup_chart_type(type, cg->id, RRD_ID_LENGTH_MAX), "cpu_per_core");
1260 + if(!cg->st_cpu_per_core) {
1261 + snprintfz(title, CHART_TITLE_MAX, "CPU Usage (%d%% = %d core%s) Per Core for cgroup %s", (processors * 100), processors, (processors > 1) ? "s" : "", cg->chart_title);
1262 + cg->st_cpu_per_core = rrdset_create(type, "cpu_per_core", NULL, "cpu", "cgroup.cpu_per_core", title, "%", 40100, update_every, RRDSET_TYPE_STACKED);
1263
1180 - for(i = 0; i < cg->cpuacct_usage.cpus ;i++) {
1181 - snprintfz(id, CHART_TITLE_MAX, "cpu%u", i);
1182 - rrddim_add(st, id, NULL, 100, 1000000000, RRDDIM_INCREMENTAL);
1264 + for(i = 0; i < cg->cpuacct_usage.cpus; i++) {
1265 + snprintfz(id, CHART_TITLE_MAX, "cpu%u", i);
1266 + rrddim_add(cg->st_cpu_per_core, id, NULL, 100, 1000000000, RRDDIM_INCREMENTAL);
1267 + }
1268 }
1269 }
1185 - else rrdset_next(st);
1270 + else rrdset_next(cg->st_cpu_per_core);
1271
1272 for(i = 0; i < cg->cpuacct_usage.cpus ;i++) {
1273 snprintfz(id, CHART_TITLE_MAX, "cpu%u", i);
1189 - rrddim_set(st, id, cg->cpuacct_usage.cpu_percpu[i]);
1274 + rrddim_set(cg->st_cpu_per_core, id, cg->cpuacct_usage.cpu_percpu[i]);
1275 }
1191 - rrdset_done(st);
1276 + rrdset_done(cg->st_cpu_per_core);
1277 }
1278
1279 if(cg->memory.updated) {
1280 if(cg->memory.cache + cg->memory.rss + cg->memory.rss_huge + cg->memory.mapped_file > 0) {
1196 - st = rrdset_find_bytype(type, "mem");
1197 - if(!st) {
1198 - snprintfz(title, CHART_TITLE_MAX, "Memory Usage for cgroup %s", cg->chart_title);
1199 - st = rrdset_create(type, "mem", NULL, "mem", "cgroup.mem", title, "MB", 40210, update_every,
1200 - RRDSET_TYPE_STACKED);
1201 -
1202 - rrddim_add(st, "cache", NULL, 1, 1024 * 1024, RRDDIM_ABSOLUTE);
1203 - rrddim_add(st, "rss", NULL, 1, 1024 * 1024, RRDDIM_ABSOLUTE);
1204 - if(cg->memory.has_dirty_swap)
1205 - rrddim_add(st, "swap", NULL, 1, 1024 * 1024, RRDDIM_ABSOLUTE);
1206 - rrddim_add(st, "rss_huge", NULL, 1, 1024 * 1024, RRDDIM_ABSOLUTE);
1207 - rrddim_add(st, "mapped_file", NULL, 1, 1024 * 1024, RRDDIM_ABSOLUTE);
1281 + if(unlikely(!cg->st_mem)) {
1282 + cg->st_mem = rrdset_find_bytype(cgroup_chart_type(type, cg->id, RRD_ID_LENGTH_MAX), "mem");
1283 + if(!cg->st_mem) {
1284 + snprintfz(title, CHART_TITLE_MAX, "Memory Usage for cgroup %s", cg->chart_title);
1285 + cg->st_mem = rrdset_create(type, "mem", NULL, "mem", "cgroup.mem", title, "MB", 40210, update_every, RRDSET_TYPE_STACKED);
1286 +
1287 + rrddim_add(cg->st_mem, "cache", NULL, 1, 1024 * 1024, RRDDIM_ABSOLUTE);
1288 + rrddim_add(cg->st_mem, "rss", NULL, 1, 1024 * 1024, RRDDIM_ABSOLUTE);
1289 + if(cg->memory.has_dirty_swap)
1290 + rrddim_add(cg->st_mem, "swap", NULL, 1, 1024 * 1024, RRDDIM_ABSOLUTE);
1291 + rrddim_add(cg->st_mem, "rss_huge", NULL, 1, 1024 * 1024, RRDDIM_ABSOLUTE);
1292 + rrddim_add(cg->st_mem, "mapped_file", NULL, 1, 1024 * 1024, RRDDIM_ABSOLUTE);
1293 + }
1294 }
1209 - else rrdset_next(st);
1295 + else rrdset_next(cg->st_mem);
1296
1211 - rrddim_set(st, "cache", cg->memory.cache);
1212 - rrddim_set(st, "rss", cg->memory.rss);
1297 + rrddim_set(cg->st_mem, "cache", cg->memory.cache);
1298 + rrddim_set(cg->st_mem, "rss", cg->memory.rss);
1299 if(cg->memory.has_dirty_swap)
1214 - rrddim_set(st, "swap", cg->memory.swap);
1215 - rrddim_set(st, "rss_huge", cg->memory.rss_huge);
1216 - rrddim_set(st, "mapped_file", cg->memory.mapped_file);
1217 - rrdset_done(st);
1300 + rrddim_set(cg->st_mem, "swap", cg->memory.swap);
1301 + rrddim_set(cg->st_mem, "rss_huge", cg->memory.rss_huge);
1302 + rrddim_set(cg->st_mem, "mapped_file", cg->memory.mapped_file);
1303 + rrdset_done(cg->st_mem);
1304 }
1305
1220 - st = rrdset_find_bytype(type, "writeback");
1221 - if(!st) {
1222 - snprintfz(title, CHART_TITLE_MAX, "Writeback Memory for cgroup %s", cg->chart_title);
1223 - st = rrdset_create(type, "writeback", NULL, "mem", "cgroup.writeback", title, "MB", 40300,
1224 - update_every, RRDSET_TYPE_AREA);
1306 + if(unlikely(!cg->st_writeback)) {
1307 + cg->st_writeback = rrdset_find_bytype(cgroup_chart_type(type, cg->id, RRD_ID_LENGTH_MAX), "writeback");
1308 + if(!cg->st_writeback) {
1309 + snprintfz(title, CHART_TITLE_MAX, "Writeback Memory for cgroup %s", cg->chart_title);
1310 + cg->st_writeback = rrdset_create(type, "writeback", NULL, "mem", "cgroup.writeback", title, "MB", 40300, update_every, RRDSET_TYPE_AREA);
1311
1226 - if(cg->memory.has_dirty_swap)
1227 - rrddim_add(st, "dirty", NULL, 1, 1024 * 1024, RRDDIM_ABSOLUTE);
1228 - rrddim_add(st, "writeback", NULL, 1, 1024 * 1024, RRDDIM_ABSOLUTE);
1312 + if(cg->memory.has_dirty_swap)
1313 + rrddim_add(cg->st_writeback, "dirty", NULL, 1, 1024 * 1024, RRDDIM_ABSOLUTE);
1314 + rrddim_add(cg->st_writeback, "writeback", NULL, 1, 1024 * 1024, RRDDIM_ABSOLUTE);
1315 + }
1316 }
1230 - else rrdset_next(st);
1317 + else rrdset_next(cg->st_writeback);
1318
1319 if(cg->memory.has_dirty_swap)
1233 - rrddim_set(st, "dirty", cg->memory.dirty);
1234 - rrddim_set(st, "writeback", cg->memory.writeback);
1235 - rrdset_done(st);
1320 + rrddim_set(cg->st_writeback, "dirty", cg->memory.dirty);
1321 + rrddim_set(cg->st_writeback, "writeback", cg->memory.writeback);
1322 + rrdset_done(cg->st_writeback);
1323
1324 if(cg->memory.pgpgin + cg->memory.pgpgout > 0) {
1238 - st = rrdset_find_bytype(type, "mem_activity");
1239 - if(!st) {
1240 - snprintfz(title, CHART_TITLE_MAX, "Memory Activity for cgroup %s", cg->chart_title);
1241 - st = rrdset_create(type, "mem_activity", NULL, "mem", "cgroup.mem_activity", title, "MB/s",
1242 - 40400, update_every, RRDSET_TYPE_LINE);
1243 -
1244 - rrddim_add(st, "pgpgin", "in", sysconf(_SC_PAGESIZE), 1024 * 1024, RRDDIM_INCREMENTAL);
1245 - rrddim_add(st, "pgpgout", "out", -sysconf(_SC_PAGESIZE), 1024 * 1024, RRDDIM_INCREMENTAL);
1325 + if(unlikely(!cg->st_mem_activity)) {
1326 + cg->st_mem_activity = rrdset_find_bytype(cgroup_chart_type(type, cg->id, RRD_ID_LENGTH_MAX), "mem_activity");
1327 + if(!cg->st_mem_activity) {
1328 + snprintfz(title, CHART_TITLE_MAX, "Memory Activity for cgroup %s", cg->chart_title);
1329 + cg->st_mem_activity = rrdset_create(type, "mem_activity", NULL, "mem", "cgroup.mem_activity", title, "MB/s", 40400, update_every, RRDSET_TYPE_LINE);
1330 +
1331 + rrddim_add(cg->st_mem_activity, "pgpgin", "in", sysconf(_SC_PAGESIZE), 1024 * 1024, RRDDIM_INCREMENTAL);
1332 + rrddim_add(cg->st_mem_activity, "pgpgout", "out", -sysconf(_SC_PAGESIZE), 1024 * 1024, RRDDIM_INCREMENTAL);
1333 + }
1334 }
1247 - else rrdset_next(st);
1335 + else rrdset_next(cg->st_mem_activity);
1336
1249 - rrddim_set(st, "pgpgin", cg->memory.pgpgin);
1250 - rrddim_set(st, "pgpgout", cg->memory.pgpgout);
1251 - rrdset_done(st);
1337 + rrddim_set(cg->st_mem_activity, "pgpgin", cg->memory.pgpgin);
1338 + rrddim_set(cg->st_mem_activity, "pgpgout", cg->memory.pgpgout);
1339 + rrdset_done(cg->st_mem_activity);
1340 }
1341
1342 if(cg->memory.pgfault + cg->memory.pgmajfault > 0) {
1255 - st = rrdset_find_bytype(type, "pgfaults");
1256 - if(!st) {
1257 - snprintfz(title, CHART_TITLE_MAX, "Memory Page Faults for cgroup %s", cg->chart_title);
1258 - st = rrdset_create(type, "pgfaults", NULL, "mem", "cgroup.pgfaults", title, "MB/s", 40500,
1259 - update_every, RRDSET_TYPE_LINE);
1260 -
1261 - rrddim_add(st, "pgfault", NULL, sysconf(_SC_PAGESIZE), 1024 * 1024, RRDDIM_INCREMENTAL);
1262 - rrddim_add(st, "pgmajfault", "swap", -sysconf(_SC_PAGESIZE), 1024 * 1024, RRDDIM_INCREMENTAL);
1343 + if(unlikely(!cg->st_pgfaults)) {
1344 + cg->st_pgfaults = rrdset_find_bytype(cgroup_chart_type(type, cg->id, RRD_ID_LENGTH_MAX), "pgfaults");
1345 + if(!cg->st_pgfaults) {
1346 + snprintfz(title, CHART_TITLE_MAX, "Memory Page Faults for cgroup %s", cg->chart_title);
1347 + cg->st_pgfaults = rrdset_create(type, "pgfaults", NULL, "mem", "cgroup.pgfaults", title, "MB/s", 40500, update_every, RRDSET_TYPE_LINE);
1348 +
1349 + rrddim_add(cg->st_pgfaults, "pgfault", NULL, sysconf(_SC_PAGESIZE), 1024 * 1024, RRDDIM_INCREMENTAL);
1350 + rrddim_add(cg->st_pgfaults, "pgmajfault", "swap", -sysconf(_SC_PAGESIZE), 1024 * 1024, RRDDIM_INCREMENTAL);
1351 + }
1352 }
1264 - else rrdset_next(st);
1353 + else rrdset_next(cg->st_pgfaults);
1354
1266 - rrddim_set(st, "pgfault", cg->memory.pgfault);
1267 - rrddim_set(st, "pgmajfault", cg->memory.pgmajfault);
1268 - rrdset_done(st);
1355 + rrddim_set(cg->st_pgfaults, "pgfault", cg->memory.pgfault);
1356 + rrddim_set(cg->st_pgfaults, "pgmajfault", cg->memory.pgmajfault);
1357 + rrdset_done(cg->st_pgfaults);
1358 }
1359 }
1360
1361 if(cg->memory.usage_in_bytes_updated) {
1273 - st = rrdset_find_bytype(type, "mem_usage");
1274 - if(!st) {
1275 - snprintfz(title, CHART_TITLE_MAX, "Total Memory for cgroup %s", cg->chart_title);
1276 - st = rrdset_create(type, "mem_usage", NULL, "mem", "cgroup.mem_usage", title, "MB", 40200,
1277 - update_every, RRDSET_TYPE_STACKED);
1278 -
1279 - rrddim_add(st, "ram", NULL, 1, 1024 * 1024, RRDDIM_ABSOLUTE);
1280 - rrddim_add(st, "swap", NULL, 1, 1024 * 1024, RRDDIM_ABSOLUTE);
1362 + if(unlikely(!cg->st_mem_usage)) {
1363 + cg->st_mem_usage = rrdset_find_bytype(cgroup_chart_type(type, cg->id, RRD_ID_LENGTH_MAX), "mem_usage");
1364 + if(!cg->st_mem_usage) {
1365 + snprintfz(title, CHART_TITLE_MAX, "Total Memory for cgroup %s", cg->chart_title);
1366 + cg->st_mem_usage = rrdset_create(type, "mem_usage", NULL, "mem", "cgroup.mem_usage", title, "MB", 40200, update_every, RRDSET_TYPE_STACKED);
1367 +
1368 + rrddim_add(cg->st_mem_usage, "ram", NULL, 1, 1024 * 1024, RRDDIM_ABSOLUTE);
1369 + rrddim_add(cg->st_mem_usage, "swap", NULL, 1, 1024 * 1024, RRDDIM_ABSOLUTE);
1370 + }
1371 }
1282 - else rrdset_next(st);
1372 + else rrdset_next(cg->st_mem_usage);
1373
1284 - rrddim_set(st, "ram", cg->memory.usage_in_bytes);
1285 - rrddim_set(st, "swap", (cg->memory.msw_usage_in_bytes > cg->memory.usage_in_bytes)?cg->memory.msw_usage_in_bytes - cg->memory.usage_in_bytes:0);
1286 - rrdset_done(st);
1374 + rrddim_set(cg->st_mem_usage, "ram", cg->memory.usage_in_bytes);
1375 + rrddim_set(cg->st_mem_usage, "swap", (cg->memory.msw_usage_in_bytes > cg->memory.usage_in_bytes)?cg->memory.msw_usage_in_bytes - cg->memory.usage_in_bytes:0);
1376 + rrdset_done(cg->st_mem_usage);
1377 }
1378
1379 if(cg->memory.failcnt_updated && cg->memory.failcnt > 0) {
1290 - st = rrdset_find_bytype(type, "mem_failcnt");
1291 - if(!st) {
1292 - snprintfz(title, CHART_TITLE_MAX, "Memory Limit Failures for cgroup %s", cg->chart_title);
1293 - st = rrdset_create(type, "mem_failcnt", NULL, "mem", "cgroup.mem_failcnt", title, "MB", 40250,
1294 - update_every, RRDSET_TYPE_LINE);
1380 + if(unlikely(!cg->st_mem_failcnt)) {
1381 + cg->st_mem_failcnt = rrdset_find_bytype(cgroup_chart_type(type, cg->id, RRD_ID_LENGTH_MAX), "mem_failcnt");
1382 + if(!cg->st_mem_failcnt) {
1383 + snprintfz(title, CHART_TITLE_MAX, "Memory Limit Failures for cgroup %s", cg->chart_title);
1384 + cg->st_mem_failcnt = rrdset_create(type, "mem_failcnt", NULL, "mem", "cgroup.mem_failcnt", title, "MB", 40250, update_every, RRDSET_TYPE_LINE);
1385
1296 - rrddim_add(st, "failures", NULL, 1, 1, RRDDIM_INCREMENTAL);
1386 + rrddim_add(cg->st_mem_failcnt, "failures", NULL, 1, 1, RRDDIM_INCREMENTAL);
1387 + }
1388 }
1298 - else rrdset_next(st);
1389 + else rrdset_next(cg->st_mem_failcnt);
1390
1300 - rrddim_set(st, "failures", cg->memory.failcnt);
1301 - rrdset_done(st);
1391 + rrddim_set(cg->st_mem_failcnt, "failures", cg->memory.failcnt);
1392 + rrdset_done(cg->st_mem_failcnt);
1393 }
1394
1395 if(cg->io_service_bytes.updated && cg->io_service_bytes.Read + cg->io_service_bytes.Write > 0) {
1305 - st = rrdset_find_bytype(type, "io");
1306 - if(!st) {
1307 - snprintfz(title, CHART_TITLE_MAX, "I/O Bandwidth (all disks) for cgroup %s", cg->chart_title);
1308 - st = rrdset_create(type, "io", NULL, "disk", "cgroup.io", title, "KB/s", 41200,
1309 - update_every, RRDSET_TYPE_AREA);
1310 -
1311 - rrddim_add(st, "read", NULL, 1, 1024, RRDDIM_INCREMENTAL);
1312 - rrddim_add(st, "write", NULL, -1, 1024, RRDDIM_INCREMENTAL);
1396 + if(unlikely(!cg->st_io)) {
1397 + cg->st_io = rrdset_find_bytype(cgroup_chart_type(type, cg->id, RRD_ID_LENGTH_MAX), "io");
1398 + if(!cg->st_io) {
1399 + snprintfz(title, CHART_TITLE_MAX, "I/O Bandwidth (all disks) for cgroup %s", cg->chart_title);
1400 + cg->st_io = rrdset_create(type, "io", NULL, "disk", "cgroup.io", title, "KB/s", 41200, update_every, RRDSET_TYPE_AREA);
1401 +
1402 + rrddim_add(cg->st_io, "read", NULL, 1, 1024, RRDDIM_INCREMENTAL);
1403 + rrddim_add(cg->st_io, "write", NULL, -1, 1024, RRDDIM_INCREMENTAL);
1404 + }
1405 }
1314 - else rrdset_next(st);
1406 + else rrdset_next(cg->st_io);
1407
1316 - rrddim_set(st, "read", cg->io_service_bytes.Read);
1317 - rrddim_set(st, "write", cg->io_service_bytes.Write);
1318 - rrdset_done(st);
1408 + rrddim_set(cg->st_io, "read", cg->io_service_bytes.Read);
1409 + rrddim_set(cg->st_io, "write", cg->io_service_bytes.Write);
1410 + rrdset_done(cg->st_io);
1411 }
1412
1413 if(cg->io_serviced.updated && cg->io_serviced.Read + cg->io_serviced.Write > 0) {
1322 - st = rrdset_find_bytype(type, "serviced_ops");
1323 - if(!st) {
1324 - snprintfz(title, CHART_TITLE_MAX, "Serviced I/O Operations (all disks) for cgroup %s", cg->chart_title);
1325 - st = rrdset_create(type, "serviced_ops", NULL, "disk", "cgroup.serviced_ops", title, "operations/s", 41200,
1326 - update_every, RRDSET_TYPE_LINE);
1327 -
1328 - rrddim_add(st, "read", NULL, 1, 1, RRDDIM_INCREMENTAL);
1329 - rrddim_add(st, "write", NULL, -1, 1, RRDDIM_INCREMENTAL);
1414 + if(unlikely(!cg->st_serviced_ops)) {
1415 + cg->st_serviced_ops = rrdset_find_bytype(cgroup_chart_type(type, cg->id, RRD_ID_LENGTH_MAX), "serviced_ops");
1416 + if(!cg->st_serviced_ops) {
1417 + snprintfz(title, CHART_TITLE_MAX, "Serviced I/O Operations (all disks) for cgroup %s"
1418 + , cg->chart_title);
1419 + cg->st_serviced_ops = rrdset_create(type, "serviced_ops", NULL, "disk", "cgroup.serviced_ops", title, "operations/s", 41200, update_every, RRDSET_TYPE_LINE);
1420 +
1421 + rrddim_add(cg->st_serviced_ops, "read", NULL, 1, 1, RRDDIM_INCREMENTAL);
1422 + rrddim_add(cg->st_serviced_ops, "write", NULL, -1, 1, RRDDIM_INCREMENTAL);
1423 + }
1424 }
1331 - else rrdset_next(st);
1425 + else rrdset_next(cg->st_serviced_ops);
1426
1333 - rrddim_set(st, "read", cg->io_serviced.Read);
1334 - rrddim_set(st, "write", cg->io_serviced.Write);
1335 - rrdset_done(st);
1427 + rrddim_set(cg->st_serviced_ops, "read", cg->io_serviced.Read);
1428 + rrddim_set(cg->st_serviced_ops, "write", cg->io_serviced.Write);
1429 + rrdset_done(cg->st_serviced_ops);
1430 }
1431
1432 if(cg->throttle_io_service_bytes.updated && cg->throttle_io_service_bytes.Read + cg->throttle_io_service_bytes.Write > 0) {
1339 - st = rrdset_find_bytype(type, "throttle_io");
1340 - if(!st) {
1341 - snprintfz(title, CHART_TITLE_MAX, "Throttle I/O Bandwidth (all disks) for cgroup %s", cg->chart_title);
1342 - st = rrdset_create(type, "throttle_io", NULL, "disk", "cgroup.throttle_io", title, "KB/s", 41200,
1343 - update_every, RRDSET_TYPE_AREA);
1344 -
1345 - rrddim_add(st, "read", NULL, 1, 1024, RRDDIM_INCREMENTAL);
1346 - rrddim_add(st, "write", NULL, -1, 1024, RRDDIM_INCREMENTAL);
1433 + if(unlikely(!cg->st_throttle_io)) {
1434 + cg->st_throttle_io = rrdset_find_bytype(cgroup_chart_type(type, cg->id, RRD_ID_LENGTH_MAX), "throttle_io");
1435 + if(!cg->st_throttle_io) {
1436 + snprintfz(title, CHART_TITLE_MAX, "Throttle I/O Bandwidth (all disks) for cgroup %s", cg->chart_title);
1437 + cg->st_throttle_io = rrdset_create(type, "throttle_io", NULL, "disk", "cgroup.throttle_io", title, "KB/s", 41200, update_every, RRDSET_TYPE_AREA);
1438 +
1439 + rrddim_add(cg->st_throttle_io, "read", NULL, 1, 1024, RRDDIM_INCREMENTAL);
1440 + rrddim_add(cg->st_throttle_io, "write", NULL, -1, 1024, RRDDIM_INCREMENTAL);
1441 + }
1442 }
1348 - else rrdset_next(st);
1443 + else rrdset_next(cg->st_throttle_io);
1444
1350 - rrddim_set(st, "read", cg->throttle_io_service_bytes.Read);
1351 - rrddim_set(st, "write", cg->throttle_io_service_bytes.Write);
1352 - rrdset_done(st);
1445 + rrddim_set(cg->st_throttle_io, "read", cg->throttle_io_service_bytes.Read);
1446 + rrddim_set(cg->st_throttle_io, "write", cg->throttle_io_service_bytes.Write);
1447 + rrdset_done(cg->st_throttle_io);
1448 }
1449
1450
1451 if(cg->throttle_io_serviced.updated && cg->throttle_io_serviced.Read + cg->throttle_io_serviced.Write > 0) {
1357 - st = rrdset_find_bytype(type, "throttle_serviced_ops");
1358 - if(!st) {
1359 - snprintfz(title, CHART_TITLE_MAX, "Throttle Serviced I/O Operations (all disks) for cgroup %s", cg->chart_title);
1360 - st = rrdset_create(type, "throttle_serviced_ops", NULL, "disk", "cgroup.throttle_serviced_ops", title, "operations/s", 41200,
1361 - update_every, RRDSET_TYPE_LINE);
1362 -
1363 - rrddim_add(st, "read", NULL, 1, 1, RRDDIM_INCREMENTAL);
1364 - rrddim_add(st, "write", NULL, -1, 1, RRDDIM_INCREMENTAL);
1452 + if(unlikely(!cg->st_throttle_serviced_ops)) {
1453 + cg->st_throttle_serviced_ops = rrdset_find_bytype(cgroup_chart_type(type, cg->id, RRD_ID_LENGTH_MAX), "throttle_serviced_ops");
1454 + if(!cg->st_throttle_serviced_ops) {
1455 + snprintfz(title, CHART_TITLE_MAX, "Throttle Serviced I/O Operations (all disks) for cgroup %s", cg->chart_title);
1456 + cg->st_throttle_serviced_ops = rrdset_create(type, "throttle_serviced_ops", NULL, "disk", "cgroup.throttle_serviced_ops", title, "operations/s", 41200, update_every, RRDSET_TYPE_LINE);
1457 +
1458 + rrddim_add(cg->st_throttle_serviced_ops, "read", NULL, 1, 1, RRDDIM_INCREMENTAL);
1459 + rrddim_add(cg->st_throttle_serviced_ops, "write", NULL, -1, 1, RRDDIM_INCREMENTAL);
1460 + }
1461 }
1366 - else rrdset_next(st);
1462 + else rrdset_next(cg->st_throttle_serviced_ops);
1463
1368 - rrddim_set(st, "read", cg->throttle_io_serviced.Read);
1369 - rrddim_set(st, "write", cg->throttle_io_serviced.Write);
1370 - rrdset_done(st);
1464 + rrddim_set(cg->st_throttle_serviced_ops, "read", cg->throttle_io_serviced.Read);
1465 + rrddim_set(cg->st_throttle_serviced_ops, "write", cg->throttle_io_serviced.Write);
1466 + rrdset_done(cg->st_throttle_serviced_ops);
1467 }
1468
1469 if(cg->io_queued.updated) {
1374 - st = rrdset_find_bytype(type, "queued_ops");
1375 - if(!st) {
1376 - snprintfz(title, CHART_TITLE_MAX, "Queued I/O Operations (all disks) for cgroup %s", cg->chart_title);
1377 - st = rrdset_create(type, "queued_ops", NULL, "disk", "cgroup.queued_ops", title, "operations", 42000,
1378 - update_every, RRDSET_TYPE_LINE);
1379 -
1380 - rrddim_add(st, "read", NULL, 1, 1, RRDDIM_ABSOLUTE);
1381 - rrddim_add(st, "write", NULL, -1, 1, RRDDIM_ABSOLUTE);
1470 + if(unlikely(!cg->st_queued_ops)) {
1471 + cg->st_queued_ops = rrdset_find_bytype(cgroup_chart_type(type, cg->id, RRD_ID_LENGTH_MAX), "queued_ops");
1472 + if(!cg->st_queued_ops) {
1473 + snprintfz(title, CHART_TITLE_MAX, "Queued I/O Operations (all disks) for cgroup %s", cg->chart_title);
1474 + cg->st_queued_ops = rrdset_create(type, "queued_ops", NULL, "disk", "cgroup.queued_ops", title, "operations", 42000, update_every, RRDSET_TYPE_LINE);
1475 +
1476 + rrddim_add(cg->st_queued_ops, "read", NULL, 1, 1, RRDDIM_ABSOLUTE);
1477 + rrddim_add(cg->st_queued_ops, "write", NULL, -1, 1, RRDDIM_ABSOLUTE);
1478 + }
1479 }
1383 - else rrdset_next(st);
1480 + else rrdset_next(cg->st_queued_ops);
1481
1385 - rrddim_set(st, "read", cg->io_queued.Read);
1386 - rrddim_set(st, "write", cg->io_queued.Write);
1387 - rrdset_done(st);
1482 + rrddim_set(cg->st_queued_ops, "read", cg->io_queued.Read);
1483 + rrddim_set(cg->st_queued_ops, "write", cg->io_queued.Write);
1484 + rrdset_done(cg->st_queued_ops);
1485 }
1486
1487 if(cg->io_merged.updated && cg->io_merged.Read + cg->io_merged.Write > 0) {
1391 - st = rrdset_find_bytype(type, "merged_ops");
1392 - if(!st) {
1393 - snprintfz(title, CHART_TITLE_MAX, "Merged I/O Operations (all disks) for cgroup %s", cg->chart_title);
1394 - st = rrdset_create(type, "merged_ops", NULL, "disk", "cgroup.merged_ops", title, "operations/s", 42100,
1395 - update_every, RRDSET_TYPE_LINE);
1396 -
1397 - rrddim_add(st, "read", NULL, 1, 1024, RRDDIM_INCREMENTAL);
1398 - rrddim_add(st, "write", NULL, -1, 1024, RRDDIM_INCREMENTAL);
1488 + if(unlikely(!cg->st_merged_ops)) {
1489 + cg->st_merged_ops = rrdset_find_bytype(cgroup_chart_type(type, cg->id, RRD_ID_LENGTH_MAX), "merged_ops");
1490 + if(!cg->st_merged_ops) {
1491 + snprintfz(title, CHART_TITLE_MAX, "Merged I/O Operations (all disks) for cgroup %s", cg->chart_title);
1492 + cg->st_merged_ops = rrdset_create(type, "merged_ops", NULL, "disk", "cgroup.merged_ops", title, "operations/s", 42100, update_every, RRDSET_TYPE_LINE);
1493 +
1494 + rrddim_add(cg->st_merged_ops, "read", NULL, 1, 1024, RRDDIM_INCREMENTAL);
1495 + rrddim_add(cg->st_merged_ops, "write", NULL, -1, 1024, RRDDIM_INCREMENTAL);
1496 + }
1497 }
1400 - else rrdset_next(st);
1498 + else rrdset_next(cg->st_merged_ops);
1499
1402 - rrddim_set(st, "read", cg->io_merged.Read);
1403 - rrddim_set(st, "write", cg->io_merged.Write);
1404 - rrdset_done(st);
1500 + rrddim_set(cg->st_merged_ops, "read", cg->io_merged.Read);
1501 + rrddim_set(cg->st_merged_ops, "write", cg->io_merged.Write);
1502 + rrdset_done(cg->st_merged_ops);
1503 }
1504 }
1505