From 78d53e2d121dfa6ddb94cc5ae0f94ddfcdb4e51a Mon Sep 17 00:00:00 2001 From: Vladimir Kobal Date: Wed, 28 Dec 2016 15:40:33 -0500 Subject: [PATCH] Add disk I/O chart to macOS plugin --- configure.ac | 1 + src/Makefile.am | 1 + src/macos_fw.c | 97 ++++++++++++++++++++++++++++++++++++++++++++ src/macos_mach_smi.c | 2 +- src/plugin_macos.c | 10 +++++ src/plugin_macos.h | 1 + 6 files changed, 111 insertions(+), 1 deletion(-) create mode 100644 src/macos_fw.c diff --git a/configure.ac b/configure.ac index 1b03d0bfcb4014..d2745f62fc4831 100644 --- a/configure.ac +++ b/configure.ac @@ -46,6 +46,7 @@ freebsd*) ;; darwin*) build_target=macos + LDFLAGS="${LDFLAGS} -framework CoreFoundation -framework IOKit" ;; *) ;; diff --git a/src/Makefile.am b/src/Makefile.am index 8df6b61fcfb3e0..e1f87b5e4dfbc6 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -72,6 +72,7 @@ netdata_SOURCES += \ plugin_macos.c plugin_macos.h \ macos_sysctl.c \ macos_mach_smi.c \ + macos_fw.c \ $(NULL) else netdata_SOURCES += \ diff --git a/src/macos_fw.c b/src/macos_fw.c new file mode 100644 index 00000000000000..47d70eda7b34f9 --- /dev/null +++ b/src/macos_fw.c @@ -0,0 +1,97 @@ +#include "common.h" +#include +#include +#include + +int do_macos_iokit(int update_every, usec_t dt) { + (void)dt; + + static int do_io = -1; + + if (unlikely(do_io == -1)) { + do_io = config_get_boolean("plugin:macos:iokit", "disk i/o", 1); + } + + RRDSET *st; + + mach_port_t master_port; + io_registry_entry_t drive; + io_iterator_t drive_list; + CFNumberRef number; + CFDictionaryRef properties, statistics; + UInt64 value; + collected_number total_disk_reads = 0; + collected_number total_disk_writes = 0; + + /* Get ports and services for drive statistics. */ + if (IOMasterPort(bootstrap_port, &master_port)) { + error("MACOS: IOMasterPort() failed"); + do_io = 0; + error("DISABLED: system.io"); + /* Get the list of all drive objects. */ + } else if (IOServiceGetMatchingServices(master_port, IOServiceMatching("IOBlockStorageDriver"), &drive_list)) { + error("MACOS: IOServiceGetMatchingServices() failed"); + do_io = 0; + error("DISABLED: system.io"); + } else { + while ((drive = IOIteratorNext(drive_list)) != 0) { + number = 0; + properties = 0; + statistics = 0; + value = 0; + + /* Obtain the properties for this drive object. */ + if (IORegistryEntryCreateCFProperties(drive, (CFMutableDictionaryRef *)&properties, kCFAllocatorDefault, 0)) { + error("MACOS: IORegistryEntryCreateCFProperties() failed"); + do_io = 0; + error("DISABLED: system.io"); + break; + } else if (properties != 0) { + /* Obtain the statistics from the drive properties. */ + statistics = (CFDictionaryRef)CFDictionaryGetValue(properties, CFSTR(kIOBlockStorageDriverStatisticsKey)); + + if (statistics != 0) { + /* Get bytes read. */ + number = (CFNumberRef)CFDictionaryGetValue(statistics, CFSTR(kIOBlockStorageDriverStatisticsBytesReadKey)); + if (number != 0) { + CFNumberGetValue(number, kCFNumberSInt64Type, &value); + total_disk_reads += value; + } + + /* Get bytes written. */ + number = (CFNumberRef)CFDictionaryGetValue(statistics, CFSTR(kIOBlockStorageDriverStatisticsBytesWrittenKey)); + if (number != 0) { + CFNumberGetValue(number, kCFNumberSInt64Type, &value); + total_disk_writes += value; + } + } + + /* Release. */ + CFRelease(properties); + } + + /* Release. */ + IOObjectRelease(drive); + } + IOIteratorReset(drive_list); + + /* Release. */ + IOObjectRelease(drive_list); + } + + if (do_io) { + st = rrdset_find_bytype("system", "io"); + if (unlikely(!st)) { + st = rrdset_create("system", "io", NULL, "disk", NULL, "Disk I/O", "kilobytes/s", 150, update_every, RRDSET_TYPE_AREA); + rrddim_add(st, "in", NULL, 1, 1024, RRDDIM_INCREMENTAL); + rrddim_add(st, "out", NULL, -1, 1024, RRDDIM_INCREMENTAL); + } + else rrdset_next(st); + + rrddim_set(st, "in", total_disk_reads); + rrddim_set(st, "out", total_disk_writes); + rrdset_done(st); + } + + return 0; +} diff --git a/src/macos_mach_smi.c b/src/macos_mach_smi.c index 58510688888d8c..d86a032205bf79 100644 --- a/src/macos_mach_smi.c +++ b/src/macos_mach_smi.c @@ -36,7 +36,7 @@ int do_macos_mach_smi(int update_every, usec_t dt) { if (likely(do_cpu)) { if (unlikely(HOST_CPU_LOAD_INFO_COUNT != 4)) { - error("FREEBSD: There are %d CPU states (4 was expected)", HOST_CPU_LOAD_INFO_COUNT); + error("MACOS: There are %d CPU states (4 was expected)", HOST_CPU_LOAD_INFO_COUNT); do_cpu = 0; error("DISABLED: system.cpu"); } else { diff --git a/src/plugin_macos.c b/src/plugin_macos.c index 2f3a9cf453ab19..9f88d1e2e6ca8a 100644 --- a/src/plugin_macos.c +++ b/src/plugin_macos.c @@ -22,10 +22,12 @@ void *macos_main(void *ptr) int vdo_cpu_netdata = !config_get_boolean("plugin:macos", "netdata server resources", 1); int vdo_macos_sysctl = !config_get_boolean("plugin:macos", "sysctl", 1); int vdo_macos_mach_smi = !config_get_boolean("plugin:macos", "mach system management interface", 1); + int vdo_macos_iokit = !config_get_boolean("plugin:macos", "iokit", 1); // keep track of the time each module was called unsigned long long sutime_macos_sysctl = 0ULL; unsigned long long sutime_macos_mach_smi = 0ULL; + unsigned long long sutime_macos_iokit = 0ULL; usec_t step = rrd_update_every * USEC_PER_SEC; for(;;) { @@ -57,6 +59,14 @@ void *macos_main(void *ptr) } if(unlikely(netdata_exit)) break; + if(!vdo_macos_iokit) { + debug(D_PROCNETDEV_LOOP, "MACOS: calling do_macos_iokit()."); + now = now_realtime_usec(); + vdo_macos_iokit = do_macos_iokit(rrd_update_every, (sutime_macos_iokit > 0)?now - sutime_macos_iokit:0ULL); + sutime_macos_iokit = now; + } + if(unlikely(netdata_exit)) break; + // END -- the job is done // -------------------------------------------------------------------- diff --git a/src/plugin_macos.h b/src/plugin_macos.h index b903ff5ba7f289..a6f966a87e0e72 100644 --- a/src/plugin_macos.h +++ b/src/plugin_macos.h @@ -5,5 +5,6 @@ void *macos_main(void *ptr); extern int do_macos_sysctl(int update_every, usec_t dt); extern int do_macos_mach_smi(int update_every, usec_t dt); +extern int do_macos_iokit(int update_every, usec_t dt); #endif /* NETDATA_PLUGIN_MACOS_H */