proc/diskstats: add block-devices function (#16338)
* diskstats add block-devices function * fix writes time max
Ilya Mashchenko committed
Nov 6, 2023 at 10:38 UTC
b7592c443c3bc9f7d7fcccf203817e15878c857b
2 files changed
+472
-94
collectors/proc.plugin/plugin_proc.c
+2
@@ -142,6 +142,8 @@ void *proc_main(void *ptr)
142
{
143
worker_register("PROC");
144
145
+ rrd_collector_started();
146
+
147
if (config_get_boolean("plugin:proc", "/proc/net/dev", CONFIG_BOOLEAN_YES)) {
148
netdev_thread = mallocz(sizeof(netdata_thread_t));
149
netdata_log_debug(D_SYSTEM, "Starting thread %s.", THREAD_NETDEV_NAME);
collectors/proc.plugin/proc_diskstats.c
+470
-94
@@ -6,6 +6,8 @@
6
#define PLUGIN_PROC_MODULE_DISKSTATS_NAME "/proc/diskstats"
7
#define CONFIG_SECTION_PLUGIN_PROC_DISKSTATS "plugin:" PLUGIN_PROC_CONFIG_NAME ":" PLUGIN_PROC_MODULE_DISKSTATS_NAME
8
9
+#define RRDFUNCTIONS_DISKSTATS_HELP "View block device statistics"
10
+
11
#define DISK_TYPE_UNKNOWN 0
12
#define DISK_TYPE_PHYSICAL 1
13
#define DISK_TYPE_PARTITION 2
@@ -14,6 +16,8 @@
16
#define DEFAULT_PREFERRED_IDS "*"
17
#define DEFAULT_EXCLUDED_DISKS "loop* ram*"
18
19
+static netdata_mutex_t diskstats_dev_mutex = NETDATA_MUTEX_INITIALIZER;
20
+
21
static struct disk {
22
char *disk; // the name of the disk (sda, sdb, etc, after being looked up)
23
char *device; // the device of the disk (before being looked up)
@@ -28,6 +32,9 @@ static struct disk {
32
int sector_size;
33
int type;
34
35
+ bool excluded;
36
+ bool function_ready;
37
+
38
char *mount_point;
39
40
char *chart_id;
@@ -543,7 +550,11 @@ static inline char *get_disk_model(char *device) {
550
return NULL;
551
}
552
546
- return strdupz(buffer);
553
+ char *clean = trim(buffer);
554
+ if (!clean)
555
+ return NULL;
556
+
557
+ return strdupz(clean);
558
}
559
560
static inline char *get_disk_serial(char *device) {
@@ -582,8 +593,10 @@ static inline char *get_disk_serial(char *device) {
593
static void get_disk_config(struct disk *d) {
594
int def_enable = global_enable_new_disks_detected_at_runtime;
595
585
- if(def_enable != CONFIG_BOOLEAN_NO && (simple_pattern_matches(excluded_disks, d->device) || simple_pattern_matches(excluded_disks, d->disk)))
596
+ if(def_enable != CONFIG_BOOLEAN_NO && (simple_pattern_matches(excluded_disks, d->device) || simple_pattern_matches(excluded_disks, d->disk))) {
597
+ d->excluded = true;
598
def_enable = CONFIG_BOOLEAN_NO;
599
+ }
600
601
char var_name[4096 + 1];
602
snprintfz(var_name, 4096, CONFIG_SECTION_PLUGIN_PROC_DISKSTATS ":%s", d->disk);
@@ -663,6 +676,8 @@ static void get_disk_config(struct disk *d) {
676
ddo_ext = global_do_ext,
677
ddo_backlog = global_do_backlog,
678
ddo_bcache = global_do_bcache;
679
+ } else {
680
+ d->excluded = true;
681
}
682
683
d->do_io = config_get_boolean_ondemand(var_name, "bandwidth", ddo_io);
@@ -702,6 +717,8 @@ static struct disk *get_disk(unsigned long major, unsigned long minor, char *dis
717
// create a new disk structure
718
d = (struct disk *)callocz(1, sizeof(struct disk));
719
720
+ d->excluded = false;
721
+ d->function_ready = false;
722
d->disk = get_disk_name(major, minor, disk);
723
d->device = strdupz(disk);
724
d->disk_by_id = get_disk_by_id(disk);
@@ -963,35 +980,457 @@ static struct disk *get_disk(unsigned long major, unsigned long minor, char *dis
980
}
981
982
get_disk_config(d);
983
+
984
return d;
985
}
986
987
+static const char *get_disk_type_string(int disk_type) {
988
+ switch (disk_type) {
989
+ case DISK_TYPE_PHYSICAL:
990
+ return "physical";
991
+ case DISK_TYPE_PARTITION:
992
+ return "partition";
993
+ case DISK_TYPE_VIRTUAL:
994
+ return "virtual";
995
+ default:
996
+ return "unknown";
997
+ }
998
+}
999
+
1000
static void add_labels_to_disk(struct disk *d, RRDSET *st) {
1001
rrdlabels_add(st->rrdlabels, "device", d->disk, RRDLABEL_SRC_AUTO);
1002
rrdlabels_add(st->rrdlabels, "mount_point", d->mount_point, RRDLABEL_SRC_AUTO);
1003
rrdlabels_add(st->rrdlabels, "id", d->disk_by_id, RRDLABEL_SRC_AUTO);
1004
rrdlabels_add(st->rrdlabels, "model", d->model, RRDLABEL_SRC_AUTO);
1005
rrdlabels_add(st->rrdlabels, "serial", d->serial, RRDLABEL_SRC_AUTO);
975
-// rrdlabels_add(st->rrdlabels, "rotational", d->rotational ? "true" : "false", RRDLABEL_SRC_AUTO);
976
-// rrdlabels_add(st->rrdlabels, "removable", d->removable ? "true" : "false", RRDLABEL_SRC_AUTO);
1006
+ rrdlabels_add(st->rrdlabels, "device_type", get_disk_type_string(d->type), RRDLABEL_SRC_AUTO);
1007
+}
1008
978
- switch (d->type) {
979
- default:
980
- case DISK_TYPE_UNKNOWN:
981
- rrdlabels_add(st->rrdlabels, "device_type", "unknown", RRDLABEL_SRC_AUTO);
982
- break;
1009
+static int diskstats_function_block_devices(BUFFER *wb, int timeout __maybe_unused, const char *function __maybe_unused,
1010
+ void *collector_data __maybe_unused,
1011
+ rrd_function_result_callback_t result_cb, void *result_cb_data,
1012
+ rrd_function_is_cancelled_cb_t is_cancelled_cb, void *is_cancelled_cb_data,
1013
+ rrd_function_register_canceller_cb_t register_canceller_cb __maybe_unused,
1014
+ void *register_canceller_cb_data __maybe_unused) {
1015
+
1016
+ buffer_flush(wb);
1017
+ wb->content_type = CT_APPLICATION_JSON;
1018
+ buffer_json_initialize(wb, "\"", "\"", 0, true, BUFFER_JSON_OPTIONS_DEFAULT);
1019
+
1020
+ buffer_json_member_add_string(wb, "hostname", rrdhost_hostname(localhost));
1021
+ buffer_json_member_add_uint64(wb, "status", HTTP_RESP_OK);
1022
+ buffer_json_member_add_string(wb, "type", "table");
1023
+ buffer_json_member_add_time_t(wb, "update_every", 1);
1024
+ buffer_json_member_add_string(wb, "help", RRDFUNCTIONS_DISKSTATS_HELP);
1025
+ buffer_json_member_add_array(wb, "data");
1026
+
1027
+ double max_io_reads = 0.0;
1028
+ double max_io_writes = 0.0;
1029
+ double max_io = 0.0;
1030
+ double max_backlog_time = 0.0;
1031
+ double max_busy_time = 0.0;
1032
+ double max_busy_perc = 0.0;
1033
+ double max_iops_reads = 0.0;
1034
+ double max_iops_writes = 0.0;
1035
+ double max_iops_time_reads = 0.0;
1036
+ double max_iops_time_writes = 0.0;
1037
+ double max_iops_avg_time_read = 0.0;
1038
+ double max_iops_avg_time_write = 0.0;
1039
+ double max_iops_avg_size_read = 0.0;
1040
+ double max_iops_avg_size_write = 0.0;
1041
+
1042
+ netdata_mutex_lock(&diskstats_dev_mutex);
1043
+
1044
+ for (struct disk *d = disk_root; d; d = d->next) {
1045
+ if (unlikely(!d->function_ready))
1046
+ continue;
1047
984
- case DISK_TYPE_PHYSICAL:
985
- rrdlabels_add(st->rrdlabels, "device_type", "physical", RRDLABEL_SRC_AUTO);
986
- break;
1048
+ buffer_json_add_array_item_array(wb);
1049
988
- case DISK_TYPE_PARTITION:
989
- rrdlabels_add(st->rrdlabels, "device_type", "partition", RRDLABEL_SRC_AUTO);
990
- break;
1050
+ buffer_json_add_array_item_string(wb, d->device);
1051
+ buffer_json_add_array_item_string(wb, get_disk_type_string(d->type));
1052
+ buffer_json_add_array_item_string(wb, d->disk_by_id);
1053
+ buffer_json_add_array_item_string(wb, d->model);
1054
+ buffer_json_add_array_item_string(wb, d->serial);
1055
992
- case DISK_TYPE_VIRTUAL:
993
- rrdlabels_add(st->rrdlabels, "device_type", "virtual", RRDLABEL_SRC_AUTO);
994
- break;
1056
+ // IO
1057
+ double io_reads = NAN;
1058
+ if (d->rd_io_reads) {
1059
+ io_reads = d->rd_io_reads->collector.last_stored_value / 1024.0;
1060
+ max_io_reads = MAX(max_io_reads, io_reads);
1061
+ }
1062
+ buffer_json_add_array_item_double(wb, io_reads);
1063
+
1064
+ double io_writes = NAN;
1065
+ if (d->rd_io_writes) {
1066
+ io_writes = ABS(d->rd_io_writes->collector.last_stored_value / 1024.0);
1067
+ max_io_writes = MAX(max_io_writes, io_writes);
1068
+ }
1069
+ buffer_json_add_array_item_double(wb, io_writes);
1070
+
1071
+ double io_total = NAN;
1072
+ if (!isnan(io_reads) && !isnan(io_writes)) {
1073
+ io_total = io_reads + io_writes;
1074
+ max_io = MAX(max_io, io_total);
1075
+ }
1076
+ buffer_json_add_array_item_double(wb, io_total);
1077
+
1078
+ // Backlog and Busy Time
1079
+ double busy_perc = NAN;
1080
+ if (d->rd_util_utilization) {
1081
+ busy_perc = d->rd_util_utilization->collector.last_stored_value;
1082
+ max_busy_perc = MAX(max_busy_perc, busy_perc);
1083
+ }
1084
+ buffer_json_add_array_item_double(wb, busy_perc);
1085
+ double busy_time = NAN;
1086
+ if (d->rd_busy_busy) {
1087
+ busy_time = d->rd_busy_busy->collector.last_stored_value;
1088
+ max_busy_time = MAX(max_busy_time, busy_time);
1089
+ }
1090
+ buffer_json_add_array_item_double(wb, busy_time);
1091
+ double backlog_time = NAN;
1092
+ if (d->rd_backlog_backlog) {
1093
+ backlog_time = d->rd_backlog_backlog->collector.last_stored_value;
1094
+ max_backlog_time = MAX(max_backlog_time, backlog_time);
1095
+ }
1096
+ buffer_json_add_array_item_double(wb, backlog_time);
1097
+
1098
+ // IOPS
1099
+ double iops_reads = NAN;
1100
+ if (d->rd_ops_reads) {
1101
+ iops_reads = d->rd_ops_reads->collector.last_stored_value;
1102
+ max_iops_reads = MAX(max_iops_reads, iops_reads);
1103
+ }
1104
+ buffer_json_add_array_item_double(wb, iops_reads);
1105
+ double iops_writes = NAN;
1106
+ if (d->rd_ops_writes) {
1107
+ iops_writes = ABS(d->rd_ops_writes->collector.last_stored_value);
1108
+ max_iops_writes = MAX(max_iops_writes, iops_writes);
1109
+ }
1110
+ buffer_json_add_array_item_double(wb, iops_writes);
1111
+
1112
+ // IO Time
1113
+ double iops_time_reads = NAN;
1114
+ if (d->rd_iotime_reads) {
1115
+ iops_time_reads = d->rd_iotime_reads->collector.last_stored_value;
1116
+ max_iops_time_reads = MAX(max_iops_time_reads, iops_time_reads);
1117
+ }
1118
+ buffer_json_add_array_item_double(wb, iops_time_reads);
1119
+
1120
+ double iops_time_writes = NAN;
1121
+ if (d->rd_iotime_writes) {
1122
+ iops_time_writes = ABS(d->rd_iotime_writes->collector.last_stored_value);
1123
+ max_iops_time_writes = MAX(max_iops_time_writes, iops_time_writes);
1124
+ }
1125
+ buffer_json_add_array_item_double(wb, iops_time_writes);
1126
+
1127
+ // Avg IO Time
1128
+ double iops_avg_time_read = NAN;
1129
+ if (d->rd_await_reads) {
1130
+ iops_avg_time_read = d->rd_await_reads->collector.last_stored_value;
1131
+ max_iops_avg_time_read = MAX(max_iops_avg_time_read, iops_avg_time_read);
1132
+ }
1133
+ buffer_json_add_array_item_double(wb, iops_avg_time_read);
1134
+ double iops_avg_time_write = NAN;
1135
+ if (d->rd_await_writes) {
1136
+ iops_avg_time_write = ABS(d->rd_await_writes->collector.last_stored_value);
1137
+ max_iops_avg_time_write = MAX(max_iops_avg_time_write, iops_avg_time_write);
1138
+ }
1139
+ buffer_json_add_array_item_double(wb, iops_avg_time_write);
1140
+
1141
+ // Avg IO Size
1142
+ double iops_avg_size_read = NAN;
1143
+ if (d->rd_avgsz_reads) {
1144
+ iops_avg_size_read = d->rd_avgsz_reads->collector.last_stored_value;
1145
+ max_iops_avg_size_read = MAX(max_iops_avg_size_read, iops_avg_size_read);
1146
+ }
1147
+ buffer_json_add_array_item_double(wb, iops_avg_size_read);
1148
+ double iops_avg_size_write = NAN;
1149
+ if (d->rd_avgsz_writes) {
1150
+ iops_avg_size_write = ABS(d->rd_avgsz_writes->collector.last_stored_value);
1151
+ max_iops_avg_size_write = MAX(max_iops_avg_size_write, iops_avg_size_write);
1152
+ }
1153
+ buffer_json_add_array_item_double(wb, iops_avg_size_write);
1154
+
1155
+ // End
1156
+ buffer_json_array_close(wb);
1157
+ }
1158
+
1159
+ netdata_mutex_unlock(&diskstats_dev_mutex);
1160
+
1161
+ buffer_json_array_close(wb); // data
1162
+ buffer_json_member_add_object(wb, "columns");
1163
+ {
1164
+ size_t field_id = 0;
1165
+
1166
+ buffer_rrdf_table_add_field(wb, field_id++, "Device", "Device Name",
1167
+ RRDF_FIELD_TYPE_STRING, RRDF_FIELD_VISUAL_VALUE, RRDF_FIELD_TRANSFORM_NONE,
1168
+ 0, NULL, NAN, RRDF_FIELD_SORT_ASCENDING, NULL,
1169
+ RRDF_FIELD_SUMMARY_COUNT, RRDF_FIELD_FILTER_MULTISELECT,
1170
+ RRDF_FIELD_OPTS_VISIBLE | RRDF_FIELD_OPTS_UNIQUE_KEY | RRDF_FIELD_OPTS_STICKY,
1171
+ NULL);
1172
+ buffer_rrdf_table_add_field(wb, field_id++, "Type", "Device Type",
1173
+ RRDF_FIELD_TYPE_STRING, RRDF_FIELD_VISUAL_VALUE, RRDF_FIELD_TRANSFORM_NONE,
1174
+ 0, NULL, NAN, RRDF_FIELD_SORT_ASCENDING, NULL,
1175
+ RRDF_FIELD_SUMMARY_COUNT, RRDF_FIELD_FILTER_MULTISELECT,
1176
+ RRDF_FIELD_OPTS_UNIQUE_KEY,
1177
+ NULL);
1178
+ buffer_rrdf_table_add_field(wb, field_id++, "ID", "Device ID",
1179
+ RRDF_FIELD_TYPE_STRING, RRDF_FIELD_VISUAL_VALUE, RRDF_FIELD_TRANSFORM_NONE,
1180
+ 0, NULL, NAN, RRDF_FIELD_SORT_ASCENDING, NULL,
1181
+ RRDF_FIELD_SUMMARY_COUNT, RRDF_FIELD_FILTER_MULTISELECT,
1182
+ RRDF_FIELD_OPTS_UNIQUE_KEY,
1183
+ NULL);
1184
+ buffer_rrdf_table_add_field(wb, field_id++, "Model", "Device Model",
1185
+ RRDF_FIELD_TYPE_STRING, RRDF_FIELD_VISUAL_VALUE, RRDF_FIELD_TRANSFORM_NONE,
1186
+ 0, NULL, NAN, RRDF_FIELD_SORT_ASCENDING, NULL,
1187
+ RRDF_FIELD_SUMMARY_COUNT, RRDF_FIELD_FILTER_MULTISELECT,
1188
+ RRDF_FIELD_OPTS_UNIQUE_KEY,
1189
+ NULL);
1190
+ buffer_rrdf_table_add_field(wb, field_id++, "Serial", "Device Serial Number",
1191
+ RRDF_FIELD_TYPE_STRING, RRDF_FIELD_VISUAL_VALUE, RRDF_FIELD_TRANSFORM_NONE,
1192
+ 0, NULL, NAN, RRDF_FIELD_SORT_ASCENDING, NULL,
1193
+ RRDF_FIELD_SUMMARY_COUNT, RRDF_FIELD_FILTER_MULTISELECT,
1194
+ RRDF_FIELD_OPTS_UNIQUE_KEY,
1195
+ NULL);
1196
+
1197
+ buffer_rrdf_table_add_field(wb, field_id++, "Read", "Data Read from Device",
1198
+ RRDF_FIELD_TYPE_BAR_WITH_INTEGER, RRDF_FIELD_VISUAL_BAR, RRDF_FIELD_TRANSFORM_NUMBER,
1199
+ 2, "MiB", max_io_reads, RRDF_FIELD_SORT_DESCENDING, NULL,
1200
+ RRDF_FIELD_SUMMARY_SUM, RRDF_FIELD_FILTER_NONE,
1201
+ RRDF_FIELD_OPTS_VISIBLE,
1202
+ NULL);
1203
+ buffer_rrdf_table_add_field(wb, field_id++, "Written", "Data Writen to Device",
1204
+ RRDF_FIELD_TYPE_BAR_WITH_INTEGER, RRDF_FIELD_VISUAL_BAR, RRDF_FIELD_TRANSFORM_NUMBER,
1205
+ 2, "MiB", max_io_writes, RRDF_FIELD_SORT_DESCENDING, NULL,
1206
+ RRDF_FIELD_SUMMARY_SUM, RRDF_FIELD_FILTER_NONE,
1207
+ RRDF_FIELD_OPTS_VISIBLE,
1208
+ NULL);
1209
+ buffer_rrdf_table_add_field(wb, field_id++, "Total", "Data Transferred to and from Device",
1210
+ RRDF_FIELD_TYPE_BAR_WITH_INTEGER, RRDF_FIELD_VISUAL_BAR, RRDF_FIELD_TRANSFORM_NUMBER,
1211
+ 2, "MiB", max_io, RRDF_FIELD_SORT_DESCENDING, NULL,
1212
+ RRDF_FIELD_SUMMARY_SUM, RRDF_FIELD_FILTER_NONE,
1213
+ RRDF_FIELD_OPTS_VISIBLE,
1214
+ NULL);
1215
+
1216
+ buffer_rrdf_table_add_field(wb, field_id++, "Busy%", "Disk Busy Percentage",
1217
+ RRDF_FIELD_TYPE_BAR_WITH_INTEGER, RRDF_FIELD_VISUAL_BAR, RRDF_FIELD_TRANSFORM_NUMBER,
1218
+ 2, "%", max_busy_perc, RRDF_FIELD_SORT_DESCENDING, NULL,
1219
+ RRDF_FIELD_SUMMARY_SUM, RRDF_FIELD_FILTER_NONE,
1220
+ RRDF_FIELD_OPTS_VISIBLE,
1221
+ NULL);
1222
+ buffer_rrdf_table_add_field(wb, field_id++, "Busy", "Disk Busy Time",
1223
+ RRDF_FIELD_TYPE_BAR_WITH_INTEGER, RRDF_FIELD_VISUAL_BAR, RRDF_FIELD_TRANSFORM_NUMBER,
1224
+ 2, "milliseconds", max_busy_time, RRDF_FIELD_SORT_DESCENDING, NULL,
1225
+ RRDF_FIELD_SUMMARY_SUM, RRDF_FIELD_FILTER_NONE,
1226
+ RRDF_FIELD_OPTS_VISIBLE,
1227
+ NULL);
1228
+ buffer_rrdf_table_add_field(wb, field_id++, "Backlog", "Disk Backlog",
1229
+ RRDF_FIELD_TYPE_BAR_WITH_INTEGER, RRDF_FIELD_VISUAL_BAR, RRDF_FIELD_TRANSFORM_NUMBER,
1230
+ 2, "milliseconds", max_backlog_time, RRDF_FIELD_SORT_DESCENDING, NULL,
1231
+ RRDF_FIELD_SUMMARY_SUM, RRDF_FIELD_FILTER_NONE,
1232
+ RRDF_FIELD_OPTS_VISIBLE,
1233
+ NULL);
1234
+
1235
+ buffer_rrdf_table_add_field(wb, field_id++, "Reads", "Completed Read Operations",
1236
+ RRDF_FIELD_TYPE_BAR_WITH_INTEGER, RRDF_FIELD_VISUAL_BAR, RRDF_FIELD_TRANSFORM_NUMBER,
1237
+ 2, "ops", max_iops_reads, RRDF_FIELD_SORT_DESCENDING, NULL,
1238
+ RRDF_FIELD_SUMMARY_SUM, RRDF_FIELD_FILTER_NONE,
1239
+ RRDF_FIELD_OPTS_VISIBLE,
1240
+ NULL);
1241
+ buffer_rrdf_table_add_field(wb, field_id++, "Writes", "Completed Write Operations",
1242
+ RRDF_FIELD_TYPE_BAR_WITH_INTEGER, RRDF_FIELD_VISUAL_BAR, RRDF_FIELD_TRANSFORM_NUMBER,
1243
+ 2, "ops", max_iops_writes, RRDF_FIELD_SORT_DESCENDING, NULL,
1244
+ RRDF_FIELD_SUMMARY_SUM, RRDF_FIELD_FILTER_NONE,
1245
+ RRDF_FIELD_OPTS_VISIBLE,
1246
+ NULL);
1247
+
1248
+ buffer_rrdf_table_add_field(wb, field_id++, "ReadsTime", "Read Operations Time",
1249
+ RRDF_FIELD_TYPE_BAR_WITH_INTEGER, RRDF_FIELD_VISUAL_BAR, RRDF_FIELD_TRANSFORM_NUMBER,
1250
+ 2, "milliseconds", max_iops_time_reads, RRDF_FIELD_SORT_DESCENDING, NULL,
1251
+ RRDF_FIELD_SUMMARY_SUM, RRDF_FIELD_FILTER_NONE,
1252
+ RRDF_FIELD_OPTS_VISIBLE,
1253
+ NULL);
1254
+ buffer_rrdf_table_add_field(wb, field_id++, "WritesTime", "Write Operations Time",
1255
+ RRDF_FIELD_TYPE_BAR_WITH_INTEGER, RRDF_FIELD_VISUAL_BAR, RRDF_FIELD_TRANSFORM_NUMBER,
1256
+ 2, "milliseconds", max_iops_time_writes, RRDF_FIELD_SORT_DESCENDING, NULL,
1257
+ RRDF_FIELD_SUMMARY_SUM, RRDF_FIELD_FILTER_NONE,
1258
+ RRDF_FIELD_OPTS_VISIBLE,
1259
+ NULL);
1260
+
1261
+ buffer_rrdf_table_add_field(wb, field_id++, "ReadAvgTime", "Average Read Operation Service Time",
1262
+ RRDF_FIELD_TYPE_BAR_WITH_INTEGER, RRDF_FIELD_VISUAL_BAR, RRDF_FIELD_TRANSFORM_NUMBER,
1263
+ 2, "milliseconds", max_iops_avg_time_read, RRDF_FIELD_SORT_DESCENDING, NULL,
1264
+ RRDF_FIELD_SUMMARY_SUM, RRDF_FIELD_FILTER_NONE,
1265
+ RRDF_FIELD_OPTS_VISIBLE,
1266
+ NULL);
1267
+ buffer_rrdf_table_add_field(wb, field_id++, "WriteAvgTime", "Average Write Operation Service Time",
1268
+ RRDF_FIELD_TYPE_BAR_WITH_INTEGER, RRDF_FIELD_VISUAL_BAR, RRDF_FIELD_TRANSFORM_NUMBER,
1269
+ 2, "milliseconds", max_iops_avg_time_write, RRDF_FIELD_SORT_DESCENDING, NULL,
1270
+ RRDF_FIELD_SUMMARY_SUM, RRDF_FIELD_FILTER_NONE,
1271
+ RRDF_FIELD_OPTS_VISIBLE,
1272
+ NULL);
1273
+
1274
+ buffer_rrdf_table_add_field(wb, field_id++, "ReadAvgSz", "Average Read Operation Size",
1275
+ RRDF_FIELD_TYPE_BAR_WITH_INTEGER, RRDF_FIELD_VISUAL_BAR, RRDF_FIELD_TRANSFORM_NUMBER,
1276
+ 2, "KiB", max_iops_avg_size_read, RRDF_FIELD_SORT_DESCENDING, NULL,
1277
+ RRDF_FIELD_SUMMARY_SUM, RRDF_FIELD_FILTER_NONE,
1278
+ RRDF_FIELD_OPTS_VISIBLE,
1279
+ NULL);
1280
+ buffer_rrdf_table_add_field(wb, field_id++, "WriteAvgSz", "Average Write Operation Size",
1281
+ RRDF_FIELD_TYPE_BAR_WITH_INTEGER, RRDF_FIELD_VISUAL_BAR, RRDF_FIELD_TRANSFORM_NUMBER,
1282
+ 2, "KiB", max_iops_avg_size_write, RRDF_FIELD_SORT_DESCENDING, NULL,
1283
+ RRDF_FIELD_SUMMARY_SUM, RRDF_FIELD_FILTER_NONE,
1284
+ RRDF_FIELD_OPTS_VISIBLE,
1285
+ NULL);
1286
+ }
1287
+
1288
+ buffer_json_object_close(wb); // columns
1289
+ buffer_json_member_add_string(wb, "default_sort_column", "Total");
1290
+
1291
+ buffer_json_member_add_object(wb, "charts");
1292
+ {
1293
+ buffer_json_member_add_object(wb, "IO");
1294
+ {
1295
+ buffer_json_member_add_string(wb, "name", "IO");
1296
+ buffer_json_member_add_string(wb, "type", "stacked-bar");
1297
+ buffer_json_member_add_array(wb, "columns");
1298
+ {
1299
+ buffer_json_add_array_item_string(wb, "Read");
1300
+ buffer_json_add_array_item_string(wb, "Written");
1301
+ }
1302
+ buffer_json_array_close(wb);
1303
+ }
1304
+ buffer_json_object_close(wb);
1305
+
1306
+ buffer_json_member_add_object(wb, "Busy");
1307
+ {
1308
+ buffer_json_member_add_string(wb, "name", "Busy");
1309
+ buffer_json_member_add_string(wb, "type", "stacked-bar");
1310
+ buffer_json_member_add_array(wb, "columns");
1311
+ {
1312
+ buffer_json_add_array_item_string(wb, "Busy");
1313
+ }
1314
+ buffer_json_array_close(wb);
1315
+ }
1316
+ buffer_json_object_close(wb);
1317
+ }
1318
+ buffer_json_object_close(wb); // charts
1319
+
1320
+ buffer_json_member_add_array(wb, "default_charts");
1321
+ {
1322
+ buffer_json_add_array_item_array(wb);
1323
+ buffer_json_add_array_item_string(wb, "IO");
1324
+ buffer_json_add_array_item_string(wb, "Device");
1325
+ buffer_json_array_close(wb);
1326
+
1327
+ buffer_json_add_array_item_array(wb);
1328
+ buffer_json_add_array_item_string(wb, "Busy");
1329
+ buffer_json_add_array_item_string(wb, "Device");
1330
+ buffer_json_array_close(wb);
1331
+ }
1332
+ buffer_json_array_close(wb);
1333
+
1334
+ buffer_json_member_add_object(wb, "group_by");
1335
+ {
1336
+ buffer_json_member_add_object(wb, "Type");
1337
+ {
1338
+ buffer_json_member_add_string(wb, "name", "Type");
1339
+ buffer_json_member_add_array(wb, "columns");
1340
+ {
1341
+ buffer_json_add_array_item_string(wb, "Type");
1342
+ }
1343
+ buffer_json_array_close(wb);
1344
+ }
1345
+ buffer_json_object_close(wb);
1346
+ }
1347
+ buffer_json_object_close(wb); // group_by
1348
+
1349
+ buffer_json_member_add_time_t(wb, "expires", now_realtime_sec() + 1);
1350
+ buffer_json_finalize(wb);
1351
+
1352
+ int response = HTTP_RESP_OK;
1353
+ if(is_cancelled_cb && is_cancelled_cb(is_cancelled_cb_data)) {
1354
+ buffer_flush(wb);
1355
+ response = HTTP_RESP_CLIENT_CLOSED_REQUEST;
1356
+ }
1357
+
1358
+ if(result_cb)
1359
+ result_cb(wb, response, result_cb_data);
1360
+
1361
+ return response;
1362
+}
1363
+
1364
+static void diskstats_cleanup_disks() {
1365
+ struct disk *d = disk_root, *last = NULL;
1366
+ while (d) {
1367
+ if (unlikely(global_cleanup_removed_disks && !d->updated)) {
1368
+ struct disk *t = d;
1369
+
1370
+ rrdset_obsolete_and_pointer_null(d->st_avgsz);
1371
+ rrdset_obsolete_and_pointer_null(d->st_ext_avgsz);
1372
+ rrdset_obsolete_and_pointer_null(d->st_await);
1373
+ rrdset_obsolete_and_pointer_null(d->st_ext_await);
1374
+ rrdset_obsolete_and_pointer_null(d->st_backlog);
1375
+ rrdset_obsolete_and_pointer_null(d->st_busy);
1376
+ rrdset_obsolete_and_pointer_null(d->st_io);
1377
+ rrdset_obsolete_and_pointer_null(d->st_ext_io);
1378
+ rrdset_obsolete_and_pointer_null(d->st_iotime);
1379
+ rrdset_obsolete_and_pointer_null(d->st_ext_iotime);
1380
+ rrdset_obsolete_and_pointer_null(d->st_mops);
1381
+ rrdset_obsolete_and_pointer_null(d->st_ext_mops);
1382
+ rrdset_obsolete_and_pointer_null(d->st_ops);
1383
+ rrdset_obsolete_and_pointer_null(d->st_ext_ops);
1384
+ rrdset_obsolete_and_pointer_null(d->st_qops);
1385
+ rrdset_obsolete_and_pointer_null(d->st_svctm);
1386
+ rrdset_obsolete_and_pointer_null(d->st_util);
1387
+ rrdset_obsolete_and_pointer_null(d->st_bcache);
1388
+ rrdset_obsolete_and_pointer_null(d->st_bcache_bypass);
1389
+ rrdset_obsolete_and_pointer_null(d->st_bcache_rates);
1390
+ rrdset_obsolete_and_pointer_null(d->st_bcache_size);
1391
+ rrdset_obsolete_and_pointer_null(d->st_bcache_usage);
1392
+ rrdset_obsolete_and_pointer_null(d->st_bcache_hit_ratio);
1393
+ rrdset_obsolete_and_pointer_null(d->st_bcache_cache_allocations);
1394
+ rrdset_obsolete_and_pointer_null(d->st_bcache_cache_read_races);
1395
+
1396
+ if (d == disk_root) {
1397
+ disk_root = d = d->next;
1398
+ last = NULL;
1399
+ } else if (last) {
1400
+ last->next = d = d->next;
1401
+ }
1402
+
1403
+ freez(t->bcache_filename_dirty_data);
1404
+ freez(t->bcache_filename_writeback_rate);
1405
+ freez(t->bcache_filename_cache_congested);
1406
+ freez(t->bcache_filename_cache_available_percent);
1407
+ freez(t->bcache_filename_stats_five_minute_cache_hit_ratio);
1408
+ freez(t->bcache_filename_stats_hour_cache_hit_ratio);
1409
+ freez(t->bcache_filename_stats_day_cache_hit_ratio);
1410
+ freez(t->bcache_filename_stats_total_cache_hit_ratio);
1411
+ freez(t->bcache_filename_stats_total_cache_hits);
1412
+ freez(t->bcache_filename_stats_total_cache_misses);
1413
+ freez(t->bcache_filename_stats_total_cache_miss_collisions);
1414
+ freez(t->bcache_filename_stats_total_cache_bypass_hits);
1415
+ freez(t->bcache_filename_stats_total_cache_bypass_misses);
1416
+ freez(t->bcache_filename_stats_total_cache_readaheads);
1417
+ freez(t->bcache_filename_cache_read_races);
1418
+ freez(t->bcache_filename_cache_io_errors);
1419
+ freez(t->bcache_filename_priority_stats);
1420
+
1421
+ freez(t->disk);
1422
+ freez(t->device);
1423
+ freez(t->disk_by_id);
1424
+ freez(t->model);
1425
+ freez(t->serial);
1426
+ freez(t->mount_point);
1427
+ freez(t->chart_id);
1428
+ freez(t);
1429
+ } else {
1430
+ d->updated = 0;
1431
+ last = d;
1432
+ d = d->next;
1433
+ }
1434
}
1435
}
1436
@@ -1080,12 +1519,20 @@ int do_proc_diskstats(int update_every, usec_t dt) {
1519
ff = procfile_readall(ff);
1520
if(unlikely(!ff)) return 0; // we return 0, so that we will retry to open it next time
1521
1522
+ static bool add_func = true;
1523
+ if (add_func) {
1524
+ rrd_function_add(localhost, NULL, "block-devices", 10, RRDFUNCTIONS_DISKSTATS_HELP, true, diskstats_function_block_devices, NULL);
1525
+ add_func = false;
1526
+ }
1527
+
1528
size_t lines = procfile_lines(ff), l;
1529
1530
collected_number system_read_kb = 0, system_write_kb = 0;
1531
1532
int do_dc_stats = 0, do_fl_stats = 0;
1533
1534
+ netdata_mutex_lock(&diskstats_dev_mutex);
1535
+
1536
for(l = 0; l < lines ;l++) {
1537
// --------------------------------------------------------------------------
1538
// Read parameters
@@ -1210,7 +1657,6 @@ int do_proc_diskstats(int update_every, usec_t dt) {
1657
1658
// --------------------------------------------------------------------------
1659
// Do performance metrics
1213
-
1660
if(d->do_io == CONFIG_BOOLEAN_YES || (d->do_io == CONFIG_BOOLEAN_AUTO &&
1661
(readsectors || writesectors || discardsectors ||
1662
netdata_zero_metrics_enabled == CONFIG_BOOLEAN_YES))) {
@@ -2056,8 +2502,13 @@ int do_proc_diskstats(int update_every, usec_t dt) {
2502
rrdset_done(d->st_bcache_bypass);
2503
}
2504
}
2505
+
2506
+ d->function_ready = !d->excluded;
2507
}
2508
2509
+ diskstats_cleanup_disks();
2510
+
2511
+ netdata_mutex_unlock(&diskstats_dev_mutex);
2512
// update the system total I/O
2513
2514
if(global_do_io == CONFIG_BOOLEAN_YES || (global_do_io == CONFIG_BOOLEAN_AUTO &&
@@ -2091,80 +2542,5 @@ int do_proc_diskstats(int update_every, usec_t dt) {
2542
rrdset_done(st_io);
2543
}
2544
2094
- // cleanup removed disks
2095
-
2096
- struct disk *d = disk_root, *last = NULL;
2097
- while(d) {
2098
- if(unlikely(global_cleanup_removed_disks && !d->updated)) {
2099
- struct disk *t = d;
2100
-
2101
- rrdset_obsolete_and_pointer_null(d->st_avgsz);
2102
- rrdset_obsolete_and_pointer_null(d->st_ext_avgsz);
2103
- rrdset_obsolete_and_pointer_null(d->st_await);
2104
- rrdset_obsolete_and_pointer_null(d->st_ext_await);
2105
- rrdset_obsolete_and_pointer_null(d->st_backlog);
2106
- rrdset_obsolete_and_pointer_null(d->st_busy);
2107
- rrdset_obsolete_and_pointer_null(d->st_io);
2108
- rrdset_obsolete_and_pointer_null(d->st_ext_io);
2109
- rrdset_obsolete_and_pointer_null(d->st_iotime);
2110
- rrdset_obsolete_and_pointer_null(d->st_ext_iotime);
2111
- rrdset_obsolete_and_pointer_null(d->st_mops);
2112
- rrdset_obsolete_and_pointer_null(d->st_ext_mops);
2113
- rrdset_obsolete_and_pointer_null(d->st_ops);
2114
- rrdset_obsolete_and_pointer_null(d->st_ext_ops);
2115
- rrdset_obsolete_and_pointer_null(d->st_qops);
2116
- rrdset_obsolete_and_pointer_null(d->st_svctm);
2117
- rrdset_obsolete_and_pointer_null(d->st_util);
2118
- rrdset_obsolete_and_pointer_null(d->st_bcache);
2119
- rrdset_obsolete_and_pointer_null(d->st_bcache_bypass);
2120
- rrdset_obsolete_and_pointer_null(d->st_bcache_rates);
2121
- rrdset_obsolete_and_pointer_null(d->st_bcache_size);
2122
- rrdset_obsolete_and_pointer_null(d->st_bcache_usage);
2123
- rrdset_obsolete_and_pointer_null(d->st_bcache_hit_ratio);
2124
- rrdset_obsolete_and_pointer_null(d->st_bcache_cache_allocations);
2125
- rrdset_obsolete_and_pointer_null(d->st_bcache_cache_read_races);
2126
-
2127
- if(d == disk_root) {
2128
- disk_root = d = d->next;
2129
- last = NULL;
2130
- }
2131
- else if(last) {
2132
- last->next = d = d->next;
2133
- }
2134
-
2135
- freez(t->bcache_filename_dirty_data);
2136
- freez(t->bcache_filename_writeback_rate);
2137
- freez(t->bcache_filename_cache_congested);
2138
- freez(t->bcache_filename_cache_available_percent);
2139
- freez(t->bcache_filename_stats_five_minute_cache_hit_ratio);
2140
- freez(t->bcache_filename_stats_hour_cache_hit_ratio);
2141
- freez(t->bcache_filename_stats_day_cache_hit_ratio);
2142
- freez(t->bcache_filename_stats_total_cache_hit_ratio);
2143
- freez(t->bcache_filename_stats_total_cache_hits);
2144
- freez(t->bcache_filename_stats_total_cache_misses);
2145
- freez(t->bcache_filename_stats_total_cache_miss_collisions);
2146
- freez(t->bcache_filename_stats_total_cache_bypass_hits);
2147
- freez(t->bcache_filename_stats_total_cache_bypass_misses);
2148
- freez(t->bcache_filename_stats_total_cache_readaheads);
2149
- freez(t->bcache_filename_cache_read_races);
2150
- freez(t->bcache_filename_cache_io_errors);
2151
- freez(t->bcache_filename_priority_stats);
2152
-
2153
- freez(t->disk);
2154
- freez(t->device);
2155
- freez(t->disk_by_id);
2156
- freez(t->model);
2157
- freez(t->serial);
2158
- freez(t->mount_point);
2159
- freez(t->chart_id);
2160
- freez(t);
2161
- }
2162
- else {
2163
- d->updated = 0;
2164
- last = d;
2165
- d = d->next;
2166
- }
2167
- }
2168
-
2545
return 0;
2546
}