Add disk stats and do minor style cleanups
Vladimir Kobal committed
Dec 9, 2016 at 23:25 UTC
f82bbd9d06244f5ec770b2b0f5df64175a94f7e7
1 file changed
+226
-22
src/freebsd_sysctl.c
+226
-22
@@ -2,6 +2,10 @@
2
3
// NEEDED BY: struct vmstat
4
#include <sys/vmmeter.h>
5
+// NEEDED BY: struct devstat
6
+#include <sys/devicestat.h>
7
+// NEEDED BY: do_disk_io
8
+#define RRD_TYPE_DISK "disk"
9
10
// FreeBSD calculates load averages once every 5 seconds
11
#define MIN_LOADAVG_UPDATE_EVERY 5
@@ -10,9 +14,9 @@ int do_freebsd_sysctl(int update_every, unsigned long long dt) {
14
(void)dt;
15
16
static int do_cpu = -1, do_cpu_cores = -1, do_interrupts = -1, do_context = -1, do_forks = -1, do_processes = -1,
13
- do_loadavg = -1, do_all_processes = -1;
17
+ do_loadavg = -1, do_all_processes = -1, do_disk_io = -1;
18
15
- if(unlikely(do_cpu == -1)) {
19
+ if (unlikely(do_cpu == -1)) {
20
do_cpu = config_get_boolean("plugin:freebsd:sysctl", "cpu utilization", 1);
21
do_cpu_cores = config_get_boolean("plugin:freebsd:sysctl", "per cpu core utilization", 1);
22
do_interrupts = config_get_boolean("plugin:freebsd:sysctl", "cpu interrupts", 1);
@@ -21,6 +25,8 @@ int do_freebsd_sysctl(int update_every, unsigned long long dt) {
25
do_processes = config_get_boolean("plugin:freebsd:sysctl", "processes running", 1);
26
do_loadavg = config_get_boolean("plugin:freebsd:sysctl", "enable load average", 1);
27
do_all_processes = config_get_boolean("plugin:freebsd:sysctl", "enable total processes", 1);
28
+
29
+ do_disk_io = config_get_boolean("plugin:freebsd:sysctl", "stats for all disks", 1);
30
}
31
32
RRDSET *st;
@@ -51,17 +57,37 @@ int do_freebsd_sysctl(int update_every, unsigned long long dt) {
57
static unsigned long *intrcnt = NULL;
58
unsigned long long totalintr = 0;
59
60
+// NEEDED BY: do_disk_io
61
+ #define BINTIME_SCALE 5.42101086242752217003726400434970855712890625e-17 // this is 1000/2^64
62
+ int numdevs;
63
+ static void *devstat_data = NULL;
64
+ struct devstat *dstat;
65
+ struct cur_dstat {
66
+ collected_number duration_read_ms;
67
+ collected_number duration_write_ms;
68
+ collected_number busy_time_ms;
69
+ } cur_dstat;
70
+ struct prev_dstat {
71
+ collected_number bytes_read;
72
+ collected_number bytes_write;
73
+ collected_number operations_read;
74
+ collected_number operations_write;
75
+ collected_number duration_read_ms;
76
+ collected_number duration_write_ms;
77
+ collected_number busy_time_ms;
78
+ } prev_dstat;
79
+
80
// --------------------------------------------------------------------
81
56
- if(last_loadavg_usec <= dt) {
57
- if(likely(do_loadavg)) {
82
+ if (last_loadavg_usec <= dt) {
83
+ if (likely(do_loadavg)) {
84
if (unlikely(GETSYSCTL("vm.loadavg", sysload))) {
85
do_loadavg = 0;
86
error("DISABLED: system.load");
87
} else {
88
89
st = rrdset_find_bytype("system", "load");
64
- if(unlikely(!st)) {
90
+ if (unlikely(!st)) {
91
st = rrdset_create("system", "load", NULL, "load", NULL, "System Load Average", "load", 100, (update_every < MIN_LOADAVG_UPDATE_EVERY) ? MIN_LOADAVG_UPDATE_EVERY : update_every, RRDSET_TYPE_LINE);
92
rrddim_add(st, "load1", NULL, 1, 1000, RRDDIM_ABSOLUTE);
93
rrddim_add(st, "load5", NULL, 1, 1000, RRDDIM_ABSOLUTE);
@@ -82,17 +108,17 @@ int do_freebsd_sysctl(int update_every, unsigned long long dt) {
108
109
// --------------------------------------------------------------------
110
85
- if(likely(do_all_processes | do_processes)) {
111
+ if (likely(do_all_processes | do_processes)) {
112
if (unlikely(GETSYSCTL("vm.vmtotal", vmtotal_data))) {
113
do_all_processes = 0;
114
error("DISABLED: system.active_processes");
115
do_processes = 0;
116
error("DISABLED: system.processes");
117
} else {
92
- if(likely(do_processes)) {
118
+ if (likely(do_processes)) {
119
120
st = rrdset_find_bytype("system", "active_processes");
95
- if(unlikely(!st)) {
121
+ if (unlikely(!st)) {
122
st = rrdset_create("system", "active_processes", NULL, "processes", NULL, "System Active Processes", "processes", 750, update_every, RRDSET_TYPE_LINE);
123
rrddim_add(st, "active", NULL, 1, 1, RRDDIM_ABSOLUTE);
124
}
@@ -101,10 +127,10 @@ int do_freebsd_sysctl(int update_every, unsigned long long dt) {
127
rrddim_set(st, "active", (vmtotal_data.t_rq + vmtotal_data.t_dw + vmtotal_data.t_pw + vmtotal_data.t_sl + vmtotal_data.t_sw));
128
rrdset_done(st);
129
}
104
- if(likely(do_processes)) {
130
+ if (likely(do_processes)) {
131
132
st = rrdset_find_bytype("system", "processes");
107
- if(unlikely(!st)) {
133
+ if (unlikely(!st)) {
134
st = rrdset_create("system", "processes", NULL, "processes", NULL, "System Processes", "processes", 600, update_every, RRDSET_TYPE_LINE);
135
136
rrddim_add(st, "running", NULL, 1, 1, RRDDIM_ABSOLUTE);
@@ -122,10 +148,10 @@ int do_freebsd_sysctl(int update_every, unsigned long long dt) {
148
149
// --------------------------------------------------------------------
150
125
- if(likely(do_processes)) {
151
+ if (likely(do_processes)) {
152
153
st = rrdset_find_bytype("system", "processes");
128
- if(unlikely(!st)) {
154
+ if (unlikely(!st)) {
155
st = rrdset_create("system", "processes", NULL, "processes", NULL, "System Processes", "processes", 600, update_every, RRDSET_TYPE_LINE);
156
157
rrddim_add(st, "running", NULL, 1, 1, RRDDIM_ABSOLUTE);
@@ -140,7 +166,7 @@ int do_freebsd_sysctl(int update_every, unsigned long long dt) {
166
167
// --------------------------------------------------------------------
168
143
- if(likely(do_cpu)) {
169
+ if (likely(do_cpu)) {
170
if (unlikely(CPUSTATES != 5)) {
171
error("FREEBSD: There are %d CPU states (5 was expected)", CPUSTATES);
172
do_cpu = 0;
@@ -152,7 +178,7 @@ int do_freebsd_sysctl(int update_every, unsigned long long dt) {
178
} else {
179
180
st = rrdset_find_bytype("system", "cpu");
155
- if(unlikely(!st)) {
181
+ if (unlikely(!st)) {
182
st = rrdset_create("system", "cpu", NULL, "cpu", "system.cpu", "Total CPU utilization", "percentage", 100, update_every, RRDSET_TYPE_STACKED);
183
184
rrddim_add(st, "user", NULL, 1, 1, RRDDIM_PCENT_OVER_DIFF_TOTAL);
@@ -176,7 +202,7 @@ int do_freebsd_sysctl(int update_every, unsigned long long dt) {
202
203
// --------------------------------------------------------------------
204
179
- if(likely(do_cpu_cores)) {
205
+ if (likely(do_cpu_cores)) {
206
if (unlikely(CPUSTATES != 5)) {
207
error("FREEBSD: There are %d CPU states (5 was expected)", CPUSTATES);
208
do_cpu_cores = 0;
@@ -203,7 +229,7 @@ int do_freebsd_sysctl(int update_every, unsigned long long dt) {
229
snprintfz(cpuid, 8, "cpu%d", i);
230
231
st = rrdset_find_bytype("cpu", cpuid);
206
- if(unlikely(!st)) {
232
+ if (unlikely(!st)) {
233
st = rrdset_create("cpu", cpuid, NULL, "utilization", "cpu.cpu", "Core utilization", "percentage", 1000, update_every, RRDSET_TYPE_STACKED);
234
235
rrddim_add(st, "user", NULL, 1, 1, RRDDIM_PCENT_OVER_DIFF_TOTAL);
@@ -228,7 +254,7 @@ int do_freebsd_sysctl(int update_every, unsigned long long dt) {
254
255
// --------------------------------------------------------------------
256
231
- if(likely(do_interrupts)) {
257
+ if (likely(do_interrupts)) {
258
if (unlikely(sysctlbyname("hw.intrcnt", NULL, &intrcnt_size, NULL, 0) == -1)) {
259
error("FREEBSD: sysctl(hw.intrcnt...) failed: %s", strerror(errno));
260
do_interrupts = 0;
@@ -244,7 +270,7 @@ int do_freebsd_sysctl(int update_every, unsigned long long dt) {
270
totalintr += intrcnt[i];
271
272
st = rrdset_find_bytype("system", "intr");
247
- if(unlikely(!st)) {
273
+ if (unlikely(!st)) {
274
st = rrdset_create("system", "intr", NULL, "interrupts", NULL, "Total Device Interrupts", "interrupts/s", 900, update_every, RRDSET_TYPE_LINE);
275
st->isdetail = 1;
276
@@ -260,14 +286,14 @@ int do_freebsd_sysctl(int update_every, unsigned long long dt) {
286
287
// --------------------------------------------------------------------
288
263
- if(likely(do_context)) {
289
+ if (likely(do_context)) {
290
if (unlikely(GETSYSCTL("vm.stats.sys.v_swtch", u_int_data))) {
291
do_context = 0;
292
error("DISABLED: system.ctxt");
293
} else {
294
295
st = rrdset_find_bytype("system", "ctxt");
270
- if(unlikely(!st)) {
296
+ if (unlikely(!st)) {
297
st = rrdset_create("system", "ctxt", NULL, "processes", NULL, "CPU Context Switches", "context switches/s", 800, update_every, RRDSET_TYPE_LINE);
298
299
rrddim_add(st, "switches", NULL, 1, 1, RRDDIM_INCREMENTAL);
@@ -281,14 +307,14 @@ int do_freebsd_sysctl(int update_every, unsigned long long dt) {
307
308
// --------------------------------------------------------------------
309
284
- if(likely(do_forks)) {
310
+ if (likely(do_forks)) {
311
if (unlikely(GETSYSCTL("vm.stats.vm.v_forks", u_int_data))) {
312
do_forks = 0;
313
error("DISABLED: system.forks");
314
} else {
315
316
st = rrdset_find_bytype("system", "forks");
291
- if(unlikely(!st)) {
317
+ if (unlikely(!st)) {
318
st = rrdset_create("system", "forks", NULL, "processes", NULL, "Started Processes", "processes/s", 700, update_every, RRDSET_TYPE_LINE);
319
st->isdetail = 1;
320
@@ -301,5 +327,183 @@ int do_freebsd_sysctl(int update_every, unsigned long long dt) {
327
}
328
}
329
330
+ // --------------------------------------------------------------------
331
+
332
+ if (likely(do_disk_io)) {
333
+ if (unlikely(GETSYSCTL("kern.devstat.numdevs", numdevs))) {
334
+ do_disk_io = 0;
335
+ error("DISABLED: disk.io");
336
+ } else {
337
+ devstat_data = reallocz(devstat_data, sizeof(long) + sizeof(struct devstat) * numdevs); // there is generation number before devstat structures
338
+ if (unlikely(getsysctl("kern.devstat.all", devstat_data, sizeof(long) + sizeof(struct devstat) * numdevs))) {
339
+ do_disk_io = 0;
340
+ error("DISABLED: disk.io");
341
+ } else {
342
+ dstat = devstat_data +sizeof(long); // skip generation number
343
+ collected_number total_disk_reads = 0;
344
+ collected_number total_disk_writes = 0;
345
+
346
+ for (i = 0; i < numdevs; i++) {
347
+ if ((dstat[i].device_type == (DEVSTAT_TYPE_IF_SCSI | DEVSTAT_TYPE_DIRECT)) || (dstat[i].device_type == (DEVSTAT_TYPE_IF_IDE | DEVSTAT_TYPE_DIRECT))) {
348
+
349
+ // --------------------------------------------------------------------
350
+
351
+ st = rrdset_find_bytype(RRD_TYPE_DISK, dstat[i].device_name);
352
+ if (unlikely(!st)) {
353
+ st = rrdset_create(RRD_TYPE_DISK, dstat[i].device_name, NULL, dstat[i].device_name, "disk.io", "Disk I/O Bandwidth", "kilobytes/s", 2000, update_every, RRDSET_TYPE_AREA);
354
+
355
+ rrddim_add(st, "reads", NULL, 1, 1024, RRDDIM_INCREMENTAL);
356
+ rrddim_add(st, "writes", NULL, -1, 1024, RRDDIM_INCREMENTAL);
357
+ }
358
+ else rrdset_next(st);
359
+
360
+ total_disk_reads += dstat[i].bytes[DEVSTAT_READ];
361
+ total_disk_writes += dstat[i].bytes[DEVSTAT_WRITE];
362
+ prev_dstat.bytes_read = rrddim_set(st, "reads", dstat[i].bytes[DEVSTAT_READ]);
363
+ prev_dstat.bytes_write = rrddim_set(st, "writes", dstat[i].bytes[DEVSTAT_WRITE]);
364
+ rrdset_done(st);
365
+
366
+ // --------------------------------------------------------------------
367
+
368
+ st = rrdset_find_bytype("disk_ops", dstat[i].device_name);
369
+ if (unlikely(!st)) {
370
+ st = rrdset_create("disk_ops", dstat[i].device_name, NULL, dstat[i].device_name, "disk.ops", "Disk Completed I/O Operations", "operations/s", 2001, update_every, RRDSET_TYPE_LINE);
371
+ st->isdetail = 1;
372
+
373
+ rrddim_add(st, "reads", NULL, 1, 1, RRDDIM_INCREMENTAL);
374
+ rrddim_add(st, "writes", NULL, -1, 1, RRDDIM_INCREMENTAL);
375
+ }
376
+ else rrdset_next(st);
377
+
378
+ prev_dstat.operations_read = rrddim_set(st, "reads", dstat[i].operations[DEVSTAT_READ]);
379
+ prev_dstat.operations_write = rrddim_set(st, "writes", dstat[i].operations[DEVSTAT_WRITE]);
380
+ rrdset_done(st);
381
+
382
+ // --------------------------------------------------------------------
383
+
384
+ st = rrdset_find_bytype("disk_qops", dstat[i].device_name);
385
+ if (unlikely(!st)) {
386
+ st = rrdset_create("disk_qops", dstat[i].device_name, NULL, dstat[i].device_name, "disk.qops", "Disk Current I/O Operations", "operations", 2002, update_every, RRDSET_TYPE_LINE);
387
+ st->isdetail = 1;
388
+
389
+ rrddim_add(st, "operations", NULL, 1, 1, RRDDIM_ABSOLUTE);
390
+ }
391
+ else rrdset_next(st);
392
+
393
+ rrddim_set(st, "operations", dstat[i].start_count - dstat[i].end_count);
394
+ rrdset_done(st);
395
+
396
+ // --------------------------------------------------------------------
397
+
398
+ st = rrdset_find_bytype("disk_util", dstat[i].device_name);
399
+ if (unlikely(!st)) {
400
+ st = rrdset_create("disk_util", dstat[i].device_name, NULL, dstat[i].device_name, "disk.util", "Disk Utilization Time", "% of time working", 2004, update_every, RRDSET_TYPE_AREA);
401
+ st->isdetail = 1;
402
+
403
+ rrddim_add(st, "utilization", NULL, 1, 10, RRDDIM_INCREMENTAL);
404
+ }
405
+ else rrdset_next(st);
406
+
407
+ cur_dstat.busy_time_ms = dstat[i].busy_time.sec * 1000 + dstat[i].busy_time.frac * BINTIME_SCALE;
408
+ prev_dstat.busy_time_ms = rrddim_set(st, "utilization", cur_dstat.busy_time_ms);
409
+ rrdset_done(st);
410
+
411
+ // --------------------------------------------------------------------
412
+
413
+ st = rrdset_find_bytype("disk_iotime", dstat[i].device_name);
414
+ if (unlikely(!st)) {
415
+ st = rrdset_create("disk_iotime", dstat[i].device_name, NULL, dstat[i].device_name, "disk.iotime", "Disk Total I/O Time", "milliseconds/s", 2022, update_every, RRDSET_TYPE_LINE);
416
+ st->isdetail = 1;
417
+
418
+ rrddim_add(st, "reads", NULL, 1, 1, RRDDIM_INCREMENTAL);
419
+ rrddim_add(st, "writes", NULL, -1, 1, RRDDIM_INCREMENTAL);
420
+ }
421
+ else rrdset_next(st);
422
+
423
+ cur_dstat.duration_read_ms = dstat[i].duration[DEVSTAT_READ].sec * 1000 + dstat[i].duration[DEVSTAT_READ].frac * BINTIME_SCALE;
424
+ cur_dstat.duration_write_ms = dstat[i].duration[DEVSTAT_WRITE].sec * 1000 + dstat[i].duration[DEVSTAT_READ].frac * BINTIME_SCALE;
425
+ prev_dstat.duration_read_ms = rrddim_set(st, "reads", cur_dstat.duration_read_ms);
426
+ prev_dstat.duration_write_ms = rrddim_set(st, "writes", cur_dstat.duration_write_ms);
427
+ rrdset_done(st);
428
+
429
+ // --------------------------------------------------------------------
430
+ // calculate differential charts
431
+ // only if this is not the first time we run
432
+
433
+ if (likely(dt)) {
434
+
435
+ // --------------------------------------------------------------------
436
+
437
+ st = rrdset_find_bytype("disk_await", dstat[i].device_name);
438
+ if (unlikely(!st)) {
439
+ st = rrdset_create("disk_await", dstat[i].device_name, NULL, dstat[i].device_name, "disk.await", "Average Completed I/O Operation Time", "ms per operation", 2005, update_every, RRDSET_TYPE_LINE);
440
+ st->isdetail = 1;
441
+
442
+ rrddim_add(st, "reads", NULL, 1, 1, RRDDIM_ABSOLUTE);
443
+ rrddim_add(st, "writes", NULL, -1, 1, RRDDIM_ABSOLUTE);
444
+ }
445
+ else rrdset_next(st);
446
+
447
+ rrddim_set(st, "reads", (dstat[i].operations[DEVSTAT_READ] - prev_dstat.operations_read) ?
448
+ (cur_dstat.duration_read_ms - prev_dstat.duration_read_ms) / (dstat[i].operations[DEVSTAT_READ] - prev_dstat.operations_read) : 0);
449
+ rrddim_set(st, "writes", (dstat[i].operations[DEVSTAT_WRITE] - prev_dstat.operations_write) ?
450
+ (cur_dstat.duration_write_ms - prev_dstat.duration_write_ms) / (dstat[i].operations[DEVSTAT_WRITE] - prev_dstat.operations_write) : 0);
451
+ rrdset_done(st);
452
+
453
+ // --------------------------------------------------------------------
454
+
455
+ st = rrdset_find_bytype("disk_avgsz", dstat[i].device_name);
456
+ if (unlikely(!st)) {
457
+ st = rrdset_create("disk_avgsz", dstat[i].device_name, NULL, dstat[i].device_name, "disk.avgsz", "Average Completed I/O Operation Bandwidth", "kilobytes per operation", 2006, update_every, RRDSET_TYPE_AREA);
458
+ st->isdetail = 1;
459
+
460
+ rrddim_add(st, "reads", NULL, 1, 1024, RRDDIM_ABSOLUTE);
461
+ rrddim_add(st, "writes", NULL, -1, 1024, RRDDIM_ABSOLUTE);
462
+ }
463
+ else rrdset_next(st);
464
+
465
+ rrddim_set(st, "reads", (dstat[i].operations[DEVSTAT_READ] - prev_dstat.operations_read) ?
466
+ (dstat[i].bytes[DEVSTAT_READ] - prev_dstat.bytes_read) / (dstat[i].operations[DEVSTAT_READ] - prev_dstat.operations_read) : 0);
467
+ rrddim_set(st, "writes", (dstat[i].operations[DEVSTAT_WRITE] - prev_dstat.operations_write) ?
468
+ (dstat[i].bytes[DEVSTAT_WRITE] - prev_dstat.bytes_write) / (dstat[i].operations[DEVSTAT_WRITE] - prev_dstat.operations_write) : 0);
469
+ rrdset_done(st);
470
+
471
+ // --------------------------------------------------------------------
472
+
473
+ st = rrdset_find_bytype("disk_svctm", dstat[i].device_name);
474
+ if (unlikely(!st)) {
475
+ st = rrdset_create("disk_svctm", dstat[i].device_name, NULL, dstat[i].device_name, "disk.svctm", "Average Service Time", "ms per operation", 2007, update_every, RRDSET_TYPE_LINE);
476
+ st->isdetail = 1;
477
+
478
+ rrddim_add(st, "svctm", NULL, 1, 1, RRDDIM_ABSOLUTE);
479
+ }
480
+ else rrdset_next(st);
481
+
482
+ rrddim_set(st, "svctm", ((dstat[i].operations[DEVSTAT_READ] - prev_dstat.operations_read) + (dstat[i].operations[DEVSTAT_WRITE] - prev_dstat.operations_write)) ?
483
+ (cur_dstat.busy_time_ms - prev_dstat.busy_time_ms) / ((dstat[i].operations[DEVSTAT_READ] - prev_dstat.operations_read) + (dstat[i].operations[DEVSTAT_WRITE] - prev_dstat.operations_write)) : 0);
484
+ rrdset_done(st);
485
+
486
+ }
487
+
488
+ }
489
+
490
+ // --------------------------------------------------------------------
491
+
492
+ st = rrdset_find_bytype("system", "io");
493
+ if (unlikely(!st)) {
494
+ st = rrdset_create("system", "io", NULL, "disk", NULL, "Disk I/O", "kilobytes/s", 150, update_every, RRDSET_TYPE_AREA);
495
+ rrddim_add(st, "in", NULL, 1, 1024, RRDDIM_INCREMENTAL);
496
+ rrddim_add(st, "out", NULL, -1, 1024, RRDDIM_INCREMENTAL);
497
+ }
498
+ else rrdset_next(st);
499
+
500
+ rrddim_set(st, "in", total_disk_reads);
501
+ rrddim_set(st, "out", total_disk_writes);
502
+ rrdset_done(st);
503
+ }
504
+ }
505
+ }
506
+ }
507
+
508
return 0;
509
}