@cryptotaxi247 / netdata-1 / commits / 91a03b04b

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 -}