- **Sophisticated alarming**<br/>
supports dynamic thresholds, hysteresis, alarm templates,
multiple role-based notification methods (such as email, slack.com,
- pushover.net, pushbullet.com telegram.org, twilio.com)
+ pushover.net, pushbullet.com telegram.org, twilio.com, messagebird.com)
- **Extensible**<br/>
you can monitor anything you can get a metric for,
- template: haproxy_backend_server_status
- on: haproxy_h.down
+template: haproxy_backend_server_status
+ on: haproxy_hs.down
units: failed servers
every: 10s
- lookup: average -10s
+ lookup: average -10s
crit: $this > 0
- info: Some of your backend servers is down!
+ info: number of failed haproxy backend servers
+ to: sysadmin
+
+template: haproxy_backend_status
+ on: haproxy_hb.down
+ units: failed backend
+ every: 10s
+ lookup: average -10s
+ crit: $this > 0
+ info: number of failed haproxy backends
+ to: sysadmin
+
+template: haproxy_last_collected
+ on: haproxy_hb.down
+ calc: $now - $last_collected_t
+ units: seconds ago
+ every: 10s
+ warn: $this > (($status >= $WARNING) ? ($update_every) : ( 5 * $update_every))
+ crit: $this > (($status == $CRITICAL) ? ($update_every) : (60 * $update_every))
+ info: number of seconds since the last successful data collection
to: sysadmin
# - messages to your slack team (slack.com),
# - messages to your telegram chat / group chat (telegram.org)
# - sms messages to your cell phone or any sms enabled device (twilio.com)
+# - sms messages to your cell phone or any sms enabled device (messagebird.com)
# - notifications to users on pagerduty.com
#
# The 'to' line given at netdata alarms defines a *role*, so that many
# In these examples, the first recipient receives all the alarms
# while the second one receives only the critical ones:
#
-# email : "user1@example.com user2@example.com|critical"
-# pushover: "2987343...9437837 8756278...2362736|critical"
-# telegram: "111827421 112746832|critical"
-# slack : "alarms disasters|critical"
-# twilio : "+15555555555 +17777777777|critical"
-# pd : "<pd_service_key_1> <pd_service_key_2>|critical"
+# email : "user1@example.com user2@example.com|critical"
+# pushover : "2987343...9437837 8756278...2362736|critical"
+# telegram : "111827421 112746832|critical"
+# slack : "alarms disasters|critical"
+# twilio : "+15555555555 +17777777777|critical"
+# messagebird: "+15555555555 +17777777777|critical"
+# pd : "<pd_service_key_1> <pd_service_key_2>|critical"
#
# If a recipient is set to empty string, the default recipient of the given
# notification method (email, pushover, telegram, slack, pd) will be used.
TWILIO_NUMBER=""
DEFAULT_RECIPIENT_TWILIO=""
+#------------------------------------------------------------------------------
+# Messagebird (messagebird.com) SMS options
+
+# multiple recipients can be given like this:
+# "+15555555555 +17777777777"
+
+# enable/disable sending messagebird SMS
+SEND_MESSAGEBIRD="YES"
+
+# to get an access key, create a free account at https://www.messagebird.com
+# verify and activate the account (no CC info needed)
+# login to your account and enter your phonenumber to get some free credits
+# to get the API key, click on 'API' in the sidebar, then 'API Access (REST)'
+# click 'Add access key' and fill in data (you want a live key to send SMS)
+
+# Without an access key, netdata cannot send Messagebird text messages.
+MESSAGEBIRD_ACCESS_KEY=""
+MESSAGEBIRD_NUMBER=""
+DEFAULT_RECIPIENT_MESSAGEBIRD=""
+
#------------------------------------------------------------------------------
# telegram (telegram.org) global notification options
role_recipients_twilio[sysadmin]="${DEFAULT_RECIPIENT_TWILIO}"
+role_recipients_messagebird[sysadmin]="${DEFAULT_RECIPIENT_MESSAGEBIRD}"
+
role_recipients_pd[sysadmin]="${DEFAULT_RECIPIENT_PD}"
# -----------------------------------------------------------------------------
role_recipients_twilio[domainadmin]="${DEFAULT_RECIPIENT_TWILIO}"
+role_recipients_messagebird[domainadmin]="${DEFAULT_RECIPIENT_MESSAGEBIRD}"
+
role_recipients_pd[domainadmin]="${DEFAULT_RECIPIENT_PD}"
# -----------------------------------------------------------------------------
role_recipients_twilio[dba]="${DEFAULT_RECIPIENT_TWILIO}"
+role_recipients_messagebird[dba]="${DEFAULT_RECIPIENT_MESSAGEBIRD}"
+
role_recipients_pd[dba]="${DEFAULT_RECIPIENT_PD}"
# -----------------------------------------------------------------------------
role_recipients_twilio[webmaster]="${DEFAULT_RECIPIENT_TWILIO}"
+role_recipients_messagebird[webmaster]="${DEFAULT_RECIPIENT_MESSAGEBIRD}"
+
role_recipients_pd[webmaster]="${DEFAULT_RECIPIENT_PD}"
# -----------------------------------------------------------------------------
role_recipients_twilio[proxyadmin]="${DEFAULT_RECIPIENT_TWILIO}"
+role_recipients_messagebird[proxyadmin]="${DEFAULT_RECIPIENT_MESSAGEBIRD}"
+
role_recipients_pd[proxyadmin]="${DEFAULT_RECIPIENT_PD}"
['15d8401b56a74120f9f832873ec9c578']='health.d/postgres.conf'
['15e32114994b92be7853b88091e7c6fb']='python.d/exim.conf'
['174c21a6ce5de97bda83d502aa47a9f8']='health.d/apache.conf'
+ ['178281aa2241d4a3e6b798bb9c4ae577']='python.d/haproxy.conf'
['18ee1c6197a4381b1c1631ef6129824f']='apps_groups.conf'
+ ['1972e48345e6c3f0d65f94a03317622b']='health_alarm_notify.conf'
['1c12b678ab65f271a96da1bbd0a1ab1c']='health.d/softnet.conf'
['1ea8e8ef1fa8a3a0fcdfba236f4cb195']='python.d/mysql.conf'
['1ef0fd38e7969c023bc3fa6d89eaf6d6']='python.d/mdstat.conf'
['a8bb4e1d0525f59692778ad8f675a77a']='python.d/example.conf'
['a8feb36776005bf419c90278787a1be8']='health.d/entropy.conf'
['a94af1c808aafdf00537d85ff2197ec8']='python.d/exim.conf'
+ ['a9ab68845db2fb695b7060273a6ac68e']='health_alarm_notify.conf'
['a9cd91675467c5426f5b51c47602c889']='apps_groups.conf'
['aa4bee249bfc0c4a88ac8c2ffb97aa0d']='health.d/squid.conf'
+ ['aa8b57a733c2035917acf81a8ebdfbe7']='health.d/haproxy.conf'
['abaf2e021f9f6ee5d1c4e4726f47348e']='health.d/ipc.conf'
['acaa6731a272f6d251afb357e99b518f']='apps_groups.conf'
['ade389c1b6efe0cff47c33e662731f0a']='python.d/squid.conf'
['af44cc53aa2bc5cc8935667119567522']='python.d.conf'
['afdae4646c755ff2d117527fbf761c8e']='health.d/disks.conf'
['b07eebc6f58d19721ac069171b911d2a']='health_alarm_notify.conf'
+ ['b0c59b2bd7a10f6a3f2be6b4b27857db']='health.d/haproxy.conf'
['b0f0a0ac415e4b1a82187b80d211e83b']='python.d/mysql.conf'
+ ['b185914d4f795e1732273dc4c7a35845']='health.d/memory.conf'
['b27f10a38a95edbbec20f44a4728b7c4']='python.d.conf'
['b32164929eda7449a9677044e11151bf']='python.d.conf'
['b3fc4749b132e55ac0d3a0f92859237e']='health.d/tcp_resets.conf'
['cd08e5534c94bf1f2cd28396c76b8bbc']='health.d/ram.conf'
['ce2e8768964a936f58c4c2144aee8a01']='health_alarm_notify.conf'
['ce3b65eac6c472b21905f7f72104f4c9']='python.d/nginx.conf'
+ ['cf48dfd828af70bea04db7a809f94358']='health.d/haproxy.conf'
['cfecf298bdafaa7e0a3a263548e82132']='python.d/sensors.conf'
['d11711b3647bc2bdd0292dd7deebbeb1']='health.d/net.conf'
['d1596fe068c8674efade49a4a8e22b5d']='health.d/isc_dhcpd.conf'
# - twilio.com notifications by Levi Blaney @shadycuz PR #1211
# - kafka notifications
# - pagerduty.com notifications by Jim Cooley @jimcooley PR #1373
+# - messagebird.com notifications by @tech_no_logical
# -----------------------------------------------------------------------------
# testing notifications
SEND_SLACK="YES"
SEND_PUSHOVER="YES"
SEND_TWILIO="YES"
+SEND_MESSAGEBIRD="YES"
SEND_TELEGRAM="YES"
SEND_EMAIL="YES"
SEND_PUSHBULLET="YES"
DEFAULT_RECIPIENT_TWILIO=
declare -A role_recipients_twilio=()
+# messagebird configs
+MESSAGEBIRD_ACCESS_KEY=
+MESSAGEBIRD_NUMBER=
+DEFAULT_RECIPIENT_MESSAGEBIRD=
+declare -A role_recipients_messagebird=()
+
# telegram configs
TELEGRAM_BOT_TOKEN=
DEFAULT_RECIPIENT_TELEGRAM=
[ "${r}" != "disabled" ] && filter_recipient_by_criticality twilio "${r}" && arr_twilio[${r/|*/}]="1"
done
+ # messagebird
+ a="${role_recipients_messagebird[${x}]}"
+ [ -z "${a}" ] && a="${DEFAULT_RECIPIENT_MESSAGEBIRD}"
+ for r in ${a//,/ }
+ do
+ [ "${r}" != "disabled" ] && filter_recipient_by_criticality messagebird "${r}" && arr_messagebird[${r/|*/}]="1"
+ done
+
# telegram
a="${role_recipients_telegram[${x}]}"
[ -z "${a}" ] && a="${DEFAULT_RECIPIENT_TELEGRAM}"
to_twilio="${!arr_twilio[*]}"
[ -z "${to_twilio}" ] && SEND_TWILIO="NO"
+# build the list of messagebird recipients (phone numbers)
+to_messagebird="${!arr_messagebird[*]}"
+[ -z "${to_messagebird}" ] && SEND_MESSAGEBIRD="NO"
+
# check array of telegram recipients (chat ids)
to_telegram="${!arr_telegram[*]}"
[ -z "${to_telegram}" ] && SEND_TELEGRAM="NO"
# check twilio
[ -z "${TWILIO_ACCOUNT_TOKEN}" -o -z "${TWILIO_ACCOUNT_SID}" -o -z "${TWILIO_NUMBER}" ] && SEND_TWILIO="NO"
+# check messagebird
+[ -z "${MESSAGEBIRD_ACCESS_KEY}" -o -z "${MESSAGEBIRD_NUMBER}" ] && SEND_MESSAGEBIRD="NO"
+
# check telegram
[ -z "${TELEGRAM_BOT_TOKEN}" ] && SEND_TELEGRAM="NO"
fi
# if we need curl, check for the curl command
-if [ \( "${SEND_PUSHOVER}" = "YES" -o "${SEND_SLACK}" = "YES" -o "${SEND_TWILIO}" = "YES" -o "${SEND_TELEGRAM}" = "YES" -o "${SEND_PUSHBULLET}" = "YES" -o "${SEND_KAFKA}" = "YES" \) -a -z "${curl}" ]
+if [ \( "${SEND_PUSHOVER}" = "YES" -o "${SEND_SLACK}" = "YES" -o "${SEND_TWILIO}" = "YES" -o "${SEND_MESSAGEBIRD}" = "YES" -o "${SEND_TELEGRAM}" = "YES" -o "${SEND_PUSHBULLET}" = "YES" -o "${SEND_KAFKA}" = "YES" \) -a -z "${curl}" ]
then
curl="$(which curl 2>/dev/null || command -v curl 2>/dev/null)"
if [ -z "${curl}" ]
SEND_TELEGRAM="NO"
SEND_SLACK="NO"
SEND_TWILIO="NO"
+ SEND_MESSAGEBIRD="NO"
SEND_KAFKA="NO"
fi
fi
fi
# check that we have at least a method enabled
-if [ "${SEND_EMAIL}" != "YES" \
- -a "${SEND_PUSHOVER}" != "YES" \
- -a "${SEND_TELEGRAM}" != "YES" \
- -a "${SEND_SLACK}" != "YES" \
- -a "${SEND_TWILIO}" != "YES" \
- -a "${SEND_PUSHBULLET}" != "YES" \
- -a "${SEND_KAFKA}" != "YES" \
- -a "${SEND_PD}" != "YES" \
+if [ "${SEND_EMAIL}" != "YES" \
+ -a "${SEND_PUSHOVER}" != "YES" \
+ -a "${SEND_TELEGRAM}" != "YES" \
+ -a "${SEND_SLACK}" != "YES" \
+ -a "${SEND_TWILIO}" != "YES" \
+ -a "${SEND_MESSAGEBIRD}" != "YES" \
+ -a "${SEND_PUSHBULLET}" != "YES" \
+ -a "${SEND_KAFKA}" != "YES" \
+ -a "${SEND_PD}" != "YES" \
]
then
fatal "All notification methods are disabled. Not sending notification to '${roles}' for '${name}' = '${value}' of chart '${chart}' for status '${status}'."
return 1
}
+# -----------------------------------------------------------------------------
+# messagebird sender
+
+send_messagebird() {
+ local accesskey="${1}" messagebirdnumber="${2}" recipients="${3}" title="${4}" message="${5}" httpcode sent=0 user
+ if [ "${SEND_MESSAGEBIRD}" = "YES" -a ! -z "${accesskey}" -a ! -z "${messagebirdnumber}" -a ! -z "${recipients}" -a ! -z "${message}" -a ! -z "${title}" ]
+ then
+ #https://developers.messagebird.com/docs/messaging
+ for user in ${recipients}
+ do
+ httpcode=$(${curl} -X POST --write-out %{http_code} --silent --output /dev/null \
+ --data-urlencode "originator=${messagebirdnumber}" \
+ --data-urlencode "recipients=${user}" \
+ --data-urlencode "body=${title} ${message}" \
+ --data-urlencode "datacoding=auto" \
+ -H "Authorization: AccessKey ${accesskey}" \
+ "https://rest.messagebird.com/messages")
+
+ if [ "${httpcode}" == "201" ]
+ then
+ info "sent Messagebird SMS for: ${host} ${chart}.${name} is ${status} to '${user}'"
+ sent=$((sent + 1))
+ else
+ error "failed to send Messagebird SMS for: ${host} ${chart}.${name} is ${status} to '${user}' with HTTP error code ${httpcode}."
+ fi
+ done
+
+ [ ${sent} -gt 0 ] && return 0
+ fi
+
+ return 1
+}
+
# -----------------------------------------------------------------------------
# telegram sender
SENT_TWILIO=$?
+# -----------------------------------------------------------------------------
+# send the messagebird SMS
+
+send_messagebird "${MESSAGEBIRD_ACCESS_KEY}" "${MESSAGEBIRD_NUMBER}" "${to_messagebird}" "${host} ${status_message} - ${name//_/ } - ${chart}" "${alarm}
+Severity: ${severity}
+Chart: ${chart}
+Family: ${family}
+${info}"
+
+SENT_MESSAGEBIRD=$?
+
+
# -----------------------------------------------------------------------------
# send the telegram.org message
# -----------------------------------------------------------------------------
# let netdata know
-if [ ${SENT_EMAIL} -eq 0 \
- -o ${SENT_PUSHOVER} -eq 0 \
- -o ${SENT_TELEGRAM} -eq 0 \
- -o ${SENT_SLACK} -eq 0 \
- -o ${SENT_TWILIO} -eq 0 \
- -o ${SENT_PUSHBULLET} -eq 0 \
- -o ${SENT_KAFKA} -eq 0 \
- -o ${SENT_PD} -eq 0 \
+if [ ${SENT_EMAIL} -eq 0 \
+ -o ${SENT_PUSHOVER} -eq 0 \
+ -o ${SENT_TELEGRAM} -eq 0 \
+ -o ${SENT_SLACK} -eq 0 \
+ -o ${SENT_TWILIO} -eq 0 \
+ -o ${SENT_MESSAGEBIRD} -eq 0 \
+ -o ${SENT_PUSHBULLET} -eq 0 \
+ -o ${SENT_KAFKA} -eq 0 \
+ -o ${SENT_PD} -eq 0 \
]
then
# we did send something
---
+# haproxy
+
+Module monitors frontend and backend metrics such as bytes in, bytes out, sessions current, sessions in queue current.
+And health metrics such as backend servers status (server check should be used).
+
+Plugin can obtain data from url **OR** unix socket.
+
+**Requirement:**
+Socket MUST be readable AND writable by netdata user.
+
+It produces:
+
+1. **Frontend** family charts
+ * Kilobytes in/s
+ * Kilobytes out/s
+ * Sessions current
+ * Sessions in queue current
+
+2. **Backend** family charts
+ * Kilobytes in/s
+ * Kilobytes out/s
+ * Sessions current
+ * Sessions in queue current
+
+3. **Health** chart
+ * number of failed servers for every backend (in DOWN state)
+
+
+### configuration
+
+Sample:
+
+```yaml
+via_url:
+ user : 'username' # ONLY IF stats auth is used
+ pass : 'password' # # ONLY IF stats auth is used
+ url : 'http://ip.address:port/url;csv;norefresh'
+```
+
+OR
+
+```yaml
+via_socket:
+ socket : 'path/to/haproxy/sock'
+```
+
+If no configuration is given, module will fail to run.
+
+---
+
# hddtemp
Module monitors disk temperatures from one or more hddtemp daemons.
retries = 60
# charts order (can be overridden if you want less charts, or different order)
-ORDER = ['fbin', 'fbout', 'fscur', 'fqcur', 'bbin', 'bbout', 'bscur', 'bqcur', 'health_down']
+ORDER = ['fbin', 'fbout', 'fscur', 'fqcur', 'bbin', 'bbout', 'bscur', 'bqcur', 'health_sdown', 'health_bdown']
CHARTS = {
'fbin': {
'options': [None, "Kilobytes in", "kilobytes in/s", 'Frontend', 'haproxy_f.bin', 'line'],
'options': [None, "Sessions in queue", "sessions", 'Backend', 'haproxy_b.qcur', 'line'],
'lines': [
]},
- 'health_down': {
- 'options': [None, "Servers in DOWN state", "failed servers", 'Health', 'haproxy_h.down', 'line'],
+ 'health_sdown': {
+ 'options': [None, "Number of servers in backend in DOWN state", "failed servers", 'Health', 'haproxy_hs.down', 'line'],
+ 'lines': [
+ ]},
+ 'health_bdown': {
+ 'options': [None, "Is backend alive? 1 = DOWN", "failed backend", 'Health', 'haproxy_hb.down', 'line'],
'lines': [
]}
}
self.definitions['bbout']['lines'].append(['_'.join(['bbout', back_ends[_]['# pxname']]), back_ends[_]['# pxname'], 'incremental', 1, 1024])
self.definitions['bscur']['lines'].append(['_'.join(['bscur', back_ends[_]['# pxname']]), back_ends[_]['# pxname'], 'absolute'])
self.definitions['bqcur']['lines'].append(['_'.join(['bqcur', back_ends[_]['# pxname']]), back_ends[_]['# pxname'], 'absolute'])
- self.definitions['health_down']['lines'].append(['_'.join(['hdown', back_ends[_]['# pxname']]), back_ends[_]['# pxname'], 'absolute'])
+ self.definitions['health_sdown']['lines'].append(['_'.join(['hsdown', back_ends[_]['# pxname']]), back_ends[_]['# pxname'], 'absolute'])
+ self.definitions['health_bdown']['lines'].append(['_'.join(['hbdown', back_ends[_]['# pxname']]), back_ends[_]['# pxname'], 'absolute'])
def _get_data(self):
"""
to_netdata.update({'_'.join([_, backend['# pxname']]): int(backend[_[1:]]) if backend.get(_[1:]) else 0})
for _ in range(len(back_ends)):
- to_netdata.update({'_'.join(['hdown', back_ends[_]['# pxname']]):
+ to_netdata.update({'_'.join(['hsdown', back_ends[_]['# pxname']]):
len([server for server in servers if is_server_down(server, back_ends, _)])})
+ to_netdata.update({'_'.join(['hbdown', back_ends[_]['# pxname']]): 1 if is_backend_down(back_ends, _) else 0})
return to_netdata
def is_server_down(server, back_ends, _):
try:
- return server['# pxname'] == back_ends[_]['# pxname'] and server['status'] != 'UP' and server['status'] != 'no check'
+ return server['# pxname'] == back_ends[_]['# pxname'] and server['status'] == 'DOWN'
+ except Exception:
+ return False
+
+def is_backend_down(back_ends, _):
+ try:
+ return back_ends[_]['status'] == 'DOWN'
except Exception:
return False
#include <netinet/icmp6.h>
// NEEDED BY do_space, do_inodes
#include <sys/mount.h>
+// NEEDED BY do_uptime
+#include <time.h>
#define KILO_FACTOR 1024
#define MEGA_FACTOR 1048576 // 1024 * 1024
do_ip_packets = -1, do_ip_fragsout = -1, do_ip_fragsin = -1, do_ip_errors = -1,
do_ip6_packets = -1, do_ip6_fragsout = -1, do_ip6_fragsin = -1, do_ip6_errors = -1,
do_icmp6 = -1, do_icmp6_redir = -1, do_icmp6_errors = -1, do_icmp6_echos = -1, do_icmp6_router = -1,
- do_icmp6_neighbor = -1, do_icmp6_types = -1, do_space = -1, do_inodes = -1;
+ do_icmp6_neighbor = -1, do_icmp6_types = -1, do_space = -1, do_inodes = -1, do_uptime = -1;
if (unlikely(do_cpu == -1)) {
do_cpu = config_get_boolean("plugin:freebsd:sysctl", "cpu utilization", 1);
do_icmp6_types = config_get_boolean_ondemand("plugin:freebsd:sysctl", "icmp types", CONFIG_ONDEMAND_ONDEMAND);
do_space = config_get_boolean("plugin:freebsd:sysctl", "space usage for all disks", 1);
do_inodes = config_get_boolean("plugin:freebsd:sysctl", "inodes usage for all disks", 1);
+ do_uptime = config_get_boolean("plugin:macos:sysctl", "system uptime", 1);
}
RRDSET *st;
int mntsize;
char mntonname[MNAMELEN + 1];
+ // NEEDED BY: do_uptime
+ struct timespec boot_time, cur_time;
+
// --------------------------------------------------------------------
if (last_loadavg_usec <= dt) {
}
}
+ // --------------------------------------------------------------------
+
+ if (likely(do_uptime)) {
+ if (unlikely(GETSYSCTL("kern.boottime", boot_time))) {
+ do_uptime = 0;
+ error("DISABLED: system.uptime");
+ } else {
+ clock_gettime(CLOCK_REALTIME, &cur_time);
+ st = rrdset_find("system.uptime");
+
+ if(unlikely(!st)) {
+ st = rrdset_create("system", "uptime", NULL, "uptime", NULL, "System Uptime", "seconds", 1000, update_every, RRDSET_TYPE_LINE);
+ rrddim_add(st, "uptime", NULL, 1, 1, RRDDIM_ABSOLUTE);
+ }
+ else rrdset_next(st);
+
+ rrddim_set(st, "uptime", cur_time.tv_sec - boot_time.tv_sec);
+ rrdset_done(st);
+ }
+ }
+
return 0;
}
#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;
+ 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_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;
+ io_registry_entry_t drive, drive_media;
io_iterator_t drive_list;
- CFNumberRef number;
CFDictionaryRef properties, statistics;
- UInt64 value;
+ 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 (IOMasterPort(bootstrap_port, &master_port)) {
+ 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 (IOServiceGetMatchingServices(master_port, IOServiceMatching("IOBlockStorageDriver"), &drive_list)) {
+ } 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) {
- number = 0;
properties = 0;
statistics = 0;
- value = 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);
/* Obtain the properties for this drive object. */
- if (IORegistryEntryCreateCFProperties(drive, (CFMutableDictionaryRef *)&properties, kCFAllocatorDefault, 0)) {
+ if (unlikely(IORegistryEntryCreateCFProperties(drive, (CFMutableDictionaryRef *)&properties, kCFAllocatorDefault, 0))) {
error("MACOS: IORegistryEntryCreateCFProperties() failed");
do_io = 0;
error("DISABLED: system.io");
break;
- } else if (properties != 0) {
+ } else if (likely(properties)) {
/* Obtain the statistics from the drive properties. */
- statistics = (CFDictionaryRef)CFDictionaryGetValue(properties, CFSTR(kIOBlockStorageDriverStatisticsKey));
+ if (likely(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;
+ if (likely(number = (CFNumberRef)CFDictionaryGetValue(statistics, CFSTR(kIOBlockStorageDriverStatisticsBytesReadKey)))) {
+ CFNumberGetValue(number, kCFNumberSInt64Type, &diskstat.bytes_read);
+ total_disk_reads += diskstat.bytes_read;
}
/* Get bytes written. */
- number = (CFNumberRef)CFDictionaryGetValue(statistics, CFSTR(kIOBlockStorageDriverStatisticsBytesWrittenKey));
- if (number != 0) {
- CFNumberGetValue(number, kCFNumberSInt64Type, &value);
- total_disk_writes += value;
+ if (likely(number = (CFNumberRef)CFDictionaryGetValue(statistics, CFSTR(kIOBlockStorageDriverStatisticsBytesWrittenKey)))) {
+ CFNumberGetValue(number, kCFNumberSInt64Type, &diskstat.bytes_write);
+ total_disk_writes += diskstat.bytes_write;
+ }
+
+ st = rrdset_find_bytype("disk", diskstat.name);
+ if (unlikely(!st)) {
+ st = rrdset_create("disk", diskstat.name, NULL, diskstat.name, "disk.io", "Disk I/O Bandwidth", "kilobytes/s", 2000, update_every, RRDSET_TYPE_AREA);
+
+ rrddim_add(st, "reads", NULL, 1, 1024, RRDDIM_INCREMENTAL);
+ rrddim_add(st, "writes", NULL, -1, 1024, RRDDIM_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("disk_ops", diskstat.name);
+ if (unlikely(!st)) {
+ st = rrdset_create("disk_ops", diskstat.name, NULL, diskstat.name, "disk.ops", "Disk Completed I/O Operations", "operations/s", 2001, update_every, RRDSET_TYPE_LINE);
+ st->isdetail = 1;
+
+ rrddim_add(st, "reads", NULL, 1, 1, RRDDIM_INCREMENTAL);
+ rrddim_add(st, "writes", NULL, -1, 1, RRDDIM_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("disk_util", diskstat.name);
+ if (unlikely(!st)) {
+ st = rrdset_create("disk_util", diskstat.name, NULL, diskstat.name, "disk.util", "Disk Utilization Time", "% of time working", 2004, update_every, RRDSET_TYPE_AREA);
+ st->isdetail = 1;
+
+ rrddim_add(st, "utilization", NULL, 1, 10000000, RRDDIM_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("disk_iotime", diskstat.name);
+ if (unlikely(!st)) {
+ st = rrdset_create("disk_iotime", diskstat.name, NULL, diskstat.name, "disk.iotime", "Disk Total I/O Time", "milliseconds/s", 2022, update_every, RRDSET_TYPE_LINE);
+ st->isdetail = 1;
+
+ rrddim_add(st, "reads", NULL, 1, 1000000, RRDDIM_INCREMENTAL);
+ rrddim_add(st, "writes", NULL, -1, 1000000, RRDDIM_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("disk_await", diskstat.name);
+ if (unlikely(!st)) {
+ st = rrdset_create("disk_await", diskstat.name, NULL, diskstat.name, "disk.await", "Average Completed I/O Operation Time", "ms per operation", 2005, update_every, RRDSET_TYPE_LINE);
+ st->isdetail = 1;
+
+ rrddim_add(st, "reads", NULL, 1, 1000000, RRDDIM_ABSOLUTE);
+ rrddim_add(st, "writes", NULL, -1, 1000000, RRDDIM_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("disk_avgsz", diskstat.name);
+ if (unlikely(!st)) {
+ st = rrdset_create("disk_avgsz", diskstat.name, NULL, diskstat.name, "disk.avgsz", "Average Completed I/O Operation Bandwidth", "kilobytes per operation", 2006, update_every, RRDSET_TYPE_AREA);
+ st->isdetail = 1;
+
+ rrddim_add(st, "reads", NULL, 1, 1024, RRDDIM_ABSOLUTE);
+ rrddim_add(st, "writes", NULL, -1, 1024, RRDDIM_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("disk_svctm", diskstat.name);
+ if (unlikely(!st)) {
+ st = rrdset_create("disk_svctm", diskstat.name, NULL, diskstat.name, "disk.svctm", "Average Service Time", "ms per operation", 2007, update_every, RRDSET_TYPE_LINE);
+ st->isdetail = 1;
+
+ rrddim_add(st, "svctm", NULL, 1, 1000000, RRDDIM_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);
}
}
IOObjectRelease(drive_list);
}
- if (do_io) {
+ if (likely(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);
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("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("disk_space", mntbuf[i].f_mntonname, NULL, mntbuf[i].f_mntonname, "disk.space", title, "GB", 2023,
+ update_every,
+ RRDSET_TYPE_STACKED);
+
+ rrddim_add(st, "avail", NULL, mntbuf[i].f_bsize, GIGA_FACTOR, RRDDIM_ABSOLUTE);
+ rrddim_add(st, "used", NULL, mntbuf[i].f_bsize, GIGA_FACTOR, RRDDIM_ABSOLUTE);
+ rrddim_add(st, "reserved_for_root", "reserved for root", mntbuf[i].f_bsize, GIGA_FACTOR,
+ RRDDIM_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("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("disk_inodes", mntbuf[i].f_mntonname, NULL, mntbuf[i].f_mntonname, "disk.inodes", title, "Inodes", 2024,
+ update_every, RRDSET_TYPE_STACKED);
+
+ rrddim_add(st, "avail", NULL, 1, 1, RRDDIM_ABSOLUTE);
+ rrddim_add(st, "used", NULL, 1, 1, RRDDIM_ABSOLUTE);
+ rrddim_add(st, "reserved_for_root", "reserved for root", 1, 1, RRDDIM_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("net", ifa->ifa_name);
+ if (unlikely(!st)) {
+ st = rrdset_create("net", ifa->ifa_name, NULL, ifa->ifa_name, "net.net", "Bandwidth", "kilobits/s", 7000, update_every, RRDSET_TYPE_AREA);
+
+ rrddim_add(st, "received", NULL, 8, 1024, RRDDIM_INCREMENTAL);
+ rrddim_add(st, "sent", NULL, -8, 1024, RRDDIM_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("net_packets", ifa->ifa_name);
+ if (unlikely(!st)) {
+ st = rrdset_create("net_packets", ifa->ifa_name, NULL, ifa->ifa_name, "net.packets", "Packets", "packets/s", 7001, update_every, RRDSET_TYPE_LINE);
+ st->isdetail = 1;
+
+ rrddim_add(st, "received", NULL, 1, 1, RRDDIM_INCREMENTAL);
+ rrddim_add(st, "sent", NULL, -1, 1, RRDDIM_INCREMENTAL);
+ rrddim_add(st, "multicast_received", NULL, 1, 1, RRDDIM_INCREMENTAL);
+ rrddim_add(st, "multicast_sent", NULL, -1, 1, RRDDIM_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("net_errors", ifa->ifa_name);
+ if (unlikely(!st)) {
+ st = rrdset_create("net_errors", ifa->ifa_name, NULL, ifa->ifa_name, "net.errors", "Interface Errors", "errors/s", 7002, update_every, RRDSET_TYPE_LINE);
+ st->isdetail = 1;
+
+ rrddim_add(st, "inbound", NULL, 1, 1, RRDDIM_INCREMENTAL);
+ rrddim_add(st, "outbound", NULL, -1, 1, RRDDIM_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("net_drops", ifa->ifa_name);
+ if (unlikely(!st)) {
+ st = rrdset_create("net_drops", ifa->ifa_name, NULL, ifa->ifa_name, "net.drops", "Interface Drops", "drops/s", 7003, update_every, RRDSET_TYPE_LINE);
+ st->isdetail = 1;
+
+ rrddim_add(st, "inbound", NULL, 1, 1, RRDDIM_INCREMENTAL);
+ }
+ else rrdset_next(st);
+
+ rrddim_set(st, "inbound", IFA_DATA(iqdrops));
+ rrdset_done(st);
+
+ // --------------------------------------------------------------------
+
+ st = rrdset_find_bytype("net_events", ifa->ifa_name);
+ if (unlikely(!st)) {
+ st = rrdset_create("net_events", ifa->ifa_name, NULL, ifa->ifa_name, "net.events", "Network Interface Events", "events/s", 7006, update_every, RRDSET_TYPE_LINE);
+ st->isdetail = 1;
+
+ rrddim_add(st, "frames", NULL, 1, 1, RRDDIM_INCREMENTAL);
+ rrddim_add(st, "collisions", NULL, -1, 1, RRDDIM_INCREMENTAL);
+ rrddim_add(st, "carrier", NULL, -1, 1, RRDDIM_INCREMENTAL);
+ }
+ else rrdset_next(st);
+
+ rrddim_set(st, "collisions", IFA_DATA(collisions));
+ rrdset_done(st);
+ }
+
+ freeifaddrs(ifap);
+ }
+ }
+
+
return 0;
}
#include <netinet/icmp_var.h>
// NEEDED BY do_icmp6...
#include <netinet/icmp6.h>
+// NEEDED BY do_uptime
+#include <time.h>
#define GETSYSCTL(name, var) getsysctl(name, &(var), sizeof(var))
do_ip_packets = -1, do_ip_fragsout = -1, do_ip_fragsin = -1, do_ip_errors = -1,
do_ip6_packets = -1, do_ip6_fragsout = -1, do_ip6_fragsin = -1, do_ip6_errors = -1,
do_icmp6 = -1, do_icmp6_redir = -1, do_icmp6_errors = -1, do_icmp6_echos = -1,
- do_icmp6_router = -1, do_icmp6_neighbor = -1, do_icmp6_types = -1;
+ do_icmp6_router = -1, do_icmp6_neighbor = -1, do_icmp6_types = -1, do_uptime = -1;
if (unlikely(do_loadavg == -1)) {
do_icmp6_router = config_get_boolean_ondemand("plugin:macos:sysctl", "icmp router", CONFIG_ONDEMAND_ONDEMAND);
do_icmp6_neighbor = config_get_boolean_ondemand("plugin:macos:sysctl", "icmp neighbor", CONFIG_ONDEMAND_ONDEMAND);
do_icmp6_types = config_get_boolean_ondemand("plugin:macos:sysctl", "icmp types", CONFIG_ONDEMAND_ONDEMAND);
+ do_uptime = config_get_boolean("plugin:macos:sysctl", "system uptime", 1);
}
RRDSET *st;
u_long msgs_out;
} icmp6_total = {0, 0};
+ // NEEDED BY: do_uptime
+ struct timespec boot_time, cur_time;
+
// --------------------------------------------------------------------
if (last_loadavg_usec <= dt) {
}
}
+ // --------------------------------------------------------------------
+
+ if (likely(do_uptime)) {
+ if (unlikely(GETSYSCTL("kern.boottime", boot_time))) {
+ do_uptime = 0;
+ error("DISABLED: system.uptime");
+ } else {
+ clock_gettime(CLOCK_REALTIME, &cur_time);
+ st = rrdset_find("system.uptime");
+
+ if(unlikely(!st)) {
+ st = rrdset_create("system", "uptime", NULL, "uptime", NULL, "System Uptime", "seconds", 1000, update_every, RRDSET_TYPE_LINE);
+ rrddim_add(st, "uptime", NULL, 1, 1, RRDDIM_ABSOLUTE);
+ }
+ else rrdset_next(st);
+
+ rrddim_set(st, "uptime", cur_time.tv_sec - boot_time.tv_sec);
+ rrdset_done(st);
+ }
+ }
+
return 0;
}
#include "common.h"
+struct netdev {
+ char *name;
+ uint32_t hash;
+ size_t len;
+
+ // flags
+ int configured;
+ int enabled;
+
+ int do_bandwidth;
+ int do_packets;
+ int do_errors;
+ int do_drops;
+ int do_fifo;
+ int do_compressed;
+ int do_events;
+
+ // data collected
+ unsigned long long rbytes;
+ unsigned long long rpackets;
+ unsigned long long rerrors;
+ unsigned long long rdrops;
+ unsigned long long rfifo;
+ unsigned long long rframe;
+ unsigned long long rcompressed;
+ unsigned long long rmulticast;
+
+ unsigned long long tbytes;
+ unsigned long long tpackets;
+ unsigned long long terrors;
+ unsigned long long tdrops;
+ unsigned long long tfifo;
+ unsigned long long tcollisions;
+ unsigned long long tcarrier;
+ unsigned long long tcompressed;
+
+ // charts
+ RRDSET *st_bandwidth;
+ RRDSET *st_packets;
+ RRDSET *st_errors;
+ RRDSET *st_drops;
+ RRDSET *st_fifo;
+ RRDSET *st_compressed;
+ RRDSET *st_events;
+
+ // dimensions
+ RRDDIM *rd_rbytes;
+ RRDDIM *rd_rpackets;
+ RRDDIM *rd_rerrors;
+ RRDDIM *rd_rdrops;
+ RRDDIM *rd_rfifo;
+ RRDDIM *rd_rframe;
+ RRDDIM *rd_rcompressed;
+ RRDDIM *rd_rmulticast;
+
+ RRDDIM *rd_tbytes;
+ RRDDIM *rd_tpackets;
+ RRDDIM *rd_terrors;
+ RRDDIM *rd_tdrops;
+ RRDDIM *rd_tfifo;
+ RRDDIM *rd_tcollisions;
+ RRDDIM *rd_tcarrier;
+ RRDDIM *rd_tcompressed;
+
+ struct netdev *next;
+};
+
+static struct netdev *netdev_root = NULL;
+
+static struct netdev *get_netdev(const char *name) {
+ static struct netdev *last = NULL;
+ struct netdev *d;
+
+ uint32_t hash = simple_hash(name);
+
+ // search it, from the last position to the end
+ for(d = last ; d ; d = d->next) {
+ if(unlikely(hash == d->hash && !strcmp(name, d->name))) {
+ last = d->next;
+ return d;
+ }
+ }
+
+ // search it from the beginning to the last position we used
+ for(d = netdev_root ; d != last ; d = d->next) {
+ if(unlikely(hash == d->hash && !strcmp(name, d->name))) {
+ last = d->next;
+ return d;
+ }
+ }
+
+ // create a new one
+ d = callocz(1, sizeof(struct netdev));
+ d->name = strdupz(name);
+ d->hash = simple_hash(d->name);
+ d->len = strlen(d->name);
+
+ // link it to the end
+ if(netdev_root) {
+ struct netdev *e;
+ for(e = netdev_root; e->next ; e = e->next) ;
+ e->next = d;
+ }
+ else
+ netdev_root = d;
+
+ return d;
+}
+
int do_proc_net_dev(int update_every, usec_t dt) {
+ (void)dt;
+
static procfile *ff = NULL;
- static int enable_new_interfaces = -1, enable_ifb_interfaces = -1;
+ static int enable_new_interfaces = -1, enable_ifb_interfaces = -1, enable_veth_interfaces = -1;
static int do_bandwidth = -1, do_packets = -1, do_errors = -1, do_drops = -1, do_fifo = -1, do_compressed = -1, do_events = -1;
- if(dt) {};
+ if(unlikely(enable_new_interfaces == -1)) {
+ enable_new_interfaces = config_get_boolean_ondemand("plugin:proc:/proc/net/dev", "enable new interfaces detected at runtime", CONFIG_ONDEMAND_ONDEMAND);
+ enable_ifb_interfaces = config_get_boolean_ondemand("plugin:proc:/proc/net/dev", "enable ifb interfaces", CONFIG_ONDEMAND_NO);
+ enable_veth_interfaces = config_get_boolean_ondemand("plugin:proc:/proc/net/dev", "enable veth interfaces", enable_new_interfaces);
+
+ do_bandwidth = config_get_boolean_ondemand("plugin:proc:/proc/net/dev", "bandwidth for all interfaces", CONFIG_ONDEMAND_ONDEMAND);
+ do_packets = config_get_boolean_ondemand("plugin:proc:/proc/net/dev", "packets for all interfaces", CONFIG_ONDEMAND_ONDEMAND);
+ do_errors = config_get_boolean_ondemand("plugin:proc:/proc/net/dev", "errors for all interfaces", CONFIG_ONDEMAND_ONDEMAND);
+ do_drops = config_get_boolean_ondemand("plugin:proc:/proc/net/dev", "drops for all interfaces", CONFIG_ONDEMAND_ONDEMAND);
+ do_fifo = config_get_boolean_ondemand("plugin:proc:/proc/net/dev", "fifo for all interfaces", CONFIG_ONDEMAND_ONDEMAND);
+ do_compressed = config_get_boolean_ondemand("plugin:proc:/proc/net/dev", "compressed packets for all interfaces", CONFIG_ONDEMAND_ONDEMAND);
+ do_events = config_get_boolean_ondemand("plugin:proc:/proc/net/dev", "frames, collisions, carrier counters for all interfaces", CONFIG_ONDEMAND_ONDEMAND);
+ }
- if(!ff) {
+ if(unlikely(!ff)) {
char filename[FILENAME_MAX + 1];
snprintfz(filename, FILENAME_MAX, "%s%s", global_host_prefix, "/proc/net/dev");
ff = procfile_open(config_get("plugin:proc:/proc/net/dev", "filename to monitor", filename), " \t,:|", PROCFILE_FLAG_DEFAULT);
+ if(unlikely(!ff)) return 1;
}
- if(!ff) return 1;
ff = procfile_readall(ff);
- if(!ff) return 0; // we return 0, so that we will retry to open it next time
-
- if(enable_new_interfaces == -1) enable_new_interfaces = config_get_boolean_ondemand("plugin:proc:/proc/net/dev", "enable new interfaces detected at runtime", CONFIG_ONDEMAND_ONDEMAND);
- if(enable_ifb_interfaces == -1) enable_ifb_interfaces = config_get_boolean_ondemand("plugin:proc:/proc/net/dev", "enable ifb interfaces", CONFIG_ONDEMAND_NO);
-
- if(do_bandwidth == -1) do_bandwidth = config_get_boolean_ondemand("plugin:proc:/proc/net/dev", "bandwidth for all interfaces", CONFIG_ONDEMAND_ONDEMAND);
- if(do_packets == -1) do_packets = config_get_boolean_ondemand("plugin:proc:/proc/net/dev", "packets for all interfaces", CONFIG_ONDEMAND_ONDEMAND);
- if(do_errors == -1) do_errors = config_get_boolean_ondemand("plugin:proc:/proc/net/dev", "errors for all interfaces", CONFIG_ONDEMAND_ONDEMAND);
- if(do_drops == -1) do_drops = config_get_boolean_ondemand("plugin:proc:/proc/net/dev", "drops for all interfaces", CONFIG_ONDEMAND_ONDEMAND);
- if(do_fifo == -1) do_fifo = config_get_boolean_ondemand("plugin:proc:/proc/net/dev", "fifo for all interfaces", CONFIG_ONDEMAND_ONDEMAND);
- if(do_compressed == -1) do_compressed = config_get_boolean_ondemand("plugin:proc:/proc/net/dev", "compressed packets for all interfaces", CONFIG_ONDEMAND_ONDEMAND);
- if(do_events == -1) do_events = config_get_boolean_ondemand("plugin:proc:/proc/net/dev", "frames, collisions, carrier counters for all interfaces", CONFIG_ONDEMAND_ONDEMAND);
+ if(unlikely(!ff)) return 0; // we return 0, so that we will retry to open it next time
uint32_t lines = procfile_lines(ff), l;
-
- char *iface;
- unsigned long long rbytes, rpackets, rerrors, rdrops, rfifo, rframe, rcompressed, rmulticast;
- unsigned long long tbytes, tpackets, terrors, tdrops, tfifo, tcollisions, tcarrier, tcompressed;
-
for(l = 2; l < lines ;l++) {
- uint32_t words = procfile_linewords(ff, l);
- if(words < 17) continue;
-
- iface = procfile_lineword(ff, l, 0);
-
- rbytes = strtoull(procfile_lineword(ff, l, 1), NULL, 10);
- rpackets = strtoull(procfile_lineword(ff, l, 2), NULL, 10);
- rerrors = strtoull(procfile_lineword(ff, l, 3), NULL, 10);
- rdrops = strtoull(procfile_lineword(ff, l, 4), NULL, 10);
- rfifo = strtoull(procfile_lineword(ff, l, 5), NULL, 10);
- rframe = strtoull(procfile_lineword(ff, l, 6), NULL, 10);
- rcompressed = strtoull(procfile_lineword(ff, l, 7), NULL, 10);
- rmulticast = strtoull(procfile_lineword(ff, l, 8), NULL, 10);
-
- tbytes = strtoull(procfile_lineword(ff, l, 9), NULL, 10);
- tpackets = strtoull(procfile_lineword(ff, l, 10), NULL, 10);
- terrors = strtoull(procfile_lineword(ff, l, 11), NULL, 10);
- tdrops = strtoull(procfile_lineword(ff, l, 12), NULL, 10);
- tfifo = strtoull(procfile_lineword(ff, l, 13), NULL, 10);
- tcollisions = strtoull(procfile_lineword(ff, l, 14), NULL, 10);
- tcarrier = strtoull(procfile_lineword(ff, l, 15), NULL, 10);
- tcompressed = strtoull(procfile_lineword(ff, l, 16), NULL, 10);
-
- int ddo_bandwidth = do_bandwidth, ddo_packets = do_packets, ddo_errors = do_errors, ddo_drops = do_drops, ddo_fifo = do_fifo, ddo_compressed = do_compressed, ddo_events = do_events;
-
- int default_enable = enable_new_interfaces;
-
- // prevent unused interfaces from creating charts
- if(strcmp(iface, "lo") == 0)
- default_enable = 0;
- else {
- int len = strlen(iface);
- if(len >= 4 && strcmp(&iface[len-4], "-ifb") == 0)
- default_enable = enable_ifb_interfaces;
- }
+ // require 17 words on each line
+ if(unlikely(procfile_linewords(ff, l) < 17)) continue;
+
+ struct netdev *d = get_netdev(procfile_lineword(ff, l, 0));
+
+ if(unlikely(!d->configured)) {
+ // this is the first time we see this interface
+
+ // remember we configured it
+ d->configured = 1;
+
+ // start with the default enabled flag
+ d->enabled = enable_new_interfaces;
+ if(d->enabled) {
+ if(unlikely(!strcmp(d->name, "lo")))
+ d->enabled = CONFIG_ONDEMAND_NO;
+ else if(unlikely(!strncmp(d->name, "veth", 4)))
+ d->enabled = enable_veth_interfaces;
+ else if(unlikely(d->len >= 4 && strcmp(&d->name[d->len - 4], "-ifb") == 0))
+ d->enabled = enable_ifb_interfaces;
+ }
- // check if the user wants it
- {
char var_name[512 + 1];
- snprintfz(var_name, 512, "plugin:proc:/proc/net/dev:%s", iface);
- default_enable = config_get_boolean_ondemand(var_name, "enabled", default_enable);
- if(default_enable == CONFIG_ONDEMAND_NO) continue;
- if(default_enable == CONFIG_ONDEMAND_ONDEMAND && !rbytes && !tbytes) continue;
-
- ddo_bandwidth = config_get_boolean_ondemand(var_name, "bandwidth", ddo_bandwidth);
- ddo_packets = config_get_boolean_ondemand(var_name, "packets", ddo_packets);
- ddo_errors = config_get_boolean_ondemand(var_name, "errors", ddo_errors);
- ddo_drops = config_get_boolean_ondemand(var_name, "drops", ddo_drops);
- ddo_fifo = config_get_boolean_ondemand(var_name, "fifo", ddo_fifo);
- ddo_compressed = config_get_boolean_ondemand(var_name, "compressed", ddo_compressed);
- ddo_events = config_get_boolean_ondemand(var_name, "events", ddo_events);
-
- if(ddo_bandwidth == CONFIG_ONDEMAND_ONDEMAND && rbytes == 0 && tbytes == 0) ddo_bandwidth = 0;
- if(ddo_errors == CONFIG_ONDEMAND_ONDEMAND && rerrors == 0 && terrors == 0) ddo_errors = 0;
- if(ddo_drops == CONFIG_ONDEMAND_ONDEMAND && rdrops == 0 && tdrops == 0) ddo_drops = 0;
- if(ddo_fifo == CONFIG_ONDEMAND_ONDEMAND && rfifo == 0 && tfifo == 0) ddo_fifo = 0;
- if(ddo_compressed == CONFIG_ONDEMAND_ONDEMAND && rcompressed == 0 && tcompressed == 0) ddo_compressed = 0;
- if(ddo_events == CONFIG_ONDEMAND_ONDEMAND && rframe == 0 && tcollisions == 0 && tcarrier == 0) ddo_events = 0;
-
- // for absolute values, we need to switch the setting to 'yes'
- // to allow it refresh from now on
- // if(ddo_fifo == CONFIG_ONDEMAND_ONDEMAND) config_set(var_name, "fifo", "yes");
+ snprintfz(var_name, 512, "plugin:proc:/proc/net/dev:%s", d->name);
+ d->enabled = config_get_boolean_ondemand(var_name, "enabled", d->enabled);
+
+ if(d->enabled == CONFIG_ONDEMAND_NO)
+ continue;
+
+ d->do_bandwidth = config_get_boolean_ondemand(var_name, "bandwidth", do_bandwidth);
+ d->do_packets = config_get_boolean_ondemand(var_name, "packets", do_packets);
+ d->do_errors = config_get_boolean_ondemand(var_name, "errors", do_errors);
+ d->do_drops = config_get_boolean_ondemand(var_name, "drops", do_drops);
+ d->do_fifo = config_get_boolean_ondemand(var_name, "fifo", do_fifo);
+ d->do_compressed = config_get_boolean_ondemand(var_name, "compressed", do_compressed);
+ d->do_events = config_get_boolean_ondemand(var_name, "events", do_events);
}
- RRDSET *st;
+ if(unlikely(!d->enabled))
+ continue;
+
+ d->rbytes = strtoull(procfile_lineword(ff, l, 1), NULL, 10);
+ d->rpackets = strtoull(procfile_lineword(ff, l, 2), NULL, 10);
+ d->rerrors = strtoull(procfile_lineword(ff, l, 3), NULL, 10);
+ d->rdrops = strtoull(procfile_lineword(ff, l, 4), NULL, 10);
+ d->rfifo = strtoull(procfile_lineword(ff, l, 5), NULL, 10);
+ d->rframe = strtoull(procfile_lineword(ff, l, 6), NULL, 10);
+ d->rcompressed = strtoull(procfile_lineword(ff, l, 7), NULL, 10);
+ d->rmulticast = strtoull(procfile_lineword(ff, l, 8), NULL, 10);
+
+ d->tbytes = strtoull(procfile_lineword(ff, l, 9), NULL, 10);
+ d->tpackets = strtoull(procfile_lineword(ff, l, 10), NULL, 10);
+ d->terrors = strtoull(procfile_lineword(ff, l, 11), NULL, 10);
+ d->tdrops = strtoull(procfile_lineword(ff, l, 12), NULL, 10);
+ d->tfifo = strtoull(procfile_lineword(ff, l, 13), NULL, 10);
+ d->tcollisions = strtoull(procfile_lineword(ff, l, 14), NULL, 10);
+ d->tcarrier = strtoull(procfile_lineword(ff, l, 15), NULL, 10);
+ d->tcompressed = strtoull(procfile_lineword(ff, l, 16), NULL, 10);
// --------------------------------------------------------------------
- if(ddo_bandwidth) {
- st = rrdset_find_bytype("net", iface);
- if(!st) {
- st = rrdset_create("net", iface, NULL, iface, "net.net", "Bandwidth", "kilobits/s", 7000, update_every, RRDSET_TYPE_AREA);
+ if(unlikely((d->do_bandwidth == CONFIG_ONDEMAND_ONDEMAND && (d->rbytes || d->tbytes))))
+ d->do_bandwidth = CONFIG_ONDEMAND_YES;
+
+ if(d->do_bandwidth == CONFIG_ONDEMAND_YES) {
+ if(unlikely(!d->st_bandwidth)) {
+ d->st_bandwidth = rrdset_find_bytype("net", d->name);
- rrddim_add(st, "received", NULL, 8, 1024, RRDDIM_INCREMENTAL);
- rrddim_add(st, "sent", NULL, -8, 1024, RRDDIM_INCREMENTAL);
+ if(!d->st_bandwidth) {
+ d->st_bandwidth = rrdset_create("net", d->name, NULL, d->name, "net.net", "Bandwidth", "kilobits/s", 7000, update_every, RRDSET_TYPE_AREA);
+ d->rd_rbytes = rrddim_add(d->st_bandwidth, "received", NULL, 8, 1024, RRDDIM_INCREMENTAL);
+ d->rd_tbytes = rrddim_add(d->st_bandwidth, "sent", NULL, -8, 1024, RRDDIM_INCREMENTAL);
+ }
}
- else rrdset_next(st);
+ else rrdset_next(d->st_bandwidth);
- rrddim_set(st, "received", rbytes);
- rrddim_set(st, "sent", tbytes);
- rrdset_done(st);
+ rrddim_set_by_pointer(d->st_bandwidth, d->rd_rbytes, d->rbytes);
+ rrddim_set_by_pointer(d->st_bandwidth, d->rd_tbytes, d->tbytes);
+ rrdset_done(d->st_bandwidth);
}
// --------------------------------------------------------------------
- if(ddo_packets) {
- st = rrdset_find_bytype("net_packets", iface);
- if(!st) {
- st = rrdset_create("net_packets", iface, NULL, iface, "net.packets", "Packets", "packets/s", 7001, update_every, RRDSET_TYPE_LINE);
- st->isdetail = 1;
+ if(unlikely((d->do_packets == CONFIG_ONDEMAND_ONDEMAND && (d->rpackets || d->tpackets || d->rmulticast))))
+ d->do_packets = CONFIG_ONDEMAND_YES;
- rrddim_add(st, "received", NULL, 1, 1, RRDDIM_INCREMENTAL);
- rrddim_add(st, "sent", NULL, -1, 1, RRDDIM_INCREMENTAL);
- rrddim_add(st, "multicast", NULL, 1, 1, RRDDIM_INCREMENTAL);
+ if(d->do_packets == CONFIG_ONDEMAND_YES) {
+ if(unlikely(!d->st_packets)) {
+ d->st_packets = rrdset_find_bytype("net_packets", d->name);
+
+ if(!d->st_packets) {
+ d->st_packets = rrdset_create("net_packets", d->name, NULL, d->name, "net.packets", "Packets", "packets/s", 7001, update_every, RRDSET_TYPE_LINE);
+ d->st_packets->isdetail = 1;
+
+ d->rd_rpackets = rrddim_add(d->st_packets, "received", NULL, 1, 1, RRDDIM_INCREMENTAL);
+ d->rd_tpackets = rrddim_add(d->st_packets, "sent", NULL, -1, 1, RRDDIM_INCREMENTAL);
+ d->rd_rmulticast = rrddim_add(d->st_packets, "multicast", NULL, 1, 1, RRDDIM_INCREMENTAL);
+ }
}
- else rrdset_next(st);
+ else rrdset_next(d->st_packets);
- rrddim_set(st, "received", rpackets);
- rrddim_set(st, "sent", tpackets);
- rrddim_set(st, "multicast", rmulticast);
- rrdset_done(st);
+ rrddim_set_by_pointer(d->st_packets, d->rd_rpackets, d->rpackets);
+ rrddim_set_by_pointer(d->st_packets, d->rd_tpackets, d->tpackets);
+ rrddim_set_by_pointer(d->st_packets, d->rd_rmulticast, d->rmulticast);
+ rrdset_done(d->st_packets);
}
// --------------------------------------------------------------------
- if(ddo_errors) {
- st = rrdset_find_bytype("net_errors", iface);
- if(!st) {
- st = rrdset_create("net_errors", iface, NULL, iface, "net.errors", "Interface Errors", "errors/s", 7002, update_every, RRDSET_TYPE_LINE);
- st->isdetail = 1;
+ if(unlikely((d->do_errors == CONFIG_ONDEMAND_ONDEMAND && (d->rerrors || d->terrors))))
+ d->do_errors = CONFIG_ONDEMAND_YES;
+
+ if(d->do_errors == CONFIG_ONDEMAND_YES) {
+ if(unlikely(!d->st_errors)) {
+ d->st_errors = rrdset_find_bytype("net_errors", d->name);
- rrddim_add(st, "inbound", NULL, 1, 1, RRDDIM_INCREMENTAL);
- rrddim_add(st, "outbound", NULL, -1, 1, RRDDIM_INCREMENTAL);
+ if(!d->st_errors) {
+ d->st_errors = rrdset_create("net_errors", d->name, NULL, d->name, "net.errors", "Interface Errors", "errors/s", 7002, update_every, RRDSET_TYPE_LINE);
+ d->st_errors->isdetail = 1;
+
+ d->rd_rerrors = rrddim_add(d->st_errors, "inbound", NULL, 1, 1, RRDDIM_INCREMENTAL);
+ d->rd_terrors = rrddim_add(d->st_errors, "outbound", NULL, -1, 1, RRDDIM_INCREMENTAL);
+ }
}
- else rrdset_next(st);
+ else rrdset_next(d->st_errors);
- rrddim_set(st, "inbound", rerrors);
- rrddim_set(st, "outbound", terrors);
- rrdset_done(st);
+ rrddim_set_by_pointer(d->st_errors, d->rd_rerrors, d->rerrors);
+ rrddim_set_by_pointer(d->st_errors, d->rd_terrors, d->terrors);
+ rrdset_done(d->st_errors);
}
// --------------------------------------------------------------------
- if(ddo_drops) {
- st = rrdset_find_bytype("net_drops", iface);
- if(!st) {
- st = rrdset_create("net_drops", iface, NULL, iface, "net.drops", "Interface Drops", "drops/s", 7003, update_every, RRDSET_TYPE_LINE);
- st->isdetail = 1;
+ if(unlikely((d->do_drops == CONFIG_ONDEMAND_ONDEMAND && (d->rdrops || d->tdrops))))
+ d->do_drops = CONFIG_ONDEMAND_YES;
+
+ if(d->do_drops == CONFIG_ONDEMAND_YES) {
+ if(unlikely(!d->st_drops)) {
+ d->st_drops = rrdset_find_bytype("net_drops", d->name);
- rrddim_add(st, "inbound", NULL, 1, 1, RRDDIM_INCREMENTAL);
- rrddim_add(st, "outbound", NULL, -1, 1, RRDDIM_INCREMENTAL);
+ if(!d->st_drops) {
+ d->st_drops = rrdset_create("net_drops", d->name, NULL, d->name, "net.drops", "Interface Drops", "drops/s", 7003, update_every, RRDSET_TYPE_LINE);
+ d->st_drops->isdetail = 1;
+
+ d->rd_rdrops = rrddim_add(d->st_drops, "inbound", NULL, 1, 1, RRDDIM_INCREMENTAL);
+ d->rd_tdrops = rrddim_add(d->st_drops, "outbound", NULL, -1, 1, RRDDIM_INCREMENTAL);
+ }
}
- else rrdset_next(st);
+ else rrdset_next(d->st_drops);
- rrddim_set(st, "inbound", rdrops);
- rrddim_set(st, "outbound", tdrops);
- rrdset_done(st);
+ rrddim_set_by_pointer(d->st_drops, d->rd_rdrops, d->rdrops);
+ rrddim_set_by_pointer(d->st_drops, d->rd_tdrops, d->tdrops);
+ rrdset_done(d->st_drops);
}
// --------------------------------------------------------------------
- if(ddo_fifo) {
- st = rrdset_find_bytype("net_fifo", iface);
- if(!st) {
- st = rrdset_create("net_fifo", iface, NULL, iface, "net.fifo", "Interface FIFO Buffer Errors", "errors", 7004, update_every, RRDSET_TYPE_LINE);
- st->isdetail = 1;
+ if(unlikely((d->do_fifo == CONFIG_ONDEMAND_ONDEMAND && (d->rfifo || d->tfifo))))
+ d->do_fifo = CONFIG_ONDEMAND_YES;
+
+ if(d->do_fifo == CONFIG_ONDEMAND_YES) {
+ if(unlikely(!d->st_fifo)) {
+ d->st_fifo = rrdset_find_bytype("net_fifo", d->name);
- rrddim_add(st, "receive", NULL, 1, 1, RRDDIM_INCREMENTAL);
- rrddim_add(st, "transmit", NULL, -1, 1, RRDDIM_INCREMENTAL);
+ if(!d->st_fifo) {
+ d->st_fifo = rrdset_create("net_fifo", d->name, NULL, d->name, "net.fifo", "Interface FIFO Buffer Errors", "errors", 7004, update_every, RRDSET_TYPE_LINE);
+ d->st_fifo->isdetail = 1;
+
+ d->rd_rfifo = rrddim_add(d->st_fifo, "receive", NULL, 1, 1, RRDDIM_INCREMENTAL);
+ d->rd_tfifo = rrddim_add(d->st_fifo, "transmit", NULL, -1, 1, RRDDIM_INCREMENTAL);
+ }
}
- else rrdset_next(st);
+ else rrdset_next(d->st_fifo);
- rrddim_set(st, "receive", rfifo);
- rrddim_set(st, "transmit", tfifo);
- rrdset_done(st);
+ rrddim_set_by_pointer(d->st_fifo, d->rd_rfifo, d->rfifo);
+ rrddim_set_by_pointer(d->st_fifo, d->rd_tfifo, d->tfifo);
+ rrdset_done(d->st_fifo);
}
// --------------------------------------------------------------------
- if(ddo_compressed) {
- st = rrdset_find_bytype("net_compressed", iface);
- if(!st) {
- st = rrdset_create("net_compressed", iface, NULL, iface, "net.compressed", "Compressed Packets", "packets/s", 7005, update_every, RRDSET_TYPE_LINE);
- st->isdetail = 1;
+ if(unlikely((d->do_compressed == CONFIG_ONDEMAND_ONDEMAND && (d->rcompressed || d->tcompressed))))
+ d->do_compressed = CONFIG_ONDEMAND_YES;
+
+ if(d->do_compressed == CONFIG_ONDEMAND_YES) {
+ if(unlikely(!d->st_compressed)) {
+ d->st_compressed = rrdset_find_bytype("net_compressed", d->name);
+ if(!d->st_compressed) {
+ d->st_compressed = rrdset_create("net_compressed", d->name, NULL, d->name, "net.compressed", "Compressed Packets", "packets/s", 7005, update_every, RRDSET_TYPE_LINE);
+ d->st_compressed->isdetail = 1;
- rrddim_add(st, "received", NULL, 1, 1, RRDDIM_INCREMENTAL);
- rrddim_add(st, "sent", NULL, -1, 1, RRDDIM_INCREMENTAL);
+ d->rd_rcompressed = rrddim_add(d->st_compressed, "received", NULL, 1, 1, RRDDIM_INCREMENTAL);
+ d->rd_tcompressed = rrddim_add(d->st_compressed, "sent", NULL, -1, 1, RRDDIM_INCREMENTAL);
+ }
}
- else rrdset_next(st);
+ else rrdset_next(d->st_compressed);
- rrddim_set(st, "received", rcompressed);
- rrddim_set(st, "sent", tcompressed);
- rrdset_done(st);
+ rrddim_set_by_pointer(d->st_compressed, d->rd_rcompressed, d->rcompressed);
+ rrddim_set_by_pointer(d->st_compressed, d->rd_tcompressed, d->tcompressed);
+ rrdset_done(d->st_compressed);
}
// --------------------------------------------------------------------
- if(ddo_events) {
- st = rrdset_find_bytype("net_events", iface);
- if(!st) {
- st = rrdset_create("net_events", iface, NULL, iface, "net.events", "Network Interface Events", "events/s", 7006, update_every, RRDSET_TYPE_LINE);
- st->isdetail = 1;
+ if(unlikely((d->do_events == CONFIG_ONDEMAND_ONDEMAND && (d->rframe || d->tcollisions || d->tcarrier))))
+ d->do_events = CONFIG_ONDEMAND_YES;
+
+ if(d->do_events == CONFIG_ONDEMAND_YES) {
+ if(unlikely(!d->st_events)) {
+ d->st_events = rrdset_find_bytype("net_events", d->name);
+ if(!d->st_events) {
+ d->st_events = rrdset_create("net_events", d->name, NULL, d->name, "net.events", "Network Interface Events", "events/s", 7006, update_every, RRDSET_TYPE_LINE);
+ d->st_events->isdetail = 1;
- rrddim_add(st, "frames", NULL, 1, 1, RRDDIM_INCREMENTAL);
- rrddim_add(st, "collisions", NULL, -1, 1, RRDDIM_INCREMENTAL);
- rrddim_add(st, "carrier", NULL, -1, 1, RRDDIM_INCREMENTAL);
+ d->rd_rframe = rrddim_add(d->st_events, "frames", NULL, 1, 1, RRDDIM_INCREMENTAL);
+ d->rd_tcollisions = rrddim_add(d->st_events, "collisions", NULL, -1, 1, RRDDIM_INCREMENTAL);
+ d->rd_tcarrier = rrddim_add(d->st_events, "carrier", NULL, -1, 1, RRDDIM_INCREMENTAL);
+ }
}
- else rrdset_next(st);
+ else rrdset_next(d->st_events);
- rrddim_set(st, "frames", rframe);
- rrddim_set(st, "collisions", tcollisions);
- rrddim_set(st, "carrier", tcarrier);
- rrdset_done(st);
+ rrddim_set_by_pointer(d->st_events, d->rd_rframe, d->rframe);
+ rrddim_set_by_pointer(d->st_events, d->rd_tcollisions, d->tcollisions);
+ rrddim_set_by_pointer(d->st_events, d->rd_tcarrier, d->tcarrier);
+ rrdset_done(d->st_events);
}
}