Self-cleaning obsolete disks in FreeBSD plugin
Vladimir Kobal committed
Mar 30, 2017 at 16:38 UTC
91a03b04bc6dfdc0f69cb1825096a5730b7b1929
4 files changed
+664
-603
CMakeLists.txt
+1
@@ -31,6 +31,7 @@ set(NETDATA_SOURCE_FILES
31
src/freebsd_sysctl.c
32
src/freebsd_getmntinfo.c
33
src/freebsd_getifaddrs.c
34
+ src/freebsd_devstat.c
35
src/global_statistics.c
36
src/global_statistics.h
37
src/health.c
src/Makefile.am
+1
@@ -148,6 +148,7 @@ netdata_SOURCES += \
148
freebsd_sysctl.c \
149
freebsd_getmntinfo.c \
150
freebsd_getifaddrs.c \
151
+ freebsd_devstat.c \
152
$(NULL)
153
else
154
if MACOS
src/freebsd_devstat.c
new
+662
@@ -0,0 +1,662 @@
1
+#include "common.h"
2
+
3
+#include <sys/devicestat.h>
4
+
5
+struct disk {
6
+ char *name;
7
+ uint32_t hash;
8
+ size_t len;
9
+
10
+ // flags
11
+ int configured;
12
+ int enabled;
13
+ int updated;
14
+
15
+ int do_io;
16
+ int do_ops;
17
+ int do_qops;
18
+ int do_util;
19
+ int do_iotime;
20
+ int do_await;
21
+ int do_avagsz;
22
+ int do_svctm;
23
+
24
+
25
+ // data for differential charts
26
+
27
+ struct prev_dstat {
28
+ collected_number bytes_read;
29
+ collected_number bytes_write;
30
+ collected_number operations_read;
31
+ collected_number operations_write;
32
+ collected_number duration_read_ms;
33
+ collected_number duration_write_ms;
34
+ collected_number busy_time_ms;
35
+ } prev_dstat;
36
+
37
+ // charts and dimensions
38
+
39
+ RRDSET *st_io;
40
+ RRDDIM *rd_io_in;
41
+ RRDDIM *rd_io_out;
42
+
43
+ RRDSET *st_ops;
44
+ RRDDIM *rd_ops_in;
45
+ RRDDIM *rd_ops_out;
46
+
47
+ RRDSET *st_qops;
48
+ RRDDIM *rd_qops;
49
+
50
+ RRDSET *st_util;
51
+ RRDDIM *rd_util;
52
+
53
+ RRDSET *st_iotime;
54
+ RRDDIM *rd_iotime_in;
55
+ RRDDIM *rd_iotime_out;
56
+
57
+ RRDSET *st_await;
58
+ RRDDIM *rd_await_in;
59
+ RRDDIM *rd_await_out;
60
+
61
+ RRDSET *st_avagsz;
62
+ RRDDIM *rd_avagsz_in;
63
+ RRDDIM *rd_avagsz_out;
64
+
65
+ RRDSET *st_svctm;
66
+ RRDDIM *rd_svctm;
67
+
68
+ struct disk *next;
69
+};
70
+
71
+static struct disk *disks_root = NULL, *disks_last_used = NULL;
72
+
73
+static size_t disks_added = 0, disks_found = 0;
74
+
75
+static void disk_free(struct disk *dm) {
76
+ if (likely(dm->st_io))
77
+ rrdset_flag_set(dm->st_io, RRDSET_FLAG_OBSOLETE);
78
+ if (likely(dm->st_ops))
79
+ rrdset_flag_set(dm->st_ops, RRDSET_FLAG_OBSOLETE);
80
+ if (likely(dm->st_qops))
81
+ rrdset_flag_set(dm->st_qops, RRDSET_FLAG_OBSOLETE);
82
+ if (likely(dm->st_util))
83
+ rrdset_flag_set(dm->st_util, RRDSET_FLAG_OBSOLETE);
84
+ if (likely(dm->st_iotime))
85
+ rrdset_flag_set(dm->st_iotime, RRDSET_FLAG_OBSOLETE);
86
+ if (likely(dm->st_await))
87
+ rrdset_flag_set(dm->st_await, RRDSET_FLAG_OBSOLETE);
88
+ if (likely(dm->st_avagsz))
89
+ rrdset_flag_set(dm->st_avagsz, RRDSET_FLAG_OBSOLETE);
90
+ if (likely(dm->st_svctm))
91
+ rrdset_flag_set(dm->st_svctm, RRDSET_FLAG_OBSOLETE);
92
+
93
+ disks_added--;
94
+ freez(dm->name);
95
+ freez(dm);
96
+}
97
+
98
+static void disks_cleanup() {
99
+ if (likely(disks_found == disks_added)) return;
100
+
101
+ struct disk *dm = disks_root, *last = NULL;
102
+ while(dm) {
103
+ if (unlikely(!dm->updated)) {
104
+ // info("Removing disk '%s', linked after '%s'", dm->name, last?last->name:"ROOT");
105
+
106
+ if (disks_last_used == dm)
107
+ disks_last_used = last;
108
+
109
+ struct disk *t = dm;
110
+
111
+ if (dm == disks_root || !last)
112
+ disks_root = dm = dm->next;
113
+
114
+ else
115
+ last->next = dm = dm->next;
116
+
117
+ t->next = NULL;
118
+ disk_free(t);
119
+ }
120
+ else {
121
+ last = dm;
122
+ dm->updated = 0;
123
+ dm = dm->next;
124
+ }
125
+ }
126
+}
127
+
128
+static struct disk *get_disk(const char *name) {
129
+ struct disk *dm;
130
+
131
+ uint32_t hash = simple_hash(name);
132
+
133
+ // search it, from the last position to the end
134
+ for(dm = disks_last_used ; dm ; dm = dm->next) {
135
+ if (unlikely(hash == dm->hash && !strcmp(name, dm->name))) {
136
+ disks_last_used = dm->next;
137
+ return dm;
138
+ }
139
+ }
140
+
141
+ // search it from the beginning to the last position we used
142
+ for(dm = disks_root ; dm != disks_last_used ; dm = dm->next) {
143
+ if (unlikely(hash == dm->hash && !strcmp(name, dm->name))) {
144
+ disks_last_used = dm->next;
145
+ return dm;
146
+ }
147
+ }
148
+
149
+ // create a new one
150
+ dm = callocz(1, sizeof(struct disk));
151
+ dm->name = strdupz(name);
152
+ dm->hash = simple_hash(dm->name);
153
+ dm->len = strlen(dm->name);
154
+ disks_added++;
155
+
156
+ // link it to the end
157
+ if (disks_root) {
158
+ struct disk *e;
159
+ for(e = disks_root; e->next ; e = e->next) ;
160
+ e->next = dm;
161
+ }
162
+ else
163
+ disks_root = dm;
164
+
165
+ return dm;
166
+}
167
+
168
+// --------------------------------------------------------------------------------------------------------------------
169
+// kern.devstat
170
+
171
+int do_kern_devstat(int update_every, usec_t dt) {
172
+
173
+#define DELAULT_EXLUDED_DISKS ""
174
+#define CONFIG_SECTION_KERN_DEVSTAT "plugin:freebsd:kern.devstat"
175
+#define BINTIME_SCALE 5.42101086242752217003726400434970855712890625e-17 // this is 1000/2^64
176
+
177
+ static int enable_new_disks = -1;
178
+ static int enable_pass_devices = -1, do_system_io = -1, do_io = -1, do_ops = -1, do_qops = -1, do_util = -1,
179
+ do_iotime = -1, do_await = -1, do_avagsz = -1, do_svctm = -1;
180
+ static SIMPLE_PATTERN *excluded_disks = NULL;
181
+
182
+ if (unlikely(enable_new_disks == -1)) {
183
+ enable_new_disks = config_get_boolean_ondemand(CONFIG_SECTION_KERN_DEVSTAT,
184
+ "enable new disks detected at runtime", CONFIG_BOOLEAN_AUTO);
185
+
186
+ enable_pass_devices = config_get_boolean_ondemand(CONFIG_SECTION_KERN_DEVSTAT,
187
+ "performance metrics for pass devices", CONFIG_BOOLEAN_AUTO);
188
+
189
+ do_system_io = config_get_boolean_ondemand(CONFIG_SECTION_KERN_DEVSTAT, "total bandwidth for all disks",
190
+ CONFIG_BOOLEAN_YES);
191
+
192
+ do_io = config_get_boolean_ondemand(CONFIG_SECTION_KERN_DEVSTAT, "bandwidth for all disks",
193
+ CONFIG_BOOLEAN_AUTO);
194
+ do_ops = config_get_boolean_ondemand(CONFIG_SECTION_KERN_DEVSTAT, "operations for all disks",
195
+ CONFIG_BOOLEAN_AUTO);
196
+ do_qops = config_get_boolean_ondemand(CONFIG_SECTION_KERN_DEVSTAT, "queued operations for all disks",
197
+ CONFIG_BOOLEAN_AUTO);
198
+ do_util = config_get_boolean_ondemand(CONFIG_SECTION_KERN_DEVSTAT, "utilization percentage for all disks",
199
+ CONFIG_BOOLEAN_AUTO);
200
+ do_iotime = config_get_boolean_ondemand(CONFIG_SECTION_KERN_DEVSTAT, "i/o time for all disks",
201
+ CONFIG_BOOLEAN_AUTO);
202
+ do_await = config_get_boolean_ondemand(CONFIG_SECTION_KERN_DEVSTAT, "average completed i/o time for all disks",
203
+ CONFIG_BOOLEAN_AUTO);
204
+ do_avagsz = config_get_boolean_ondemand(CONFIG_SECTION_KERN_DEVSTAT, "average completed i/o bandwidth for all disks",
205
+ CONFIG_BOOLEAN_AUTO);
206
+ do_svctm = config_get_boolean_ondemand(CONFIG_SECTION_KERN_DEVSTAT, "average service time for all disks",
207
+ CONFIG_BOOLEAN_AUTO);
208
+
209
+ excluded_disks = simple_pattern_create(
210
+ config_get(CONFIG_SECTION_KERN_DEVSTAT, "disable by default disks matching", DELAULT_EXLUDED_DISKS)
211
+ , SIMPLE_PATTERN_EXACT
212
+ );
213
+ }
214
+
215
+ if (likely(do_system_io || do_io || do_ops || do_qops || do_util || do_iotime || do_await || do_avagsz || do_svctm)) {
216
+ static int mib_numdevs[3] = {0, 0, 0};
217
+ int numdevs;
218
+ int common_error = 0;
219
+
220
+ if (unlikely(GETSYSCTL_SIMPLE("kern.devstat.numdevs", mib_numdevs, numdevs))) {
221
+ common_error = 1;
222
+ } else {
223
+ static int mib_devstat[3] = {0, 0, 0};
224
+ static void *devstat_data = NULL;
225
+ static int old_numdevs = 0;
226
+
227
+ if (unlikely(numdevs != old_numdevs)) {
228
+ devstat_data = reallocz(devstat_data, sizeof(long) + sizeof(struct devstat) *
229
+ numdevs); // there is generation number before devstat structures
230
+ old_numdevs = numdevs;
231
+ }
232
+ if (unlikely(GETSYSCTL_WSIZE("kern.devstat.all", mib_devstat, devstat_data,
233
+ sizeof(long) + sizeof(struct devstat) * numdevs))) {
234
+ common_error = 1;
235
+ } else {
236
+ struct devstat *dstat;
237
+ int i;
238
+ collected_number total_disk_kbytes_read = 0;
239
+ collected_number total_disk_kbytes_write = 0;
240
+
241
+ disks_found = 0;
242
+
243
+ dstat = devstat_data + sizeof(long); // skip generation number
244
+
245
+ for (i = 0; i < numdevs; i++) {
246
+ if (likely(do_system_io)) {
247
+ if (((dstat[i].device_type & DEVSTAT_TYPE_MASK) == DEVSTAT_TYPE_DIRECT) || ((dstat[i].device_type & DEVSTAT_TYPE_MASK) == DEVSTAT_TYPE_STORARRAY)) {
248
+ total_disk_kbytes_read += dstat[i].bytes[DEVSTAT_READ] / KILO_FACTOR;
249
+ total_disk_kbytes_write += dstat[i].bytes[DEVSTAT_WRITE] / KILO_FACTOR;
250
+ }
251
+ }
252
+
253
+ if (unlikely(!enable_pass_devices))
254
+ if ((dstat[i].device_type & DEVSTAT_TYPE_PASS) == DEVSTAT_TYPE_PASS)
255
+ continue;
256
+
257
+ if (((dstat[i].device_type & DEVSTAT_TYPE_MASK) == DEVSTAT_TYPE_DIRECT) || ((dstat[i].device_type & DEVSTAT_TYPE_MASK) == DEVSTAT_TYPE_STORARRAY)) {
258
+ char disk[DEVSTAT_NAME_LEN + MAX_INT_DIGITS + 1];
259
+ struct cur_dstat {
260
+ collected_number duration_read_ms;
261
+ collected_number duration_write_ms;
262
+ collected_number busy_time_ms;
263
+ } cur_dstat;
264
+
265
+ sprintf(disk, "%s%d", dstat[i].device_name, dstat[i].unit_number);
266
+
267
+ struct disk *dm = get_disk(disk);
268
+ dm->updated = 1;
269
+ disks_found++;
270
+
271
+ if(unlikely(!dm->configured)) {
272
+ char var_name[4096 + 1];
273
+
274
+ // this is the first time we see this disk
275
+
276
+ // remember we configured it
277
+ dm->configured = 1;
278
+
279
+ dm->enabled = enable_new_disks;
280
+
281
+ if (likely(dm->enabled))
282
+ dm->enabled = !simple_pattern_matches(excluded_disks, disk);
283
+
284
+ snprintfz(var_name, 4096, "%s:%s", CONFIG_SECTION_KERN_DEVSTAT, disk);
285
+ dm->enabled = config_get_boolean_ondemand(var_name, "enabled", dm->enabled);
286
+
287
+ dm->do_io = config_get_boolean_ondemand(var_name, "bandwidth", do_io);
288
+ dm->do_ops = config_get_boolean_ondemand(var_name, "operations", do_ops);
289
+ dm->do_qops = config_get_boolean_ondemand(var_name, "queued operations", do_qops);
290
+ dm->do_util = config_get_boolean_ondemand(var_name, "utilization percentage", do_util);
291
+ dm->do_iotime = config_get_boolean_ondemand(var_name, "i/o time", do_iotime);
292
+ dm->do_await = config_get_boolean_ondemand(var_name, "average completed i/o time",
293
+ do_await);
294
+ dm->do_avagsz = config_get_boolean_ondemand(var_name, "average completed i/o bandwidth",
295
+ do_avagsz);
296
+ dm->do_svctm = config_get_boolean_ondemand(var_name, "average service time", do_svctm);
297
+
298
+ // initialise data for differential charts
299
+
300
+ dm->prev_dstat.bytes_read = dstat[i].bytes[DEVSTAT_READ];
301
+ dm->prev_dstat.bytes_write = dstat[i].bytes[DEVSTAT_WRITE];
302
+ dm->prev_dstat.operations_read = dstat[i].operations[DEVSTAT_READ];
303
+ dm->prev_dstat.operations_write = dstat[i].operations[DEVSTAT_WRITE];
304
+ dm->prev_dstat.duration_read_ms = dstat[i].duration[DEVSTAT_READ].sec * 1000
305
+ + dstat[i].duration[DEVSTAT_READ].frac * BINTIME_SCALE;
306
+ dm->prev_dstat.duration_write_ms = dstat[i].duration[DEVSTAT_WRITE].sec * 1000
307
+ + dstat[i].duration[DEVSTAT_READ].frac * BINTIME_SCALE;
308
+ dm->prev_dstat.busy_time_ms = dstat[i].busy_time.sec * 1000
309
+ + dstat[i].busy_time.frac * BINTIME_SCALE;
310
+ }
311
+
312
+ cur_dstat.duration_read_ms = dstat[i].duration[DEVSTAT_READ].sec * 1000
313
+ + dstat[i].duration[DEVSTAT_READ].frac * BINTIME_SCALE;
314
+ cur_dstat.duration_write_ms = dstat[i].duration[DEVSTAT_WRITE].sec * 1000
315
+ + dstat[i].duration[DEVSTAT_READ].frac * BINTIME_SCALE;
316
+ cur_dstat.busy_time_ms = dstat[i].busy_time.sec * 1000 + dstat[i].busy_time.frac * BINTIME_SCALE;
317
+
318
+ // --------------------------------------------------------------------
319
+
320
+ if(dm->do_io == CONFIG_BOOLEAN_YES || (dm->do_io == CONFIG_BOOLEAN_AUTO &&
321
+ (dstat[i].bytes[DEVSTAT_READ] || dstat[i].bytes[DEVSTAT_WRITE]))) {
322
+ if (unlikely(!dm->st_io)) {
323
+ dm->st_io = rrdset_create_localhost("disk",
324
+ disk,
325
+ NULL,
326
+ disk,
327
+ "disk.io",
328
+ "Disk I/O Bandwidth",
329
+ "kilobytes/s",
330
+ 2000,
331
+ update_every,
332
+ RRDSET_TYPE_AREA
333
+ );
334
+
335
+ dm->rd_io_in = rrddim_add(dm->st_io, "reads", NULL, 1, KILO_FACTOR,
336
+ RRD_ALGORITHM_INCREMENTAL);
337
+ dm->rd_io_out = rrddim_add(dm->st_io, "writes", NULL, -1, KILO_FACTOR,
338
+ RRD_ALGORITHM_INCREMENTAL);
339
+ } else
340
+ rrdset_next(dm->st_io);
341
+
342
+ rrddim_set_by_pointer(dm->st_io, dm->rd_io_in, dstat[i].bytes[DEVSTAT_READ]);
343
+ rrddim_set_by_pointer(dm->st_io, dm->rd_io_out, dstat[i].bytes[DEVSTAT_WRITE]);
344
+ rrdset_done(dm->st_io);
345
+ }
346
+
347
+ // --------------------------------------------------------------------
348
+
349
+ if(dm->do_ops == CONFIG_BOOLEAN_YES || (dm->do_ops == CONFIG_BOOLEAN_AUTO &&
350
+ (dstat[i].operations[DEVSTAT_READ] || dstat[i].operations[DEVSTAT_WRITE]))) {
351
+ if (unlikely(!dm->st_ops)) {
352
+ dm->st_ops = rrdset_create_localhost("disk_ops",
353
+ disk,
354
+ NULL,
355
+ disk,
356
+ "disk.ops",
357
+ "Disk Completed I/O Operations",
358
+ "operations/s",
359
+ 2001,
360
+ update_every,
361
+ RRDSET_TYPE_LINE
362
+ );
363
+
364
+ rrdset_flag_set(dm->st_ops, RRDSET_FLAG_DETAIL);
365
+
366
+ dm->rd_ops_in = rrddim_add(dm->st_ops, "reads", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
367
+ dm->rd_ops_out = rrddim_add(dm->st_ops, "writes", NULL, -1, 1,
368
+ RRD_ALGORITHM_INCREMENTAL);
369
+ } else
370
+ rrdset_next(dm->st_ops);
371
+
372
+ rrddim_set_by_pointer(dm->st_ops, dm->rd_ops_in, dstat[i].operations[DEVSTAT_READ]);
373
+ rrddim_set_by_pointer(dm->st_ops, dm->rd_ops_out, dstat[i].operations[DEVSTAT_WRITE]);
374
+ rrdset_done(dm->st_ops);
375
+ }
376
+
377
+ // --------------------------------------------------------------------
378
+
379
+ if(dm->do_qops == CONFIG_BOOLEAN_YES || (dm->do_qops == CONFIG_BOOLEAN_AUTO &&
380
+ (dstat[i].start_count || dstat[i].end_count))) {
381
+ if (unlikely(!dm->st_qops)) {
382
+ dm->st_qops = rrdset_create_localhost("disk_qops",
383
+ disk,
384
+ NULL,
385
+ disk,
386
+ "disk.qops",
387
+ "Disk Current I/O Operations",
388
+ "operations",
389
+ 2002,
390
+ update_every,
391
+ RRDSET_TYPE_LINE
392
+ );
393
+
394
+ rrdset_flag_set(dm->st_qops, RRDSET_FLAG_DETAIL);
395
+
396
+ dm->rd_qops = rrddim_add(dm->st_qops, "operations", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE);
397
+ } else
398
+ rrdset_next(dm->st_qops);
399
+
400
+ rrddim_set_by_pointer(dm->st_qops, dm->rd_qops, dstat[i].start_count - dstat[i].end_count);
401
+ rrdset_done(dm->st_qops);
402
+ }
403
+
404
+ // --------------------------------------------------------------------
405
+
406
+ if(dm->do_util == CONFIG_BOOLEAN_YES || (dm->do_util == CONFIG_BOOLEAN_AUTO &&
407
+ cur_dstat.busy_time_ms)) {
408
+ if (unlikely(!dm->st_util)) {
409
+ dm->st_util = rrdset_create_localhost("disk_util",
410
+ disk,
411
+ NULL,
412
+ disk,
413
+ "disk.util",
414
+ "Disk Utilization Time",
415
+ "% of time working",
416
+ 2004,
417
+ update_every,
418
+ RRDSET_TYPE_AREA
419
+ );
420
+
421
+ rrdset_flag_set(dm->st_util, RRDSET_FLAG_DETAIL);
422
+
423
+ dm->rd_util = rrddim_add(dm->st_util, "utilization", NULL, 1, 10,
424
+ RRD_ALGORITHM_INCREMENTAL);
425
+ } else
426
+ rrdset_next(dm->st_util);
427
+
428
+ rrddim_set_by_pointer(dm->st_util, dm->rd_util, cur_dstat.busy_time_ms);
429
+ rrdset_done(dm->st_util);
430
+ }
431
+
432
+ // --------------------------------------------------------------------
433
+
434
+ if(dm->do_iotime == CONFIG_BOOLEAN_YES || (dm->do_iotime == CONFIG_BOOLEAN_AUTO &&
435
+ (cur_dstat.duration_read_ms || cur_dstat.duration_write_ms))) {
436
+ if (unlikely(!dm->st_iotime)) {
437
+ dm->st_iotime = rrdset_create_localhost("disk_iotime",
438
+ disk,
439
+ NULL,
440
+ disk,
441
+ "disk.iotime",
442
+ "Disk Total I/O Time",
443
+ "milliseconds/s",
444
+ 2022,
445
+ update_every,
446
+ RRDSET_TYPE_LINE
447
+ );
448
+
449
+ rrdset_flag_set(dm->st_iotime, RRDSET_FLAG_DETAIL);
450
+
451
+ dm->rd_iotime_in = rrddim_add(dm->st_iotime, "reads", NULL, 1, 1,
452
+ RRD_ALGORITHM_INCREMENTAL);
453
+ dm->rd_iotime_out = rrddim_add(dm->st_iotime, "writes", NULL, -1, 1,
454
+ RRD_ALGORITHM_INCREMENTAL);
455
+ } else
456
+ rrdset_next(dm->st_iotime);
457
+
458
+ rrddim_set_by_pointer(dm->st_iotime, dm->rd_iotime_in, cur_dstat.duration_read_ms);
459
+ rrddim_set_by_pointer(dm->st_iotime, dm->rd_iotime_out, cur_dstat.duration_write_ms);
460
+ rrdset_done(dm->st_iotime);
461
+ }
462
+
463
+ // --------------------------------------------------------------------
464
+ // calculate differential charts
465
+ // only if this is not the first time we run
466
+
467
+ if (likely(dt)) {
468
+
469
+ // --------------------------------------------------------------------
470
+
471
+ if(dm->do_await == CONFIG_BOOLEAN_YES || (dm->do_await == CONFIG_BOOLEAN_AUTO &&
472
+ (dstat[i].operations[DEVSTAT_READ] || dstat[i].operations[DEVSTAT_WRITE]))) {
473
+ if (unlikely(!dm->st_await)) {
474
+ dm->st_await = rrdset_create_localhost("disk_await",
475
+ disk,
476
+ NULL,
477
+ disk,
478
+ "disk.await",
479
+ "Average Completed I/O Operation Time",
480
+ "ms per operation",
481
+ 2005,
482
+ update_every,
483
+ RRDSET_TYPE_LINE
484
+ );
485
+
486
+ rrdset_flag_set(dm->st_await, RRDSET_FLAG_DETAIL);
487
+
488
+ dm->rd_await_in = rrddim_add(dm->st_await, "reads", NULL, 1, 1,
489
+ RRD_ALGORITHM_ABSOLUTE);
490
+ dm->rd_await_out = rrddim_add(dm->st_await, "writes", NULL, -1, 1,
491
+ RRD_ALGORITHM_ABSOLUTE);
492
+ } else
493
+ rrdset_next(dm->st_await);
494
+
495
+ rrddim_set_by_pointer(dm->st_await, dm->rd_await_in,
496
+ (dstat[i].operations[DEVSTAT_READ] -
497
+ dm->prev_dstat.operations_read) ?
498
+ (cur_dstat.duration_read_ms - dm->prev_dstat.duration_read_ms) /
499
+ (dstat[i].operations[DEVSTAT_READ] -
500
+ dm->prev_dstat.operations_read) :
501
+ 0);
502
+ rrddim_set_by_pointer(dm->st_await, dm->rd_await_out,
503
+ (dstat[i].operations[DEVSTAT_WRITE] -
504
+ dm->prev_dstat.operations_write) ?
505
+ (cur_dstat.duration_write_ms - dm->prev_dstat.duration_write_ms) /
506
+ (dstat[i].operations[DEVSTAT_WRITE] -
507
+ dm->prev_dstat.operations_write) :
508
+ 0);
509
+ rrdset_done(dm->st_await);
510
+ }
511
+
512
+ // --------------------------------------------------------------------
513
+
514
+ if(dm->do_avagsz == CONFIG_BOOLEAN_YES || (dm->do_avagsz == CONFIG_BOOLEAN_AUTO &&
515
+ (dstat[i].operations[DEVSTAT_READ] || dstat[i].operations[DEVSTAT_WRITE]))) {
516
+ if (unlikely(!dm->st_avagsz)) {
517
+ dm->st_avagsz = rrdset_create_localhost("disk_avgsz",
518
+ disk,
519
+ NULL,
520
+ disk,
521
+ "disk.avgsz",
522
+ "Average Completed I/O Operation Bandwidth",
523
+ "kilobytes per operation",
524
+ 2006,
525
+ update_every,
526
+ RRDSET_TYPE_AREA
527
+ );
528
+
529
+ rrdset_flag_set(dm->st_avagsz, RRDSET_FLAG_DETAIL);
530
+
531
+ dm->rd_avagsz_in = rrddim_add(dm->st_avagsz, "reads", NULL, 1, KILO_FACTOR,
532
+ RRD_ALGORITHM_ABSOLUTE);
533
+ dm->rd_avagsz_out = rrddim_add(dm->st_avagsz, "writes", NULL, -1, KILO_FACTOR,
534
+ RRD_ALGORITHM_ABSOLUTE);
535
+ } else
536
+ rrdset_next(dm->st_avagsz);
537
+
538
+ rrddim_set_by_pointer(dm->st_avagsz, dm->rd_avagsz_in,
539
+ (dstat[i].operations[DEVSTAT_READ] -
540
+ dm->prev_dstat.operations_read) ?
541
+ (dstat[i].bytes[DEVSTAT_READ] - dm->prev_dstat.bytes_read) /
542
+ (dstat[i].operations[DEVSTAT_READ] -
543
+ dm->prev_dstat.operations_read) :
544
+ 0);
545
+ rrddim_set_by_pointer(dm->st_avagsz, dm->rd_avagsz_out,
546
+ (dstat[i].operations[DEVSTAT_WRITE] -
547
+ dm->prev_dstat.operations_write) ?
548
+ (dstat[i].bytes[DEVSTAT_WRITE] - dm->prev_dstat.bytes_write) /
549
+ (dstat[i].operations[DEVSTAT_WRITE] -
550
+ dm->prev_dstat.operations_write) :
551
+ 0);
552
+ rrdset_done(dm->st_avagsz);
553
+ }
554
+
555
+ // --------------------------------------------------------------------
556
+
557
+ if(dm->do_svctm == CONFIG_BOOLEAN_YES || (dm->do_svctm == CONFIG_BOOLEAN_AUTO &&
558
+ (dstat[i].operations[DEVSTAT_READ] || dstat[i].operations[DEVSTAT_WRITE]))) {
559
+ if (unlikely(!dm->st_svctm)) {
560
+ dm->st_svctm = rrdset_create_localhost("disk_svctm",
561
+ disk,
562
+ NULL,
563
+ disk,
564
+ "disk.svctm",
565
+ "Average Service Time",
566
+ "ms per operation",
567
+ 2007,
568
+ update_every,
569
+ RRDSET_TYPE_LINE
570
+ );
571
+
572
+ rrdset_flag_set(dm->st_svctm, RRDSET_FLAG_DETAIL);
573
+
574
+ dm->rd_svctm = rrddim_add(dm->st_svctm, "svctm", NULL, 1, 1,
575
+ RRD_ALGORITHM_ABSOLUTE);
576
+ } else
577
+ rrdset_next(dm->st_svctm);
578
+
579
+ rrddim_set_by_pointer(dm->st_svctm, dm->rd_svctm,
580
+ ((dstat[i].operations[DEVSTAT_READ] - dm->prev_dstat.operations_read) +
581
+ (dstat[i].operations[DEVSTAT_WRITE] - dm->prev_dstat.operations_write)) ?
582
+ (cur_dstat.busy_time_ms - dm->prev_dstat.busy_time_ms) /
583
+ ((dstat[i].operations[DEVSTAT_READ] - dm->prev_dstat.operations_read) +
584
+ (dstat[i].operations[DEVSTAT_WRITE] - dm->prev_dstat.operations_write)) :
585
+ 0);
586
+ rrdset_done(dm->st_svctm);
587
+ }
588
+
589
+ // --------------------------------------------------------------------
590
+
591
+ dm->prev_dstat.bytes_read = dstat[i].bytes[DEVSTAT_READ];
592
+ dm->prev_dstat.bytes_write = dstat[i].bytes[DEVSTAT_WRITE];
593
+ dm->prev_dstat.operations_read = dstat[i].operations[DEVSTAT_READ];
594
+ dm->prev_dstat.operations_write = dstat[i].operations[DEVSTAT_WRITE];
595
+ dm->prev_dstat.duration_read_ms = cur_dstat.duration_read_ms;
596
+ dm->prev_dstat.duration_write_ms = cur_dstat.duration_write_ms;
597
+ dm->prev_dstat.busy_time_ms = cur_dstat.busy_time_ms;
598
+ }
599
+ }
600
+ }
601
+
602
+ // --------------------------------------------------------------------
603
+
604
+ if (likely(do_system_io)) {
605
+ static RRDSET *st = NULL;
606
+ static RRDDIM *rd_in = NULL, *rd_out = NULL;
607
+
608
+ if (unlikely(!st)) {
609
+ st = rrdset_create_localhost("system",
610
+ "io",
611
+ NULL,
612
+ "disk",
613
+ NULL,
614
+ "Disk I/O",
615
+ "kilobytes/s",
616
+ 150,
617
+ update_every,
618
+ RRDSET_TYPE_AREA
619
+ );
620
+
621
+ rd_in = rrddim_add(st, "in", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
622
+ rd_out = rrddim_add(st, "out", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL);
623
+ } else
624
+ rrdset_next(st);
625
+
626
+ rrddim_set_by_pointer(st, rd_in, total_disk_kbytes_read);
627
+ rrddim_set_by_pointer(st, rd_out, total_disk_kbytes_write);
628
+ rrdset_done(st);
629
+ }
630
+ }
631
+ }
632
+ if (unlikely(common_error)) {
633
+ do_system_io = 0;
634
+ error("DISABLED: system.io chart");
635
+ do_io = 0;
636
+ error("DISABLED: disk.* charts");
637
+ do_ops = 0;
638
+ error("DISABLED: disk_ops.* charts");
639
+ do_qops = 0;
640
+ error("DISABLED: disk_qops.* charts");
641
+ do_util = 0;
642
+ error("DISABLED: disk_util.* charts");
643
+ do_iotime = 0;
644
+ error("DISABLED: disk_iotime.* charts");
645
+ do_await = 0;
646
+ error("DISABLED: disk_await.* charts");
647
+ do_avagsz = 0;
648
+ error("DISABLED: disk_avgsz.* charts");
649
+ do_svctm = 0;
650
+ error("DISABLED: disk_svctm.* charts");
651
+ error("DISABLED: kern.devstat module");
652
+ return 1;
653
+ }
654
+ } else {
655
+ error("DISABLED: kern.devstat module");
656
+ return 1;
657
+ }
658
+
659
+ disks_cleanup();
660
+
661
+ return 0;
662
+}
src/freebsd_sysctl.c
-603
@@ -1,7 +1,6 @@
1
#include "common.h"
2
3
#include <sys/vmmeter.h>
4
-#include <sys/devicestat.h>
4
#include <vm/vm_param.h>
5
6
#define _KERNEL
@@ -11,7 +10,6 @@
10
#undef _KERNEL
11
12
#include <net/netisr.h>
14
-#include <net/if.h>
13
14
#include <netinet/ip.h>
15
#include <netinet/ip_var.h>
@@ -2775,604 +2773,3 @@ int do_net_inet6_icmp6_stats(int update_every, usec_t dt) {
2773
2774
return 0;
2775
}
2778
-
2779
-// --------------------------------------------------------------------------------------------------------------------
2780
-// kern.devstat
2781
-
2782
-int do_kern_devstat(int update_every, usec_t dt) {
2783
-
2784
-#define DELAULT_EXLUDED_DISKS ""
2785
-#define CONFIG_SECTION_KERN_DEVSTAT "plugin:freebsd:kern.devstat"
2786
-#define BINTIME_SCALE 5.42101086242752217003726400434970855712890625e-17 // this is 1000/2^64
2787
-
2788
- static int enable_pass_devices = -1, do_system_io = -1, do_io = -1, do_ops = -1, do_qops = -1, do_util = -1,
2789
- do_iotime = -1, do_await = -1, do_avagsz = -1, do_svctm = -1;
2790
-
2791
- if (unlikely(enable_pass_devices == -1)) {
2792
- enable_pass_devices = config_get_boolean_ondemand(CONFIG_SECTION_KERN_DEVSTAT,
2793
- "performance metrics for pass devices", CONFIG_BOOLEAN_AUTO);
2794
-
2795
- do_system_io = config_get_boolean_ondemand(CONFIG_SECTION_KERN_DEVSTAT, "total bandwidth for all disks",
2796
- CONFIG_BOOLEAN_YES);
2797
-
2798
- do_io = config_get_boolean_ondemand(CONFIG_SECTION_KERN_DEVSTAT, "bandwidth for all disks",
2799
- CONFIG_BOOLEAN_AUTO);
2800
- do_ops = config_get_boolean_ondemand(CONFIG_SECTION_KERN_DEVSTAT, "operations for all disks",
2801
- CONFIG_BOOLEAN_AUTO);
2802
- do_qops = config_get_boolean_ondemand(CONFIG_SECTION_KERN_DEVSTAT, "queued operations for all disks",
2803
- CONFIG_BOOLEAN_AUTO);
2804
- do_util = config_get_boolean_ondemand(CONFIG_SECTION_KERN_DEVSTAT, "utilization percentage for all disks",
2805
- CONFIG_BOOLEAN_AUTO);
2806
- do_iotime = config_get_boolean_ondemand(CONFIG_SECTION_KERN_DEVSTAT, "i/o time for all disks",
2807
- CONFIG_BOOLEAN_AUTO);
2808
- do_await = config_get_boolean_ondemand(CONFIG_SECTION_KERN_DEVSTAT, "average completed i/o time for all disks",
2809
- CONFIG_BOOLEAN_AUTO);
2810
- do_avagsz = config_get_boolean_ondemand(CONFIG_SECTION_KERN_DEVSTAT, "average completed i/o bandwidth for all disks",
2811
- CONFIG_BOOLEAN_AUTO);
2812
- do_svctm = config_get_boolean_ondemand(CONFIG_SECTION_KERN_DEVSTAT, "average service time for all disks",
2813
- CONFIG_BOOLEAN_AUTO);
2814
- }
2815
-
2816
- if (likely(do_system_io || do_io || do_ops || do_qops || do_util || do_iotime || do_await || do_avagsz || do_svctm)) {
2817
- static int mib_numdevs[3] = {0, 0, 0};
2818
- int numdevs;
2819
- int common_error = 0;
2820
-
2821
- if (unlikely(GETSYSCTL_SIMPLE("kern.devstat.numdevs", mib_numdevs, numdevs))) {
2822
- common_error = 1;
2823
- } else {
2824
- static int mib_devstat[3] = {0, 0, 0};
2825
- static void *devstat_data = NULL;
2826
- static int old_numdevs = 0;
2827
-
2828
- if (unlikely(numdevs != old_numdevs)) {
2829
- devstat_data = reallocz(devstat_data, sizeof(long) + sizeof(struct devstat) *
2830
- numdevs); // there is generation number before devstat structures
2831
- old_numdevs = numdevs;
2832
- }
2833
- if (unlikely(GETSYSCTL_WSIZE("kern.devstat.all", mib_devstat, devstat_data,
2834
- sizeof(long) + sizeof(struct devstat) * numdevs))) {
2835
- common_error = 1;
2836
- } else {
2837
- struct devstat *dstat;
2838
- int i;
2839
- collected_number total_disk_kbytes_read = 0;
2840
- collected_number total_disk_kbytes_write = 0;
2841
-
2842
- // Data to be stored in DICTIONARY disks.
2843
- // This DICTIONARY is used to lookup the settings of the disks on each iteration.
2844
- struct disks_metadata {
2845
- int do_io;
2846
- int do_ops;
2847
- int do_qops;
2848
- int do_util;
2849
- int do_iotime;
2850
- int do_await;
2851
- int do_avagsz;
2852
- int do_svctm;
2853
-
2854
-
2855
- // data for differential charts
2856
-
2857
- struct prev_dstat {
2858
- collected_number bytes_read;
2859
- collected_number bytes_write;
2860
- collected_number operations_read;
2861
- collected_number operations_write;
2862
- collected_number duration_read_ms;
2863
- collected_number duration_write_ms;
2864
- collected_number busy_time_ms;
2865
- } prev_dstat;
2866
-
2867
- // charts and dimensions
2868
-
2869
- RRDSET *st_io;
2870
- RRDDIM *rd_io_in;
2871
- RRDDIM *rd_io_out;
2872
-
2873
- RRDSET *st_ops;
2874
- RRDDIM *rd_ops_in;
2875
- RRDDIM *rd_ops_out;
2876
-
2877
- RRDSET *st_qops;
2878
- RRDDIM *rd_qops;
2879
-
2880
- RRDSET *st_util;
2881
- RRDDIM *rd_util;
2882
-
2883
- RRDSET *st_iotime;
2884
- RRDDIM *rd_iotime_in;
2885
- RRDDIM *rd_iotime_out;
2886
-
2887
- RRDSET *st_await;
2888
- RRDDIM *rd_await_in;
2889
- RRDDIM *rd_await_out;
2890
-
2891
- RRDSET *st_avagsz;
2892
- RRDDIM *rd_avagsz_in;
2893
- RRDDIM *rd_avagsz_out;
2894
-
2895
- RRDSET *st_svctm;
2896
- RRDDIM *rd_svctm;
2897
-
2898
- };
2899
- static DICTIONARY *disks = NULL;
2900
- static SIMPLE_PATTERN *excluded_disks = NULL;
2901
-
2902
- if(unlikely(!disks)) {
2903
-
2904
- excluded_disks = simple_pattern_create(
2905
- config_get(CONFIG_SECTION_KERN_DEVSTAT, "disable by default disks matching",
2906
- DELAULT_EXLUDED_DISKS)
2907
- , SIMPLE_PATTERN_EXACT
2908
- );
2909
-
2910
- disks = dictionary_create(DICTIONARY_FLAG_SINGLE_THREADED);
2911
- }
2912
-
2913
- dstat = devstat_data + sizeof(long); // skip generation number
2914
-
2915
- for (i = 0; i < numdevs; i++) {
2916
- if (likely(do_system_io)) {
2917
- if (((dstat[i].device_type & DEVSTAT_TYPE_MASK) == DEVSTAT_TYPE_DIRECT) || ((dstat[i].device_type & DEVSTAT_TYPE_MASK) == DEVSTAT_TYPE_STORARRAY)) {
2918
- total_disk_kbytes_read += dstat[i].bytes[DEVSTAT_READ] / KILO_FACTOR;
2919
- total_disk_kbytes_write += dstat[i].bytes[DEVSTAT_WRITE] / KILO_FACTOR;
2920
- }
2921
- }
2922
-
2923
- if (unlikely(!enable_pass_devices))
2924
- if ((dstat[i].device_type & DEVSTAT_TYPE_PASS) == DEVSTAT_TYPE_PASS)
2925
- continue;
2926
-
2927
- if (((dstat[i].device_type & DEVSTAT_TYPE_MASK) == DEVSTAT_TYPE_DIRECT) || ((dstat[i].device_type & DEVSTAT_TYPE_MASK) == DEVSTAT_TYPE_STORARRAY)) {
2928
- char disk[DEVSTAT_NAME_LEN + MAX_INT_DIGITS + 1];
2929
- int def_io, def_ops, def_qops, def_util, def_iotime, def_await, def_avagsz, def_svctm,
2930
- iter_io, iter_ops, iter_qops, iter_util, iter_iotime, iter_await, iter_avagsz, iter_svctm;
2931
- struct cur_dstat {
2932
- collected_number duration_read_ms;
2933
- collected_number duration_write_ms;
2934
- collected_number busy_time_ms;
2935
- } cur_dstat;
2936
-
2937
- sprintf(disk, "%s%d", dstat[i].device_name, dstat[i].unit_number);
2938
-
2939
- struct disks_metadata *dm = dictionary_get(disks, disk);
2940
- if(unlikely(!dm)) {
2941
- char var_name[4096 + 1];
2942
- snprintfz(var_name, 4096, "%s:%s", CONFIG_SECTION_KERN_DEVSTAT, disk);
2943
-
2944
- def_io = do_io;
2945
- def_ops = do_ops;
2946
- def_qops = do_qops;
2947
- def_util = do_util;
2948
- def_iotime = do_iotime;
2949
- def_await = do_await;
2950
- def_avagsz = do_avagsz;
2951
- def_svctm = do_svctm;
2952
-
2953
- if(unlikely(simple_pattern_matches(excluded_disks, disk))) {
2954
- def_io = CONFIG_BOOLEAN_NO;
2955
- def_ops = CONFIG_BOOLEAN_NO;
2956
- def_qops = CONFIG_BOOLEAN_NO;
2957
- def_util = CONFIG_BOOLEAN_NO;
2958
- def_iotime = CONFIG_BOOLEAN_NO;
2959
- def_await = CONFIG_BOOLEAN_NO;
2960
- def_avagsz = CONFIG_BOOLEAN_NO;
2961
- def_svctm = CONFIG_BOOLEAN_NO;
2962
- }
2963
-
2964
- iter_io = config_get_boolean_ondemand(var_name, "bandwidth", def_io);
2965
- iter_ops = config_get_boolean_ondemand(var_name, "operations", def_ops);
2966
- iter_qops = config_get_boolean_ondemand(var_name, "queued operations", def_qops);
2967
- iter_util = config_get_boolean_ondemand(var_name, "utilization percentage", def_util);
2968
- iter_iotime = config_get_boolean_ondemand(var_name, "i/o time", def_iotime);
2969
- iter_await = config_get_boolean_ondemand(var_name, "average completed i/o time", def_await);
2970
- iter_avagsz = config_get_boolean_ondemand(var_name, "average completed i/o bandwidth",
2971
- def_avagsz);
2972
- iter_svctm = config_get_boolean_ondemand(var_name, "average service time", def_svctm);
2973
-
2974
- struct disks_metadata dmp = {
2975
- .do_io = iter_io,
2976
- .do_ops = iter_ops,
2977
- .do_qops = iter_qops,
2978
- .do_util = iter_util,
2979
- .do_iotime = iter_iotime,
2980
- .do_await = iter_await,
2981
- .do_avagsz = iter_avagsz,
2982
- .do_svctm = iter_svctm,
2983
-
2984
- .st_io = NULL,
2985
- .rd_io_in = NULL,
2986
- .rd_io_out = NULL,
2987
-
2988
- .st_ops = NULL,
2989
- .rd_ops_in = NULL,
2990
- .rd_ops_out = NULL,
2991
-
2992
- .st_qops = NULL,
2993
- .rd_qops = NULL,
2994
-
2995
- .st_util = NULL,
2996
- .rd_util = NULL,
2997
-
2998
- .st_iotime = NULL,
2999
- .rd_iotime_in = NULL,
3000
- .rd_iotime_out = NULL,
3001
-
3002
- .st_await = NULL,
3003
- .rd_await_in = NULL,
3004
- .rd_await_out = NULL,
3005
-
3006
- .st_avagsz = NULL,
3007
- .rd_avagsz_in = NULL,
3008
- .rd_avagsz_out = NULL,
3009
-
3010
- .st_svctm = NULL,
3011
- .rd_svctm = NULL,
3012
- };
3013
-
3014
- // initialise data for differential charts
3015
-
3016
- dmp.prev_dstat.bytes_read = dstat[i].bytes[DEVSTAT_READ];
3017
- dmp.prev_dstat.bytes_write = dstat[i].bytes[DEVSTAT_WRITE];
3018
- dmp.prev_dstat.operations_read = dstat[i].operations[DEVSTAT_READ];
3019
- dmp.prev_dstat.operations_write = dstat[i].operations[DEVSTAT_WRITE];
3020
- dmp.prev_dstat.duration_read_ms = dstat[i].duration[DEVSTAT_READ].sec * 1000
3021
- + dstat[i].duration[DEVSTAT_READ].frac * BINTIME_SCALE;
3022
- dmp.prev_dstat.duration_write_ms = dstat[i].duration[DEVSTAT_WRITE].sec * 1000
3023
- + dstat[i].duration[DEVSTAT_READ].frac * BINTIME_SCALE;
3024
- dmp.prev_dstat.busy_time_ms = dstat[i].busy_time.sec * 1000
3025
- + dstat[i].busy_time.frac * BINTIME_SCALE;
3026
-
3027
- dm = dictionary_set(disks, disk, &dmp, sizeof(struct disks_metadata));
3028
- }
3029
-
3030
- cur_dstat.duration_read_ms = dstat[i].duration[DEVSTAT_READ].sec * 1000
3031
- + dstat[i].duration[DEVSTAT_READ].frac * BINTIME_SCALE;
3032
- cur_dstat.duration_write_ms = dstat[i].duration[DEVSTAT_WRITE].sec * 1000
3033
- + dstat[i].duration[DEVSTAT_READ].frac * BINTIME_SCALE;
3034
- cur_dstat.busy_time_ms = dstat[i].busy_time.sec * 1000 + dstat[i].busy_time.frac * BINTIME_SCALE;
3035
-
3036
- // --------------------------------------------------------------------
3037
-
3038
- if(dm->do_io == CONFIG_BOOLEAN_YES || (dm->do_io == CONFIG_BOOLEAN_AUTO &&
3039
- (dstat[i].bytes[DEVSTAT_READ] || dstat[i].bytes[DEVSTAT_WRITE]))) {
3040
- if (unlikely(!dm->st_io)) {
3041
- dm->st_io = rrdset_create_localhost("disk",
3042
- disk,
3043
- NULL,
3044
- disk,
3045
- "disk.io",
3046
- "Disk I/O Bandwidth",
3047
- "kilobytes/s",
3048
- 2000,
3049
- update_every,
3050
- RRDSET_TYPE_AREA
3051
- );
3052
-
3053
- dm->rd_io_in = rrddim_add(dm->st_io, "reads", NULL, 1, KILO_FACTOR,
3054
- RRD_ALGORITHM_INCREMENTAL);
3055
- dm->rd_io_out = rrddim_add(dm->st_io, "writes", NULL, -1, KILO_FACTOR,
3056
- RRD_ALGORITHM_INCREMENTAL);
3057
- } else
3058
- rrdset_next(dm->st_io);
3059
-
3060
- rrddim_set_by_pointer(dm->st_io, dm->rd_io_in, dstat[i].bytes[DEVSTAT_READ]);
3061
- rrddim_set_by_pointer(dm->st_io, dm->rd_io_out, dstat[i].bytes[DEVSTAT_WRITE]);
3062
- rrdset_done(dm->st_io);
3063
- }
3064
-
3065
- // --------------------------------------------------------------------
3066
-
3067
- if(dm->do_ops == CONFIG_BOOLEAN_YES || (dm->do_ops == CONFIG_BOOLEAN_AUTO &&
3068
- (dstat[i].operations[DEVSTAT_READ] || dstat[i].operations[DEVSTAT_WRITE]))) {
3069
- if (unlikely(!dm->st_ops)) {
3070
- dm->st_ops = rrdset_create_localhost("disk_ops",
3071
- disk,
3072
- NULL,
3073
- disk,
3074
- "disk.ops",
3075
- "Disk Completed I/O Operations",
3076
- "operations/s",
3077
- 2001,
3078
- update_every,
3079
- RRDSET_TYPE_LINE
3080
- );
3081
-
3082
- rrdset_flag_set(dm->st_ops, RRDSET_FLAG_DETAIL);
3083
-
3084
- dm->rd_ops_in = rrddim_add(dm->st_ops, "reads", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
3085
- dm->rd_ops_out = rrddim_add(dm->st_ops, "writes", NULL, -1, 1,
3086
- RRD_ALGORITHM_INCREMENTAL);
3087
- } else
3088
- rrdset_next(dm->st_ops);
3089
-
3090
- rrddim_set_by_pointer(dm->st_ops, dm->rd_ops_in, dstat[i].operations[DEVSTAT_READ]);
3091
- rrddim_set_by_pointer(dm->st_ops, dm->rd_ops_out, dstat[i].operations[DEVSTAT_WRITE]);
3092
- rrdset_done(dm->st_ops);
3093
- }
3094
-
3095
- // --------------------------------------------------------------------
3096
-
3097
- if(dm->do_qops == CONFIG_BOOLEAN_YES || (dm->do_qops == CONFIG_BOOLEAN_AUTO &&
3098
- (dstat[i].start_count || dstat[i].end_count))) {
3099
- if (unlikely(!dm->st_qops)) {
3100
- dm->st_qops = rrdset_create_localhost("disk_qops",
3101
- disk,
3102
- NULL,
3103
- disk,
3104
- "disk.qops",
3105
- "Disk Current I/O Operations",
3106
- "operations",
3107
- 2002,
3108
- update_every,
3109
- RRDSET_TYPE_LINE
3110
- );
3111
-
3112
- rrdset_flag_set(dm->st_qops, RRDSET_FLAG_DETAIL);
3113
-
3114
- dm->rd_qops = rrddim_add(dm->st_qops, "operations", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE);
3115
- } else
3116
- rrdset_next(dm->st_qops);
3117
-
3118
- rrddim_set_by_pointer(dm->st_qops, dm->rd_qops, dstat[i].start_count - dstat[i].end_count);
3119
- rrdset_done(dm->st_qops);
3120
- }
3121
-
3122
- // --------------------------------------------------------------------
3123
-
3124
- if(dm->do_util == CONFIG_BOOLEAN_YES || (dm->do_util == CONFIG_BOOLEAN_AUTO &&
3125
- cur_dstat.busy_time_ms)) {
3126
- if (unlikely(!dm->st_util)) {
3127
- dm->st_util = rrdset_create_localhost("disk_util",
3128
- disk,
3129
- NULL,
3130
- disk,
3131
- "disk.util",
3132
- "Disk Utilization Time",
3133
- "% of time working",
3134
- 2004,
3135
- update_every,
3136
- RRDSET_TYPE_AREA
3137
- );
3138
-
3139
- rrdset_flag_set(dm->st_util, RRDSET_FLAG_DETAIL);
3140
-
3141
- dm->rd_util = rrddim_add(dm->st_util, "utilization", NULL, 1, 10,
3142
- RRD_ALGORITHM_INCREMENTAL);
3143
- } else
3144
- rrdset_next(dm->st_util);
3145
-
3146
- rrddim_set_by_pointer(dm->st_util, dm->rd_util, cur_dstat.busy_time_ms);
3147
- rrdset_done(dm->st_util);
3148
- }
3149
-
3150
- // --------------------------------------------------------------------
3151
-
3152
- if(dm->do_iotime == CONFIG_BOOLEAN_YES || (dm->do_iotime == CONFIG_BOOLEAN_AUTO &&
3153
- (cur_dstat.duration_read_ms || cur_dstat.duration_write_ms))) {
3154
- if (unlikely(!dm->st_iotime)) {
3155
- dm->st_iotime = rrdset_create_localhost("disk_iotime",
3156
- disk,
3157
- NULL,
3158
- disk,
3159
- "disk.iotime",
3160
- "Disk Total I/O Time",
3161
- "milliseconds/s",
3162
- 2022,
3163
- update_every,
3164
- RRDSET_TYPE_LINE
3165
- );
3166
-
3167
- rrdset_flag_set(dm->st_iotime, RRDSET_FLAG_DETAIL);
3168
-
3169
- dm->rd_iotime_in = rrddim_add(dm->st_iotime, "reads", NULL, 1, 1,
3170
- RRD_ALGORITHM_INCREMENTAL);
3171
- dm->rd_iotime_out = rrddim_add(dm->st_iotime, "writes", NULL, -1, 1,
3172
- RRD_ALGORITHM_INCREMENTAL);
3173
- } else
3174
- rrdset_next(dm->st_iotime);
3175
-
3176
- rrddim_set_by_pointer(dm->st_iotime, dm->rd_iotime_in, cur_dstat.duration_read_ms);
3177
- rrddim_set_by_pointer(dm->st_iotime, dm->rd_iotime_out, cur_dstat.duration_write_ms);
3178
- rrdset_done(dm->st_iotime);
3179
- }
3180
-
3181
- // --------------------------------------------------------------------
3182
- // calculate differential charts
3183
- // only if this is not the first time we run
3184
-
3185
- if (likely(dt)) {
3186
-
3187
- // --------------------------------------------------------------------
3188
-
3189
- if(dm->do_await == CONFIG_BOOLEAN_YES || (dm->do_await == CONFIG_BOOLEAN_AUTO &&
3190
- (dstat[i].operations[DEVSTAT_READ] || dstat[i].operations[DEVSTAT_WRITE]))) {
3191
- if (unlikely(!dm->st_await)) {
3192
- dm->st_await = rrdset_create_localhost("disk_await",
3193
- disk,
3194
- NULL,
3195
- disk,
3196
- "disk.await",
3197
- "Average Completed I/O Operation Time",
3198
- "ms per operation",
3199
- 2005,
3200
- update_every,
3201
- RRDSET_TYPE_LINE
3202
- );
3203
-
3204
- rrdset_flag_set(dm->st_await, RRDSET_FLAG_DETAIL);
3205
-
3206
- dm->rd_await_in = rrddim_add(dm->st_await, "reads", NULL, 1, 1,
3207
- RRD_ALGORITHM_ABSOLUTE);
3208
- dm->rd_await_out = rrddim_add(dm->st_await, "writes", NULL, -1, 1,
3209
- RRD_ALGORITHM_ABSOLUTE);
3210
- } else
3211
- rrdset_next(dm->st_await);
3212
-
3213
- rrddim_set_by_pointer(dm->st_await, dm->rd_await_in,
3214
- (dstat[i].operations[DEVSTAT_READ] -
3215
- dm->prev_dstat.operations_read) ?
3216
- (cur_dstat.duration_read_ms - dm->prev_dstat.duration_read_ms) /
3217
- (dstat[i].operations[DEVSTAT_READ] -
3218
- dm->prev_dstat.operations_read) :
3219
- 0);
3220
- rrddim_set_by_pointer(dm->st_await, dm->rd_await_out,
3221
- (dstat[i].operations[DEVSTAT_WRITE] -
3222
- dm->prev_dstat.operations_write) ?
3223
- (cur_dstat.duration_write_ms - dm->prev_dstat.duration_write_ms) /
3224
- (dstat[i].operations[DEVSTAT_WRITE] -
3225
- dm->prev_dstat.operations_write) :
3226
- 0);
3227
- rrdset_done(dm->st_await);
3228
- }
3229
-
3230
- // --------------------------------------------------------------------
3231
-
3232
- if(dm->do_avagsz == CONFIG_BOOLEAN_YES || (dm->do_avagsz == CONFIG_BOOLEAN_AUTO &&
3233
- (dstat[i].operations[DEVSTAT_READ] || dstat[i].operations[DEVSTAT_WRITE]))) {
3234
- if (unlikely(!dm->st_avagsz)) {
3235
- dm->st_avagsz = rrdset_create_localhost("disk_avgsz",
3236
- disk,
3237
- NULL,
3238
- disk,
3239
- "disk.avgsz",
3240
- "Average Completed I/O Operation Bandwidth",
3241
- "kilobytes per operation",
3242
- 2006,
3243
- update_every,
3244
- RRDSET_TYPE_AREA
3245
- );
3246
-
3247
- rrdset_flag_set(dm->st_avagsz, RRDSET_FLAG_DETAIL);
3248
-
3249
- dm->rd_avagsz_in = rrddim_add(dm->st_avagsz, "reads", NULL, 1, KILO_FACTOR,
3250
- RRD_ALGORITHM_ABSOLUTE);
3251
- dm->rd_avagsz_out = rrddim_add(dm->st_avagsz, "writes", NULL, -1, KILO_FACTOR,
3252
- RRD_ALGORITHM_ABSOLUTE);
3253
- } else
3254
- rrdset_next(dm->st_avagsz);
3255
-
3256
- rrddim_set_by_pointer(dm->st_avagsz, dm->rd_avagsz_in,
3257
- (dstat[i].operations[DEVSTAT_READ] -
3258
- dm->prev_dstat.operations_read) ?
3259
- (dstat[i].bytes[DEVSTAT_READ] - dm->prev_dstat.bytes_read) /
3260
- (dstat[i].operations[DEVSTAT_READ] -
3261
- dm->prev_dstat.operations_read) :
3262
- 0);
3263
- rrddim_set_by_pointer(dm->st_avagsz, dm->rd_avagsz_out,
3264
- (dstat[i].operations[DEVSTAT_WRITE] -
3265
- dm->prev_dstat.operations_write) ?
3266
- (dstat[i].bytes[DEVSTAT_WRITE] - dm->prev_dstat.bytes_write) /
3267
- (dstat[i].operations[DEVSTAT_WRITE] -
3268
- dm->prev_dstat.operations_write) :
3269
- 0);
3270
- rrdset_done(dm->st_avagsz);
3271
- }
3272
-
3273
- // --------------------------------------------------------------------
3274
-
3275
- if(dm->do_svctm == CONFIG_BOOLEAN_YES || (dm->do_svctm == CONFIG_BOOLEAN_AUTO &&
3276
- (dstat[i].operations[DEVSTAT_READ] || dstat[i].operations[DEVSTAT_WRITE]))) {
3277
- if (unlikely(!dm->st_svctm)) {
3278
- dm->st_svctm = rrdset_create_localhost("disk_svctm",
3279
- disk,
3280
- NULL,
3281
- disk,
3282
- "disk.svctm",
3283
- "Average Service Time",
3284
- "ms per operation",
3285
- 2007,
3286
- update_every,
3287
- RRDSET_TYPE_LINE
3288
- );
3289
-
3290
- rrdset_flag_set(dm->st_svctm, RRDSET_FLAG_DETAIL);
3291
-
3292
- dm->rd_svctm = rrddim_add(dm->st_svctm, "svctm", NULL, 1, 1,
3293
- RRD_ALGORITHM_ABSOLUTE);
3294
- } else
3295
- rrdset_next(dm->st_svctm);
3296
-
3297
- rrddim_set_by_pointer(dm->st_svctm, dm->rd_svctm,
3298
- ((dstat[i].operations[DEVSTAT_READ] - dm->prev_dstat.operations_read) +
3299
- (dstat[i].operations[DEVSTAT_WRITE] - dm->prev_dstat.operations_write)) ?
3300
- (cur_dstat.busy_time_ms - dm->prev_dstat.busy_time_ms) /
3301
- ((dstat[i].operations[DEVSTAT_READ] - dm->prev_dstat.operations_read) +
3302
- (dstat[i].operations[DEVSTAT_WRITE] - dm->prev_dstat.operations_write)) :
3303
- 0);
3304
- rrdset_done(dm->st_svctm);
3305
- }
3306
-
3307
- // --------------------------------------------------------------------
3308
-
3309
- dm->prev_dstat.bytes_read = dstat[i].bytes[DEVSTAT_READ];
3310
- dm->prev_dstat.bytes_write = dstat[i].bytes[DEVSTAT_WRITE];
3311
- dm->prev_dstat.operations_read = dstat[i].operations[DEVSTAT_READ];
3312
- dm->prev_dstat.operations_write = dstat[i].operations[DEVSTAT_WRITE];
3313
- dm->prev_dstat.duration_read_ms = cur_dstat.duration_read_ms;
3314
- dm->prev_dstat.duration_write_ms = cur_dstat.duration_write_ms;
3315
- dm->prev_dstat.busy_time_ms = cur_dstat.busy_time_ms;
3316
- }
3317
- }
3318
- }
3319
-
3320
- // --------------------------------------------------------------------
3321
-
3322
- if (likely(do_system_io)) {
3323
- static RRDSET *st = NULL;
3324
- static RRDDIM *rd_in = NULL, *rd_out = NULL;
3325
-
3326
- if (unlikely(!st)) {
3327
- st = rrdset_create_localhost("system",
3328
- "io",
3329
- NULL,
3330
- "disk",
3331
- NULL,
3332
- "Disk I/O",
3333
- "kilobytes/s",
3334
- 150,
3335
- update_every,
3336
- RRDSET_TYPE_AREA
3337
- );
3338
-
3339
- rd_in = rrddim_add(st, "in", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
3340
- rd_out = rrddim_add(st, "out", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL);
3341
- } else
3342
- rrdset_next(st);
3343
-
3344
- rrddim_set_by_pointer(st, rd_in, total_disk_kbytes_read);
3345
- rrddim_set_by_pointer(st, rd_out, total_disk_kbytes_write);
3346
- rrdset_done(st);
3347
- }
3348
- }
3349
- }
3350
- if (unlikely(common_error)) {
3351
- do_system_io = 0;
3352
- error("DISABLED: system.io chart");
3353
- do_io = 0;
3354
- error("DISABLED: disk.* charts");
3355
- do_ops = 0;
3356
- error("DISABLED: disk_ops.* charts");
3357
- do_qops = 0;
3358
- error("DISABLED: disk_qops.* charts");
3359
- do_util = 0;
3360
- error("DISABLED: disk_util.* charts");
3361
- do_iotime = 0;
3362
- error("DISABLED: disk_iotime.* charts");
3363
- do_await = 0;
3364
- error("DISABLED: disk_await.* charts");
3365
- do_avagsz = 0;
3366
- error("DISABLED: disk_avgsz.* charts");
3367
- do_svctm = 0;
3368
- error("DISABLED: disk_svctm.* charts");
3369
- error("DISABLED: kern.devstat module");
3370
- return 1;
3371
- }
3372
- } else {
3373
- error("DISABLED: kern.devstat module");
3374
- return 1;
3375
- }
3376
-
3377
- return 0;
3378
-}