macos_fw.c 31 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690
  1. // SPDX-License-Identifier: GPL-3.0-or-later
  2. #include "plugin_macos.h"
  3. #include <CoreFoundation/CoreFoundation.h>
  4. #include <IOKit/IOKitLib.h>
  5. #include <IOKit/storage/IOBlockStorageDriver.h>
  6. #include <IOKit/IOBSD.h>
  7. // NEEDED BY do_space, do_inodes
  8. #include <sys/mount.h>
  9. // NEEDED BY: struct ifaddrs, getifaddrs()
  10. #include <net/if.h>
  11. #include <ifaddrs.h>
  12. // NEEDED BY: do_bandwidth
  13. #define IFA_DATA(s) (((struct if_data *)ifa->ifa_data)->ifi_ ## s)
  14. #define MAXDRIVENAME 31
  15. #define KILO_FACTOR 1024
  16. #define MEGA_FACTOR 1048576 // 1024 * 1024
  17. #define GIGA_FACTOR 1073741824 // 1024 * 1024 * 1024
  18. int do_macos_iokit(int update_every, usec_t dt) {
  19. (void)dt;
  20. static int do_io = -1, do_space = -1, do_inodes = -1, do_bandwidth = -1;
  21. if (unlikely(do_io == -1)) {
  22. do_io = config_get_boolean("plugin:macos:iokit", "disk i/o", 1);
  23. do_space = config_get_boolean("plugin:macos:sysctl", "space usage for all disks", 1);
  24. do_inodes = config_get_boolean("plugin:macos:sysctl", "inodes usage for all disks", 1);
  25. do_bandwidth = config_get_boolean("plugin:macos:sysctl", "bandwidth", 1);
  26. }
  27. RRDSET *st;
  28. mach_port_t main_port;
  29. io_registry_entry_t drive, drive_media;
  30. io_iterator_t drive_list;
  31. CFDictionaryRef properties, statistics;
  32. CFStringRef name;
  33. CFNumberRef number;
  34. kern_return_t status;
  35. collected_number total_disk_reads = 0;
  36. collected_number total_disk_writes = 0;
  37. struct diskstat {
  38. char name[MAXDRIVENAME];
  39. collected_number bytes_read;
  40. collected_number bytes_write;
  41. collected_number reads;
  42. collected_number writes;
  43. collected_number time_read;
  44. collected_number time_write;
  45. collected_number latency_read;
  46. collected_number latency_write;
  47. } diskstat;
  48. struct cur_diskstat {
  49. collected_number duration_read_ns;
  50. collected_number duration_write_ns;
  51. collected_number busy_time_ns;
  52. } cur_diskstat;
  53. struct prev_diskstat {
  54. collected_number bytes_read;
  55. collected_number bytes_write;
  56. collected_number operations_read;
  57. collected_number operations_write;
  58. collected_number duration_read_ns;
  59. collected_number duration_write_ns;
  60. collected_number busy_time_ns;
  61. } prev_diskstat;
  62. // NEEDED BY: do_space, do_inodes
  63. struct statfs *mntbuf;
  64. int mntsize, i;
  65. char title[4096 + 1];
  66. // NEEDED BY: do_bandwidth
  67. struct ifaddrs *ifa, *ifap;
  68. #if !defined(MAC_OS_VERSION_12_0) || (MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_VERSION_12_0)
  69. #define IOMainPort IOMasterPort
  70. #endif
  71. /* Get ports and services for drive statistics. */
  72. if (unlikely(IOMainPort(bootstrap_port, &main_port))) {
  73. error("MACOS: IOMasterPort() failed");
  74. do_io = 0;
  75. error("DISABLED: system.io");
  76. /* Get the list of all drive objects. */
  77. } else if (unlikely(IOServiceGetMatchingServices(main_port, IOServiceMatching("IOBlockStorageDriver"), &drive_list))) {
  78. error("MACOS: IOServiceGetMatchingServices() failed");
  79. do_io = 0;
  80. error("DISABLED: system.io");
  81. } else {
  82. while ((drive = IOIteratorNext(drive_list)) != 0) {
  83. properties = 0;
  84. statistics = 0;
  85. number = 0;
  86. bzero(&diskstat, sizeof(diskstat));
  87. /* Get drive media object. */
  88. status = IORegistryEntryGetChildEntry(drive, kIOServicePlane, &drive_media);
  89. if (unlikely(status != KERN_SUCCESS)) {
  90. IOObjectRelease(drive);
  91. continue;
  92. }
  93. /* Get drive media properties. */
  94. if (likely(!IORegistryEntryCreateCFProperties(drive_media, (CFMutableDictionaryRef *)&properties, kCFAllocatorDefault, 0))) {
  95. /* Get disk name. */
  96. if (likely(name = (CFStringRef)CFDictionaryGetValue(properties, CFSTR(kIOBSDNameKey)))) {
  97. CFStringGetCString(name, diskstat.name, MAXDRIVENAME, kCFStringEncodingUTF8);
  98. }
  99. }
  100. /* Release. */
  101. CFRelease(properties);
  102. IOObjectRelease(drive_media);
  103. if(unlikely(!*diskstat.name)) {
  104. IOObjectRelease(drive);
  105. continue;
  106. }
  107. /* Obtain the properties for this drive object. */
  108. if (unlikely(IORegistryEntryCreateCFProperties(drive, (CFMutableDictionaryRef *)&properties, kCFAllocatorDefault, 0))) {
  109. IOObjectRelease(drive);
  110. error("MACOS: IORegistryEntryCreateCFProperties() failed");
  111. do_io = 0;
  112. error("DISABLED: system.io");
  113. break;
  114. } else if (likely(properties)) {
  115. /* Obtain the statistics from the drive properties. */
  116. if (likely(statistics = (CFDictionaryRef)CFDictionaryGetValue(properties, CFSTR(kIOBlockStorageDriverStatisticsKey)))) {
  117. // --------------------------------------------------------------------
  118. /* Get bytes read. */
  119. if (likely(number = (CFNumberRef)CFDictionaryGetValue(statistics, CFSTR(kIOBlockStorageDriverStatisticsBytesReadKey)))) {
  120. CFNumberGetValue(number, kCFNumberSInt64Type, &diskstat.bytes_read);
  121. total_disk_reads += diskstat.bytes_read;
  122. }
  123. /* Get bytes written. */
  124. if (likely(number = (CFNumberRef)CFDictionaryGetValue(statistics, CFSTR(kIOBlockStorageDriverStatisticsBytesWrittenKey)))) {
  125. CFNumberGetValue(number, kCFNumberSInt64Type, &diskstat.bytes_write);
  126. total_disk_writes += diskstat.bytes_write;
  127. }
  128. st = rrdset_find_active_bytype_localhost("disk", diskstat.name);
  129. if (unlikely(!st)) {
  130. st = rrdset_create_localhost(
  131. "disk"
  132. , diskstat.name
  133. , NULL
  134. , diskstat.name
  135. , "disk.io"
  136. , "Disk I/O Bandwidth"
  137. , "KiB/s"
  138. , "macos.plugin"
  139. , "iokit"
  140. , 2000
  141. , update_every
  142. , RRDSET_TYPE_AREA
  143. );
  144. rrddim_add(st, "reads", NULL, 1, 1024, RRD_ALGORITHM_INCREMENTAL);
  145. rrddim_add(st, "writes", NULL, -1, 1024, RRD_ALGORITHM_INCREMENTAL);
  146. }
  147. else rrdset_next(st);
  148. prev_diskstat.bytes_read = rrddim_set(st, "reads", diskstat.bytes_read);
  149. prev_diskstat.bytes_write = rrddim_set(st, "writes", diskstat.bytes_write);
  150. rrdset_done(st);
  151. // --------------------------------------------------------------------
  152. /* Get number of reads. */
  153. if (likely(number = (CFNumberRef)CFDictionaryGetValue(statistics, CFSTR(kIOBlockStorageDriverStatisticsReadsKey)))) {
  154. CFNumberGetValue(number, kCFNumberSInt64Type, &diskstat.reads);
  155. }
  156. /* Get number of writes. */
  157. if (likely(number = (CFNumberRef)CFDictionaryGetValue(statistics, CFSTR(kIOBlockStorageDriverStatisticsWritesKey)))) {
  158. CFNumberGetValue(number, kCFNumberSInt64Type, &diskstat.writes);
  159. }
  160. st = rrdset_find_active_bytype_localhost("disk_ops", diskstat.name);
  161. if (unlikely(!st)) {
  162. st = rrdset_create_localhost(
  163. "disk_ops"
  164. , diskstat.name
  165. , NULL
  166. , diskstat.name
  167. , "disk.ops"
  168. , "Disk Completed I/O Operations"
  169. , "operations/s"
  170. , "macos.plugin"
  171. , "iokit"
  172. , 2001
  173. , update_every
  174. , RRDSET_TYPE_LINE
  175. );
  176. rrdset_flag_set(st, RRDSET_FLAG_DETAIL);
  177. rrddim_add(st, "reads", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
  178. rrddim_add(st, "writes", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL);
  179. }
  180. else rrdset_next(st);
  181. prev_diskstat.operations_read = rrddim_set(st, "reads", diskstat.reads);
  182. prev_diskstat.operations_write = rrddim_set(st, "writes", diskstat.writes);
  183. rrdset_done(st);
  184. // --------------------------------------------------------------------
  185. /* Get reads time. */
  186. if (likely(number = (CFNumberRef)CFDictionaryGetValue(statistics, CFSTR(kIOBlockStorageDriverStatisticsTotalReadTimeKey)))) {
  187. CFNumberGetValue(number, kCFNumberSInt64Type, &diskstat.time_read);
  188. }
  189. /* Get writes time. */
  190. if (likely(number = (CFNumberRef)CFDictionaryGetValue(statistics, CFSTR(kIOBlockStorageDriverStatisticsTotalWriteTimeKey)))) {
  191. CFNumberGetValue(number, kCFNumberSInt64Type, &diskstat.time_write);
  192. }
  193. st = rrdset_find_active_bytype_localhost("disk_util", diskstat.name);
  194. if (unlikely(!st)) {
  195. st = rrdset_create_localhost(
  196. "disk_util"
  197. , diskstat.name
  198. , NULL
  199. , diskstat.name
  200. , "disk.util"
  201. , "Disk Utilization Time"
  202. , "% of time working"
  203. , "macos.plugin"
  204. , "iokit"
  205. , 2004
  206. , update_every
  207. , RRDSET_TYPE_AREA
  208. );
  209. rrdset_flag_set(st, RRDSET_FLAG_DETAIL);
  210. rrddim_add(st, "utilization", NULL, 1, 10000000, RRD_ALGORITHM_INCREMENTAL);
  211. }
  212. else rrdset_next(st);
  213. cur_diskstat.busy_time_ns = (diskstat.time_read + diskstat.time_write);
  214. prev_diskstat.busy_time_ns = rrddim_set(st, "utilization", cur_diskstat.busy_time_ns);
  215. rrdset_done(st);
  216. // --------------------------------------------------------------------
  217. /* Get reads latency. */
  218. if (likely(number = (CFNumberRef)CFDictionaryGetValue(statistics, CFSTR(kIOBlockStorageDriverStatisticsLatentReadTimeKey)))) {
  219. CFNumberGetValue(number, kCFNumberSInt64Type, &diskstat.latency_read);
  220. }
  221. /* Get writes latency. */
  222. if (likely(number = (CFNumberRef)CFDictionaryGetValue(statistics, CFSTR(kIOBlockStorageDriverStatisticsLatentWriteTimeKey)))) {
  223. CFNumberGetValue(number, kCFNumberSInt64Type, &diskstat.latency_write);
  224. }
  225. st = rrdset_find_active_bytype_localhost("disk_iotime", diskstat.name);
  226. if (unlikely(!st)) {
  227. st = rrdset_create_localhost(
  228. "disk_iotime"
  229. , diskstat.name
  230. , NULL
  231. , diskstat.name
  232. , "disk.iotime"
  233. , "Disk Total I/O Time"
  234. , "milliseconds/s"
  235. , "macos.plugin"
  236. , "iokit"
  237. , 2022
  238. , update_every
  239. , RRDSET_TYPE_LINE
  240. );
  241. rrdset_flag_set(st, RRDSET_FLAG_DETAIL);
  242. rrddim_add(st, "reads", NULL, 1, 1000000, RRD_ALGORITHM_INCREMENTAL);
  243. rrddim_add(st, "writes", NULL, -1, 1000000, RRD_ALGORITHM_INCREMENTAL);
  244. }
  245. else rrdset_next(st);
  246. cur_diskstat.duration_read_ns = diskstat.time_read + diskstat.latency_read;
  247. cur_diskstat.duration_write_ns = diskstat.time_write + diskstat.latency_write;
  248. prev_diskstat.duration_read_ns = rrddim_set(st, "reads", cur_diskstat.duration_read_ns);
  249. prev_diskstat.duration_write_ns = rrddim_set(st, "writes", cur_diskstat.duration_write_ns);
  250. rrdset_done(st);
  251. // --------------------------------------------------------------------
  252. // calculate differential charts
  253. // only if this is not the first time we run
  254. if (likely(dt)) {
  255. // --------------------------------------------------------------------
  256. st = rrdset_find_active_bytype_localhost("disk_await", diskstat.name);
  257. if (unlikely(!st)) {
  258. st = rrdset_create_localhost(
  259. "disk_await"
  260. , diskstat.name
  261. , NULL
  262. , diskstat.name
  263. , "disk.await"
  264. , "Average Completed I/O Operation Time"
  265. , "milliseconds/operation"
  266. , "macos.plugin"
  267. , "iokit"
  268. , 2005
  269. , update_every
  270. , RRDSET_TYPE_LINE
  271. );
  272. rrdset_flag_set(st, RRDSET_FLAG_DETAIL);
  273. rrddim_add(st, "reads", NULL, 1, 1000000, RRD_ALGORITHM_ABSOLUTE);
  274. rrddim_add(st, "writes", NULL, -1, 1000000, RRD_ALGORITHM_ABSOLUTE);
  275. }
  276. else rrdset_next(st);
  277. rrddim_set(st, "reads", (diskstat.reads - prev_diskstat.operations_read) ?
  278. (cur_diskstat.duration_read_ns - prev_diskstat.duration_read_ns) / (diskstat.reads - prev_diskstat.operations_read) : 0);
  279. rrddim_set(st, "writes", (diskstat.writes - prev_diskstat.operations_write) ?
  280. (cur_diskstat.duration_write_ns - prev_diskstat.duration_write_ns) / (diskstat.writes - prev_diskstat.operations_write) : 0);
  281. rrdset_done(st);
  282. // --------------------------------------------------------------------
  283. st = rrdset_find_active_bytype_localhost("disk_avgsz", diskstat.name);
  284. if (unlikely(!st)) {
  285. st = rrdset_create_localhost(
  286. "disk_avgsz"
  287. , diskstat.name
  288. , NULL
  289. , diskstat.name
  290. , "disk.avgsz"
  291. , "Average Completed I/O Operation Bandwidth"
  292. , "KiB/operation"
  293. , "macos.plugin"
  294. , "iokit"
  295. , 2006
  296. , update_every
  297. , RRDSET_TYPE_AREA
  298. );
  299. rrdset_flag_set(st, RRDSET_FLAG_DETAIL);
  300. rrddim_add(st, "reads", NULL, 1, 1024, RRD_ALGORITHM_ABSOLUTE);
  301. rrddim_add(st, "writes", NULL, -1, 1024, RRD_ALGORITHM_ABSOLUTE);
  302. }
  303. else rrdset_next(st);
  304. rrddim_set(st, "reads", (diskstat.reads - prev_diskstat.operations_read) ?
  305. (diskstat.bytes_read - prev_diskstat.bytes_read) / (diskstat.reads - prev_diskstat.operations_read) : 0);
  306. rrddim_set(st, "writes", (diskstat.writes - prev_diskstat.operations_write) ?
  307. (diskstat.bytes_write - prev_diskstat.bytes_write) / (diskstat.writes - prev_diskstat.operations_write) : 0);
  308. rrdset_done(st);
  309. // --------------------------------------------------------------------
  310. st = rrdset_find_active_bytype_localhost("disk_svctm", diskstat.name);
  311. if (unlikely(!st)) {
  312. st = rrdset_create_localhost(
  313. "disk_svctm"
  314. , diskstat.name
  315. , NULL
  316. , diskstat.name
  317. , "disk.svctm"
  318. , "Average Service Time"
  319. , "milliseconds/operation"
  320. , "macos.plugin"
  321. , "iokit"
  322. , 2007
  323. , update_every
  324. , RRDSET_TYPE_LINE
  325. );
  326. rrdset_flag_set(st, RRDSET_FLAG_DETAIL);
  327. rrddim_add(st, "svctm", NULL, 1, 1000000, RRD_ALGORITHM_ABSOLUTE);
  328. }
  329. else rrdset_next(st);
  330. rrddim_set(st, "svctm", ((diskstat.reads - prev_diskstat.operations_read) + (diskstat.writes - prev_diskstat.operations_write)) ?
  331. (cur_diskstat.busy_time_ns - prev_diskstat.busy_time_ns) / ((diskstat.reads - prev_diskstat.operations_read) + (diskstat.writes - prev_diskstat.operations_write)) : 0);
  332. rrdset_done(st);
  333. }
  334. }
  335. /* Release. */
  336. CFRelease(properties);
  337. }
  338. /* Release. */
  339. IOObjectRelease(drive);
  340. }
  341. IOIteratorReset(drive_list);
  342. /* Release. */
  343. IOObjectRelease(drive_list);
  344. }
  345. if (likely(do_io)) {
  346. st = rrdset_find_active_bytype_localhost("system", "io");
  347. if (unlikely(!st)) {
  348. st = rrdset_create_localhost(
  349. "system"
  350. , "io"
  351. , NULL
  352. , "disk"
  353. , NULL
  354. , "Disk I/O"
  355. , "KiB/s"
  356. , "macos.plugin"
  357. , "iokit"
  358. , 150
  359. , update_every
  360. , RRDSET_TYPE_AREA
  361. );
  362. rrddim_add(st, "in", NULL, 1, 1024, RRD_ALGORITHM_INCREMENTAL);
  363. rrddim_add(st, "out", NULL, -1, 1024, RRD_ALGORITHM_INCREMENTAL);
  364. }
  365. else rrdset_next(st);
  366. rrddim_set(st, "in", total_disk_reads);
  367. rrddim_set(st, "out", total_disk_writes);
  368. rrdset_done(st);
  369. }
  370. // Can be merged with FreeBSD plugin
  371. // --------------------------------------------------------------------------
  372. if (likely(do_space || do_inodes)) {
  373. // there is no mount info in sysctl MIBs
  374. if (unlikely(!(mntsize = getmntinfo(&mntbuf, MNT_NOWAIT)))) {
  375. error("MACOS: getmntinfo() failed");
  376. do_space = 0;
  377. error("DISABLED: disk_space.X");
  378. do_inodes = 0;
  379. error("DISABLED: disk_inodes.X");
  380. } else {
  381. for (i = 0; i < mntsize; i++) {
  382. if (mntbuf[i].f_flags == MNT_RDONLY ||
  383. mntbuf[i].f_blocks == 0 ||
  384. // taken from gnulib/mountlist.c and shortened to FreeBSD related fstypes
  385. strcmp(mntbuf[i].f_fstypename, "autofs") == 0 ||
  386. strcmp(mntbuf[i].f_fstypename, "procfs") == 0 ||
  387. strcmp(mntbuf[i].f_fstypename, "subfs") == 0 ||
  388. strcmp(mntbuf[i].f_fstypename, "devfs") == 0 ||
  389. strcmp(mntbuf[i].f_fstypename, "none") == 0)
  390. continue;
  391. // --------------------------------------------------------------------------
  392. if (likely(do_space)) {
  393. st = rrdset_find_active_bytype_localhost("disk_space", mntbuf[i].f_mntonname);
  394. if (unlikely(!st)) {
  395. snprintfz(title, 4096, "Disk Space Usage for %s [%s]", mntbuf[i].f_mntonname, mntbuf[i].f_mntfromname);
  396. st = rrdset_create_localhost(
  397. "disk_space"
  398. , mntbuf[i].f_mntonname
  399. , NULL
  400. , mntbuf[i].f_mntonname
  401. , "disk.space"
  402. , title
  403. , "GiB"
  404. , "macos.plugin"
  405. , "iokit"
  406. , 2023
  407. , update_every
  408. , RRDSET_TYPE_STACKED
  409. );
  410. rrddim_add(st, "avail", NULL, mntbuf[i].f_bsize, GIGA_FACTOR, RRD_ALGORITHM_ABSOLUTE);
  411. rrddim_add(st, "used", NULL, mntbuf[i].f_bsize, GIGA_FACTOR, RRD_ALGORITHM_ABSOLUTE);
  412. rrddim_add(st, "reserved_for_root", "reserved for root", mntbuf[i].f_bsize, GIGA_FACTOR, RRD_ALGORITHM_ABSOLUTE);
  413. } else
  414. rrdset_next(st);
  415. rrddim_set(st, "avail", (collected_number) mntbuf[i].f_bavail);
  416. rrddim_set(st, "used", (collected_number) (mntbuf[i].f_blocks - mntbuf[i].f_bfree));
  417. rrddim_set(st, "reserved_for_root", (collected_number) (mntbuf[i].f_bfree - mntbuf[i].f_bavail));
  418. rrdset_done(st);
  419. }
  420. // --------------------------------------------------------------------------
  421. if (likely(do_inodes)) {
  422. st = rrdset_find_active_bytype_localhost("disk_inodes", mntbuf[i].f_mntonname);
  423. if (unlikely(!st)) {
  424. snprintfz(title, 4096, "Disk Files (inodes) Usage for %s [%s]", mntbuf[i].f_mntonname, mntbuf[i].f_mntfromname);
  425. st = rrdset_create_localhost(
  426. "disk_inodes"
  427. , mntbuf[i].f_mntonname
  428. , NULL
  429. , mntbuf[i].f_mntonname
  430. , "disk.inodes"
  431. , title
  432. , "inodes"
  433. , "macos.plugin"
  434. , "iokit"
  435. , 2024
  436. , update_every
  437. , RRDSET_TYPE_STACKED
  438. );
  439. rrddim_add(st, "avail", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE);
  440. rrddim_add(st, "used", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE);
  441. rrddim_add(st, "reserved_for_root", "reserved for root", 1, 1, RRD_ALGORITHM_ABSOLUTE);
  442. } else
  443. rrdset_next(st);
  444. rrddim_set(st, "avail", (collected_number) mntbuf[i].f_ffree);
  445. rrddim_set(st, "used", (collected_number) (mntbuf[i].f_files - mntbuf[i].f_ffree));
  446. rrdset_done(st);
  447. }
  448. }
  449. }
  450. }
  451. // Can be merged with FreeBSD plugin
  452. // --------------------------------------------------------------------
  453. if (likely(do_bandwidth)) {
  454. if (unlikely(getifaddrs(&ifap))) {
  455. error("MACOS: getifaddrs()");
  456. do_bandwidth = 0;
  457. error("DISABLED: system.ipv4");
  458. } else {
  459. for (ifa = ifap; ifa; ifa = ifa->ifa_next) {
  460. if (ifa->ifa_addr->sa_family != AF_LINK)
  461. continue;
  462. // --------------------------------------------------------------------
  463. st = rrdset_find_active_bytype_localhost("net", ifa->ifa_name);
  464. if (unlikely(!st)) {
  465. st = rrdset_create_localhost(
  466. "net"
  467. , ifa->ifa_name
  468. , NULL
  469. , ifa->ifa_name
  470. , "net.net"
  471. , "Bandwidth"
  472. , "kilobits/s"
  473. , "macos.plugin"
  474. , "iokit"
  475. , 7000
  476. , update_every
  477. , RRDSET_TYPE_AREA
  478. );
  479. rrddim_add(st, "received", NULL, 8, BITS_IN_A_KILOBIT, RRD_ALGORITHM_INCREMENTAL);
  480. rrddim_add(st, "sent", NULL, -8, BITS_IN_A_KILOBIT, RRD_ALGORITHM_INCREMENTAL);
  481. }
  482. else rrdset_next(st);
  483. rrddim_set(st, "received", IFA_DATA(ibytes));
  484. rrddim_set(st, "sent", IFA_DATA(obytes));
  485. rrdset_done(st);
  486. // --------------------------------------------------------------------
  487. st = rrdset_find_active_bytype_localhost("net_packets", ifa->ifa_name);
  488. if (unlikely(!st)) {
  489. st = rrdset_create_localhost(
  490. "net_packets"
  491. , ifa->ifa_name
  492. , NULL
  493. , ifa->ifa_name
  494. , "net.packets"
  495. , "Packets"
  496. , "packets/s"
  497. , "macos.plugin"
  498. , "iokit"
  499. , 7001
  500. , update_every
  501. , RRDSET_TYPE_LINE
  502. );
  503. rrdset_flag_set(st, RRDSET_FLAG_DETAIL);
  504. rrddim_add(st, "received", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
  505. rrddim_add(st, "sent", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL);
  506. rrddim_add(st, "multicast_received", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
  507. rrddim_add(st, "multicast_sent", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL);
  508. }
  509. else rrdset_next(st);
  510. rrddim_set(st, "received", IFA_DATA(ipackets));
  511. rrddim_set(st, "sent", IFA_DATA(opackets));
  512. rrddim_set(st, "multicast_received", IFA_DATA(imcasts));
  513. rrddim_set(st, "multicast_sent", IFA_DATA(omcasts));
  514. rrdset_done(st);
  515. // --------------------------------------------------------------------
  516. st = rrdset_find_active_bytype_localhost("net_errors", ifa->ifa_name);
  517. if (unlikely(!st)) {
  518. st = rrdset_create_localhost(
  519. "net_errors"
  520. , ifa->ifa_name
  521. , NULL
  522. , ifa->ifa_name
  523. , "net.errors"
  524. , "Interface Errors"
  525. , "errors/s"
  526. , "macos.plugin"
  527. , "iokit"
  528. , 7002
  529. , update_every
  530. , RRDSET_TYPE_LINE
  531. );
  532. rrdset_flag_set(st, RRDSET_FLAG_DETAIL);
  533. rrddim_add(st, "inbound", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
  534. rrddim_add(st, "outbound", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL);
  535. }
  536. else rrdset_next(st);
  537. rrddim_set(st, "inbound", IFA_DATA(ierrors));
  538. rrddim_set(st, "outbound", IFA_DATA(oerrors));
  539. rrdset_done(st);
  540. // --------------------------------------------------------------------
  541. st = rrdset_find_active_bytype_localhost("net_drops", ifa->ifa_name);
  542. if (unlikely(!st)) {
  543. st = rrdset_create_localhost(
  544. "net_drops"
  545. , ifa->ifa_name
  546. , NULL
  547. , ifa->ifa_name
  548. , "net.drops"
  549. , "Interface Drops"
  550. , "drops/s"
  551. , "macos.plugin"
  552. , "iokit"
  553. , 7003
  554. , update_every
  555. , RRDSET_TYPE_LINE
  556. );
  557. rrdset_flag_set(st, RRDSET_FLAG_DETAIL);
  558. rrddim_add(st, "inbound", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
  559. }
  560. else rrdset_next(st);
  561. rrddim_set(st, "inbound", IFA_DATA(iqdrops));
  562. rrdset_done(st);
  563. // --------------------------------------------------------------------
  564. st = rrdset_find_active_bytype_localhost("net_events", ifa->ifa_name);
  565. if (unlikely(!st)) {
  566. st = rrdset_create_localhost(
  567. "net_events"
  568. , ifa->ifa_name
  569. , NULL
  570. , ifa->ifa_name
  571. , "net.events"
  572. , "Network Interface Events"
  573. , "events/s"
  574. , "macos.plugin"
  575. , "iokit"
  576. , 7006
  577. , update_every
  578. , RRDSET_TYPE_LINE
  579. );
  580. rrdset_flag_set(st, RRDSET_FLAG_DETAIL);
  581. rrddim_add(st, "frames", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
  582. rrddim_add(st, "collisions", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL);
  583. rrddim_add(st, "carrier", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL);
  584. }
  585. else rrdset_next(st);
  586. rrddim_set(st, "collisions", IFA_DATA(collisions));
  587. rrdset_done(st);
  588. }
  589. freeifaddrs(ifap);
  590. }
  591. }
  592. return 0;
  593. }