summaryrefslogtreecommitdiffstats
path: root/collectors/macos.plugin/macos_fw.c
diff options
context:
space:
mode:
Diffstat (limited to 'collectors/macos.plugin/macos_fw.c')
-rw-r--r--collectors/macos.plugin/macos_fw.c687
1 files changed, 687 insertions, 0 deletions
diff --git a/collectors/macos.plugin/macos_fw.c b/collectors/macos.plugin/macos_fw.c
new file mode 100644
index 000000000..5d0ba929e
--- /dev/null
+++ b/collectors/macos.plugin/macos_fw.c
@@ -0,0 +1,687 @@
+// SPDX-License-Identifier: GPL-3.0-or-later
+
+#include "plugin_macos.h"
+
+#include <CoreFoundation/CoreFoundation.h>
+#include <IOKit/IOKitLib.h>
+#include <IOKit/storage/IOBlockStorageDriver.h>
+#include <IOKit/IOBSD.h>
+// NEEDED BY do_space, do_inodes
+#include <sys/mount.h>
+// NEEDED BY: struct ifaddrs, getifaddrs()
+#include <net/if.h>
+#include <ifaddrs.h>
+
+// NEEDED BY: do_bandwidth
+#define IFA_DATA(s) (((struct if_data *)ifa->ifa_data)->ifi_ ## s)
+
+#define MAXDRIVENAME 31
+
+#define KILO_FACTOR 1024
+#define MEGA_FACTOR 1048576 // 1024 * 1024
+#define GIGA_FACTOR 1073741824 // 1024 * 1024 * 1024
+
+int do_macos_iokit(int update_every, usec_t dt) {
+ (void)dt;
+
+ static int do_io = -1, do_space = -1, do_inodes = -1, do_bandwidth = -1;
+
+ if (unlikely(do_io == -1)) {
+ do_io = config_get_boolean("plugin:macos:iokit", "disk i/o", 1);
+ do_space = config_get_boolean("plugin:macos:sysctl", "space usage for all disks", 1);
+ do_inodes = config_get_boolean("plugin:macos:sysctl", "inodes usage for all disks", 1);
+ do_bandwidth = config_get_boolean("plugin:macos:sysctl", "bandwidth", 1);
+ }
+
+ RRDSET *st;
+
+ mach_port_t master_port;
+ io_registry_entry_t drive, drive_media;
+ io_iterator_t drive_list;
+ CFDictionaryRef properties, statistics;
+ CFStringRef name;
+ CFNumberRef number;
+ kern_return_t status;
+ collected_number total_disk_reads = 0;
+ collected_number total_disk_writes = 0;
+ struct diskstat {
+ char name[MAXDRIVENAME];
+ collected_number bytes_read;
+ collected_number bytes_write;
+ collected_number reads;
+ collected_number writes;
+ collected_number time_read;
+ collected_number time_write;
+ collected_number latency_read;
+ collected_number latency_write;
+ } diskstat;
+ struct cur_diskstat {
+ collected_number duration_read_ns;
+ collected_number duration_write_ns;
+ collected_number busy_time_ns;
+ } cur_diskstat;
+ struct prev_diskstat {
+ collected_number bytes_read;
+ collected_number bytes_write;
+ collected_number operations_read;
+ collected_number operations_write;
+ collected_number duration_read_ns;
+ collected_number duration_write_ns;
+ collected_number busy_time_ns;
+ } prev_diskstat;
+
+ // NEEDED BY: do_space, do_inodes
+ struct statfs *mntbuf;
+ int mntsize, i;
+ char mntonname[MNAMELEN + 1];
+ char title[4096 + 1];
+
+ // NEEDED BY: do_bandwidth
+ struct ifaddrs *ifa, *ifap;
+
+ /* Get ports and services for drive statistics. */
+ if (unlikely(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 (unlikely(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) {
+ properties = 0;
+ statistics = 0;
+ number = 0;
+ bzero(&diskstat, sizeof(diskstat));
+
+ /* Get drive media object. */
+ status = IORegistryEntryGetChildEntry(drive, kIOServicePlane, &drive_media);
+ if (unlikely(status != KERN_SUCCESS)) {
+ IOObjectRelease(drive);
+ continue;
+ }
+
+ /* Get drive media properties. */
+ if (likely(!IORegistryEntryCreateCFProperties(drive_media, (CFMutableDictionaryRef *)&properties, kCFAllocatorDefault, 0))) {
+ /* Get disk name. */
+ if (likely(name = (CFStringRef)CFDictionaryGetValue(properties, CFSTR(kIOBSDNameKey)))) {
+ CFStringGetCString(name, diskstat.name, MAXDRIVENAME, kCFStringEncodingUTF8);
+ }
+ }
+
+ /* Release. */
+ CFRelease(properties);
+ IOObjectRelease(drive_media);
+
+ if(unlikely(!diskstat.name || !*diskstat.name)) {
+ IOObjectRelease(drive);
+ continue;
+ }
+
+ /* Obtain the properties for this drive object. */
+ if (unlikely(IORegistryEntryCreateCFProperties(drive, (CFMutableDictionaryRef *)&properties, kCFAllocatorDefault, 0))) {
+ IOObjectRelease(drive);
+ error("MACOS: IORegistryEntryCreateCFProperties() failed");
+ do_io = 0;
+ error("DISABLED: system.io");
+ break;
+ } else if (likely(properties)) {
+ /* Obtain the statistics from the drive properties. */
+ if (likely(statistics = (CFDictionaryRef)CFDictionaryGetValue(properties, CFSTR(kIOBlockStorageDriverStatisticsKey)))) {
+
+ // --------------------------------------------------------------------
+
+ /* Get bytes read. */
+ if (likely(number = (CFNumberRef)CFDictionaryGetValue(statistics, CFSTR(kIOBlockStorageDriverStatisticsBytesReadKey)))) {
+ CFNumberGetValue(number, kCFNumberSInt64Type, &diskstat.bytes_read);
+ total_disk_reads += diskstat.bytes_read;
+ }
+
+ /* Get bytes written. */
+ if (likely(number = (CFNumberRef)CFDictionaryGetValue(statistics, CFSTR(kIOBlockStorageDriverStatisticsBytesWrittenKey)))) {
+ CFNumberGetValue(number, kCFNumberSInt64Type, &diskstat.bytes_write);
+ total_disk_writes += diskstat.bytes_write;
+ }
+
+ st = rrdset_find_bytype_localhost("disk", diskstat.name);
+ if (unlikely(!st)) {
+ st = rrdset_create_localhost(
+ "disk"
+ , diskstat.name
+ , NULL
+ , diskstat.name
+ , "disk.io"
+ , "Disk I/O Bandwidth"
+ , "kilobytes/s"
+ , "macos"
+ , "iokit"
+ , 2000
+ , update_every
+ , RRDSET_TYPE_AREA
+ );
+
+ rrddim_add(st, "reads", NULL, 1, 1024, RRD_ALGORITHM_INCREMENTAL);
+ rrddim_add(st, "writes", NULL, -1, 1024, RRD_ALGORITHM_INCREMENTAL);
+ }
+ else rrdset_next(st);
+
+ prev_diskstat.bytes_read = rrddim_set(st, "reads", diskstat.bytes_read);
+ prev_diskstat.bytes_write = rrddim_set(st, "writes", diskstat.bytes_write);
+ rrdset_done(st);
+
+ // --------------------------------------------------------------------
+
+ /* Get number of reads. */
+ if (likely(number = (CFNumberRef)CFDictionaryGetValue(statistics, CFSTR(kIOBlockStorageDriverStatisticsReadsKey)))) {
+ CFNumberGetValue(number, kCFNumberSInt64Type, &diskstat.reads);
+ }
+
+ /* Get number of writes. */
+ if (likely(number = (CFNumberRef)CFDictionaryGetValue(statistics, CFSTR(kIOBlockStorageDriverStatisticsWritesKey)))) {
+ CFNumberGetValue(number, kCFNumberSInt64Type, &diskstat.writes);
+ }
+
+ st = rrdset_find_bytype_localhost("disk_ops", diskstat.name);
+ if (unlikely(!st)) {
+ st = rrdset_create_localhost(
+ "disk_ops"
+ , diskstat.name
+ , NULL
+ , diskstat.name
+ , "disk.ops"
+ , "Disk Completed I/O Operations"
+ , "operations/s"
+ , "macos"
+ , "iokit"
+ , 2001
+ , update_every
+ , RRDSET_TYPE_LINE
+ );
+ rrdset_flag_set(st, RRDSET_FLAG_DETAIL);
+
+ rrddim_add(st, "reads", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
+ rrddim_add(st, "writes", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL);
+ }
+ else rrdset_next(st);
+
+ prev_diskstat.operations_read = rrddim_set(st, "reads", diskstat.reads);
+ prev_diskstat.operations_write = rrddim_set(st, "writes", diskstat.writes);
+ rrdset_done(st);
+
+ // --------------------------------------------------------------------
+
+ /* Get reads time. */
+ if (likely(number = (CFNumberRef)CFDictionaryGetValue(statistics, CFSTR(kIOBlockStorageDriverStatisticsTotalReadTimeKey)))) {
+ CFNumberGetValue(number, kCFNumberSInt64Type, &diskstat.time_read);
+ }
+
+ /* Get writes time. */
+ if (likely(number = (CFNumberRef)CFDictionaryGetValue(statistics, CFSTR(kIOBlockStorageDriverStatisticsTotalWriteTimeKey)))) {
+ CFNumberGetValue(number, kCFNumberSInt64Type, &diskstat.time_write);
+ }
+
+ st = rrdset_find_bytype_localhost("disk_util", diskstat.name);
+ if (unlikely(!st)) {
+ st = rrdset_create_localhost(
+ "disk_util"
+ , diskstat.name
+ , NULL
+ , diskstat.name
+ , "disk.util"
+ , "Disk Utilization Time"
+ , "% of time working"
+ , "macos"
+ , "iokit"
+ , 2004
+ , update_every
+ , RRDSET_TYPE_AREA
+ );
+ rrdset_flag_set(st, RRDSET_FLAG_DETAIL);
+
+ rrddim_add(st, "utilization", NULL, 1, 10000000, RRD_ALGORITHM_INCREMENTAL);
+ }
+ else rrdset_next(st);
+
+ cur_diskstat.busy_time_ns = (diskstat.time_read + diskstat.time_write);
+ prev_diskstat.busy_time_ns = rrddim_set(st, "utilization", cur_diskstat.busy_time_ns);
+ rrdset_done(st);
+
+ // --------------------------------------------------------------------
+
+ /* Get reads latency. */
+ if (likely(number = (CFNumberRef)CFDictionaryGetValue(statistics, CFSTR(kIOBlockStorageDriverStatisticsLatentReadTimeKey)))) {
+ CFNumberGetValue(number, kCFNumberSInt64Type, &diskstat.latency_read);
+ }
+
+ /* Get writes latency. */
+ if (likely(number = (CFNumberRef)CFDictionaryGetValue(statistics, CFSTR(kIOBlockStorageDriverStatisticsLatentWriteTimeKey)))) {
+ CFNumberGetValue(number, kCFNumberSInt64Type, &diskstat.latency_write);
+ }
+
+ st = rrdset_find_bytype_localhost("disk_iotime", diskstat.name);
+ if (unlikely(!st)) {
+ st = rrdset_create_localhost(
+ "disk_iotime"
+ , diskstat.name
+ , NULL
+ , diskstat.name
+ , "disk.iotime"
+ , "Disk Total I/O Time"
+ , "milliseconds/s"
+ , "macos"
+ , "iokit"
+ , 2022
+ , update_every
+ , RRDSET_TYPE_LINE
+ );
+ rrdset_flag_set(st, RRDSET_FLAG_DETAIL);
+
+ rrddim_add(st, "reads", NULL, 1, 1000000, RRD_ALGORITHM_INCREMENTAL);
+ rrddim_add(st, "writes", NULL, -1, 1000000, RRD_ALGORITHM_INCREMENTAL);
+ }
+ else rrdset_next(st);
+
+ cur_diskstat.duration_read_ns = diskstat.time_read + diskstat.latency_read;
+ cur_diskstat.duration_write_ns = diskstat.time_write + diskstat.latency_write;
+ prev_diskstat.duration_read_ns = rrddim_set(st, "reads", cur_diskstat.duration_read_ns);
+ prev_diskstat.duration_write_ns = rrddim_set(st, "writes", cur_diskstat.duration_write_ns);
+ rrdset_done(st);
+
+ // --------------------------------------------------------------------
+ // calculate differential charts
+ // only if this is not the first time we run
+
+ if (likely(dt)) {
+
+ // --------------------------------------------------------------------
+
+ st = rrdset_find_bytype_localhost("disk_await", diskstat.name);
+ if (unlikely(!st)) {
+ st = rrdset_create_localhost(
+ "disk_await"
+ , diskstat.name
+ , NULL
+ , diskstat.name
+ , "disk.await"
+ , "Average Completed I/O Operation Time"
+ , "ms per operation"
+ , "macos"
+ , "iokit"
+ , 2005
+ , update_every
+ , RRDSET_TYPE_LINE
+ );
+ rrdset_flag_set(st, RRDSET_FLAG_DETAIL);
+
+ rrddim_add(st, "reads", NULL, 1, 1000000, RRD_ALGORITHM_ABSOLUTE);
+ rrddim_add(st, "writes", NULL, -1, 1000000, RRD_ALGORITHM_ABSOLUTE);
+ }
+ else rrdset_next(st);
+
+ rrddim_set(st, "reads", (diskstat.reads - prev_diskstat.operations_read) ?
+ (cur_diskstat.duration_read_ns - prev_diskstat.duration_read_ns) / (diskstat.reads - prev_diskstat.operations_read) : 0);
+ rrddim_set(st, "writes", (diskstat.writes - prev_diskstat.operations_write) ?
+ (cur_diskstat.duration_write_ns - prev_diskstat.duration_write_ns) / (diskstat.writes - prev_diskstat.operations_write) : 0);
+ rrdset_done(st);
+
+ // --------------------------------------------------------------------
+
+ st = rrdset_find_bytype_localhost("disk_avgsz", diskstat.name);
+ if (unlikely(!st)) {
+ st = rrdset_create_localhost(
+ "disk_avgsz"
+ , diskstat.name
+ , NULL
+ , diskstat.name
+ , "disk.avgsz"
+ , "Average Completed I/O Operation Bandwidth"
+ , "kilobytes per operation"
+ , "macos"
+ , "iokit"
+ , 2006
+ , update_every
+ , RRDSET_TYPE_AREA
+ );
+ rrdset_flag_set(st, RRDSET_FLAG_DETAIL);
+
+ rrddim_add(st, "reads", NULL, 1, 1024, RRD_ALGORITHM_ABSOLUTE);
+ rrddim_add(st, "writes", NULL, -1, 1024, RRD_ALGORITHM_ABSOLUTE);
+ }
+ else rrdset_next(st);
+
+ rrddim_set(st, "reads", (diskstat.reads - prev_diskstat.operations_read) ?
+ (diskstat.bytes_read - prev_diskstat.bytes_read) / (diskstat.reads - prev_diskstat.operations_read) : 0);
+ rrddim_set(st, "writes", (diskstat.writes - prev_diskstat.operations_write) ?
+ (diskstat.bytes_write - prev_diskstat.bytes_write) / (diskstat.writes - prev_diskstat.operations_write) : 0);
+ rrdset_done(st);
+
+ // --------------------------------------------------------------------
+
+ st = rrdset_find_bytype_localhost("disk_svctm", diskstat.name);
+ if (unlikely(!st)) {
+ st = rrdset_create_localhost(
+ "disk_svctm"
+ , diskstat.name
+ , NULL
+ , diskstat.name
+ , "disk.svctm"
+ , "Average Service Time"
+ , "ms per operation"
+ , "macos"
+ , "iokit"
+ , 2007
+ , update_every
+ , RRDSET_TYPE_LINE
+ );
+ rrdset_flag_set(st, RRDSET_FLAG_DETAIL);
+
+ rrddim_add(st, "svctm", NULL, 1, 1000000, RRD_ALGORITHM_ABSOLUTE);
+ }
+ else rrdset_next(st);
+
+ rrddim_set(st, "svctm", ((diskstat.reads - prev_diskstat.operations_read) + (diskstat.writes - prev_diskstat.operations_write)) ?
+ (cur_diskstat.busy_time_ns - prev_diskstat.busy_time_ns) / ((diskstat.reads - prev_diskstat.operations_read) + (diskstat.writes - prev_diskstat.operations_write)) : 0);
+ rrdset_done(st);
+ }
+ }
+
+ /* Release. */
+ CFRelease(properties);
+ }
+
+ /* Release. */
+ IOObjectRelease(drive);
+ }
+ IOIteratorReset(drive_list);
+
+ /* Release. */
+ IOObjectRelease(drive_list);
+ }
+
+ if (likely(do_io)) {
+ st = rrdset_find_bytype_localhost("system", "io");
+ if (unlikely(!st)) {
+ st = rrdset_create_localhost(
+ "system"
+ , "io"
+ , NULL
+ , "disk"
+ , NULL
+ , "Disk I/O"
+ , "kilobytes/s"
+ , "macos"
+ , "iokit"
+ , 150
+ , update_every
+ , RRDSET_TYPE_AREA
+ );
+ rrddim_add(st, "in", NULL, 1, 1024, RRD_ALGORITHM_INCREMENTAL);
+ rrddim_add(st, "out", NULL, -1, 1024, RRD_ALGORITHM_INCREMENTAL);
+ }
+ else rrdset_next(st);
+
+ rrddim_set(st, "in", total_disk_reads);
+ rrddim_set(st, "out", total_disk_writes);
+ rrdset_done(st);
+ }
+
+ // Can be merged with FreeBSD plugin
+ // --------------------------------------------------------------------------
+
+ if (likely(do_space || do_inodes)) {
+ // there is no mount info in sysctl MIBs
+ if (unlikely(!(mntsize = getmntinfo(&mntbuf, MNT_NOWAIT)))) {
+ error("MACOS: getmntinfo() failed");
+ do_space = 0;
+ error("DISABLED: disk_space.X");
+ do_inodes = 0;
+ error("DISABLED: disk_inodes.X");
+ } else {
+ for (i = 0; i < mntsize; i++) {
+ if (mntbuf[i].f_flags == MNT_RDONLY ||
+ mntbuf[i].f_blocks == 0 ||
+ // taken from gnulib/mountlist.c and shortened to FreeBSD related fstypes
+ strcmp(mntbuf[i].f_fstypename, "autofs") == 0 ||
+ strcmp(mntbuf[i].f_fstypename, "procfs") == 0 ||
+ strcmp(mntbuf[i].f_fstypename, "subfs") == 0 ||
+ strcmp(mntbuf[i].f_fstypename, "devfs") == 0 ||
+ strcmp(mntbuf[i].f_fstypename, "none") == 0)
+ continue;
+
+ // --------------------------------------------------------------------------
+
+ if (likely(do_space)) {
+ st = rrdset_find_bytype_localhost("disk_space", mntbuf[i].f_mntonname);
+ if (unlikely(!st)) {
+ snprintfz(title, 4096, "Disk Space Usage for %s [%s]", mntbuf[i].f_mntonname, mntbuf[i].f_mntfromname);
+ st = rrdset_create_localhost(
+ "disk_space"
+ , mntbuf[i].f_mntonname
+ , NULL
+ , mntbuf[i].f_mntonname
+ , "disk.space"
+ , title
+ , "GB"
+ , "macos"
+ , "iokit"
+ , 2023
+ , update_every
+ , RRDSET_TYPE_STACKED
+ );
+
+ rrddim_add(st, "avail", NULL, mntbuf[i].f_bsize, GIGA_FACTOR, RRD_ALGORITHM_ABSOLUTE);
+ rrddim_add(st, "used", NULL, mntbuf[i].f_bsize, GIGA_FACTOR, RRD_ALGORITHM_ABSOLUTE);
+ rrddim_add(st, "reserved_for_root", "reserved for root", mntbuf[i].f_bsize, GIGA_FACTOR, RRD_ALGORITHM_ABSOLUTE);
+ } else
+ rrdset_next(st);
+
+ rrddim_set(st, "avail", (collected_number) mntbuf[i].f_bavail);
+ rrddim_set(st, "used", (collected_number) (mntbuf[i].f_blocks - mntbuf[i].f_bfree));
+ rrddim_set(st, "reserved_for_root", (collected_number) (mntbuf[i].f_bfree - mntbuf[i].f_bavail));
+ rrdset_done(st);
+ }
+
+ // --------------------------------------------------------------------------
+
+ if (likely(do_inodes)) {
+ st = rrdset_find_bytype_localhost("disk_inodes", mntbuf[i].f_mntonname);
+ if (unlikely(!st)) {
+ snprintfz(title, 4096, "Disk Files (inodes) Usage for %s [%s]", mntbuf[i].f_mntonname, mntbuf[i].f_mntfromname);
+ st = rrdset_create_localhost(
+ "disk_inodes"
+ , mntbuf[i].f_mntonname
+ , NULL
+ , mntbuf[i].f_mntonname
+ , "disk.inodes"
+ , title
+ , "Inodes"
+ , "macos"
+ , "iokit"
+ , 2024
+ , update_every
+ , RRDSET_TYPE_STACKED
+ );
+
+ rrddim_add(st, "avail", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE);
+ rrddim_add(st, "used", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE);
+ rrddim_add(st, "reserved_for_root", "reserved for root", 1, 1, RRD_ALGORITHM_ABSOLUTE);
+ } else
+ rrdset_next(st);
+
+ rrddim_set(st, "avail", (collected_number) mntbuf[i].f_ffree);
+ rrddim_set(st, "used", (collected_number) (mntbuf[i].f_files - mntbuf[i].f_ffree));
+ rrdset_done(st);
+ }
+ }
+ }
+ }
+
+ // Can be merged with FreeBSD plugin
+ // --------------------------------------------------------------------
+
+ if (likely(do_bandwidth)) {
+ if (unlikely(getifaddrs(&ifap))) {
+ error("MACOS: getifaddrs()");
+ do_bandwidth = 0;
+ error("DISABLED: system.ipv4");
+ } else {
+ for (ifa = ifap; ifa; ifa = ifa->ifa_next) {
+ if (ifa->ifa_addr->sa_family != AF_LINK)
+ continue;
+
+ // --------------------------------------------------------------------
+
+ st = rrdset_find_bytype_localhost("net", ifa->ifa_name);
+ if (unlikely(!st)) {
+ st = rrdset_create_localhost(
+ "net"
+ , ifa->ifa_name
+ , NULL
+ , ifa->ifa_name
+ , "net.net"
+ , "Bandwidth"
+ , "kilobits/s"
+ , "macos"
+ , "iokit"
+ , 7000
+ , update_every
+ , RRDSET_TYPE_AREA
+ );
+
+ rrddim_add(st, "received", NULL, 8, BITS_IN_A_KILOBIT, RRD_ALGORITHM_INCREMENTAL);
+ rrddim_add(st, "sent", NULL, -8, BITS_IN_A_KILOBIT, RRD_ALGORITHM_INCREMENTAL);
+ }
+ else rrdset_next(st);
+
+ rrddim_set(st, "received", IFA_DATA(ibytes));
+ rrddim_set(st, "sent", IFA_DATA(obytes));
+ rrdset_done(st);
+
+ // --------------------------------------------------------------------
+
+ st = rrdset_find_bytype_localhost("net_packets", ifa->ifa_name);
+ if (unlikely(!st)) {
+ st = rrdset_create_localhost(
+ "net_packets"
+ , ifa->ifa_name
+ , NULL
+ , ifa->ifa_name
+ , "net.packets"
+ , "Packets"
+ , "packets/s"
+ , "macos"
+ , "iokit"
+ , 7001
+ , update_every
+ , RRDSET_TYPE_LINE
+ );
+ rrdset_flag_set(st, RRDSET_FLAG_DETAIL);
+
+ rrddim_add(st, "received", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
+ rrddim_add(st, "sent", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL);
+ rrddim_add(st, "multicast_received", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
+ rrddim_add(st, "multicast_sent", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL);
+ }
+ else rrdset_next(st);
+
+ rrddim_set(st, "received", IFA_DATA(ipackets));
+ rrddim_set(st, "sent", IFA_DATA(opackets));
+ rrddim_set(st, "multicast_received", IFA_DATA(imcasts));
+ rrddim_set(st, "multicast_sent", IFA_DATA(omcasts));
+ rrdset_done(st);
+
+ // --------------------------------------------------------------------
+
+ st = rrdset_find_bytype_localhost("net_errors", ifa->ifa_name);
+ if (unlikely(!st)) {
+ st = rrdset_create_localhost(
+ "net_errors"
+ , ifa->ifa_name
+ , NULL
+ , ifa->ifa_name
+ , "net.errors"
+ , "Interface Errors"
+ , "errors/s"
+ , "macos"
+ , "iokit"
+ , 7002
+ , update_every
+ , RRDSET_TYPE_LINE
+ );
+ rrdset_flag_set(st, RRDSET_FLAG_DETAIL);
+
+ rrddim_add(st, "inbound", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
+ rrddim_add(st, "outbound", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL);
+ }
+ else rrdset_next(st);
+
+ rrddim_set(st, "inbound", IFA_DATA(ierrors));
+ rrddim_set(st, "outbound", IFA_DATA(oerrors));
+ rrdset_done(st);
+
+ // --------------------------------------------------------------------
+
+ st = rrdset_find_bytype_localhost("net_drops", ifa->ifa_name);
+ if (unlikely(!st)) {
+ st = rrdset_create_localhost(
+ "net_drops"
+ , ifa->ifa_name
+ , NULL
+ , ifa->ifa_name
+ , "net.drops"
+ , "Interface Drops"
+ , "drops/s"
+ , "macos"
+ , "iokit"
+ , 7003
+ , update_every
+ , RRDSET_TYPE_LINE
+ );
+ rrdset_flag_set(st, RRDSET_FLAG_DETAIL);
+
+ rrddim_add(st, "inbound", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
+ }
+ else rrdset_next(st);
+
+ rrddim_set(st, "inbound", IFA_DATA(iqdrops));
+ rrdset_done(st);
+
+ // --------------------------------------------------------------------
+
+ st = rrdset_find_bytype_localhost("net_events", ifa->ifa_name);
+ if (unlikely(!st)) {
+ st = rrdset_create_localhost(
+ "net_events"
+ , ifa->ifa_name
+ , NULL
+ , ifa->ifa_name
+ , "net.events"
+ , "Network Interface Events"
+ , "events/s"
+ , "macos"
+ , "iokit"
+ , 7006
+ , update_every
+ , RRDSET_TYPE_LINE
+ );
+ rrdset_flag_set(st, RRDSET_FLAG_DETAIL);
+
+ rrddim_add(st, "frames", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
+ rrddim_add(st, "collisions", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL);
+ rrddim_add(st, "carrier", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL);
+ }
+ else rrdset_next(st);
+
+ rrddim_set(st, "collisions", IFA_DATA(collisions));
+ rrdset_done(st);
+ }
+
+ freeifaddrs(ifap);
+ }
+ }
+
+
+ return 0;
+}