From: Costa Tsaousis Date: Mon, 14 Nov 2016 20:18:44 +0000 (+0200) Subject: Merge pull request #1165 from kesslerm/fix/python-plugin-crash X-Git-Tag: v1.5.0~184 X-Git-Url: https://arthur.barton.de/gitweb/?a=commitdiff_plain;h=f2db420a77c9dee11575302ea90f5ecf7fcfb349;hp=72b9c272ccf38782bf6fbcc98810e66ae376a46b;p=netdata.git Merge pull request #1165 from kesslerm/fix/python-plugin-crash Fix occasional crashes in python plugins --- diff --git a/CMakeLists.txt b/CMakeLists.txt index 9c4aa760..fc9252aa 100755 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -26,6 +26,8 @@ set(NETDATA_SOURCE_FILES src/global_statistics.h src/health.c src/health.h + src/ipc.c + src/ipc.h src/log.c src/log.h src/main.c diff --git a/charts.d/mysql.chart.sh b/charts.d/mysql.chart.sh index 86feac99..1363d01f 100755 --- a/charts.d/mysql.chart.sh +++ b/charts.d/mysql.chart.sh @@ -55,7 +55,7 @@ mysql_check() { shift fi - [ -z "${mysql_cmd}" ] && mysql_cmd="$(which mysql)" + [ -z "${mysql_cmd}" ] && mysql_cmd="$(which mysql 2>/dev/null || command -v mysql 2>/dev/null)" if [ ${#mysql_opts[@]} -eq 0 ] then diff --git a/charts.d/postfix.chart.sh b/charts.d/postfix.chart.sh index 8106414a..85604fcb 100755 --- a/charts.d/postfix.chart.sh +++ b/charts.d/postfix.chart.sh @@ -23,7 +23,7 @@ postfix_check() { # try to find the postqueue executable if [ -z "$postfix_postqueue" -o ! -x "$postfix_postqueue" ] then - postfix_postqueue="`which postqueue 2>/dev/null`" + postfix_postqueue="$(which postqueue 2>/dev/null || command -v postqueue 2>/dev/null)" fi if [ -z "$postfix_postqueue" -o ! -x "$postfix_postqueue" ] diff --git a/conf.d/Makefile.am b/conf.d/Makefile.am index c2ef258c..690b5e7c 100644 --- a/conf.d/Makefile.am +++ b/conf.d/Makefile.am @@ -4,67 +4,70 @@ MAINTAINERCLEANFILES= $(srcdir)/Makefile.in dist_config_DATA = \ - apps_groups.conf \ - charts.d.conf \ - fping.conf \ - node.d.conf \ - python.d.conf \ - health_alarm_notify.conf \ - health_email_recipients.conf \ - $(NULL) + apps_groups.conf \ + charts.d.conf \ + fping.conf \ + node.d.conf \ + python.d.conf \ + health_alarm_notify.conf \ + health_email_recipients.conf \ + $(NULL) chartsconfigdir=$(configdir)/charts.d dist_chartsconfig_DATA = \ - $(NULL) + $(NULL) nodeconfigdir=$(configdir)/node.d dist_nodeconfig_DATA = \ - node.d/README.md \ - node.d/named.conf.md \ - node.d/sma_webbox.conf.md \ - node.d/snmp.conf.md \ - $(NULL) + node.d/README.md \ + node.d/named.conf.md \ + node.d/sma_webbox.conf.md \ + node.d/snmp.conf.md \ + $(NULL) pythonconfigdir=$(configdir)/python.d dist_pythonconfig_DATA = \ - python.d/apache.conf \ - python.d/apache_cache.conf \ - python.d/cpufreq.conf \ - python.d/dovecot.conf \ - python.d/example.conf \ - python.d/exim.conf \ - python.d/hddtemp.conf \ - python.d/ipfs.conf \ - python.d/memcached.conf \ - python.d/mysql.conf \ - python.d/nginx.conf \ - python.d/nginx_log.conf \ - python.d/phpfpm.conf \ - python.d/postfix.conf \ - python.d/redis.conf \ - python.d/retroshare.conf \ - python.d/sensors.conf \ - python.d/squid.conf \ - python.d/tomcat.conf \ - $(NULL) + python.d/apache.conf \ + python.d/apache_cache.conf \ + python.d/cpufreq.conf \ + python.d/dovecot.conf \ + python.d/example.conf \ + python.d/exim.conf \ + python.d/hddtemp.conf \ + python.d/ipfs.conf \ + python.d/memcached.conf \ + python.d/mysql.conf \ + python.d/nginx.conf \ + python.d/nginx_log.conf \ + python.d/phpfpm.conf \ + python.d/postfix.conf \ + python.d/postgres.conf \ + python.d/redis.conf \ + python.d/retroshare.conf \ + python.d/sensors.conf \ + python.d/squid.conf \ + python.d/tomcat.conf \ + $(NULL) healthconfigdir=$(configdir)/health.d dist_healthconfig_DATA = \ - health.d/apache.conf \ - health.d/cpu.conf \ - health.d/disks.conf \ - health.d/entropy.conf \ - health.d/tcp_resets.conf \ - health.d/memcached.conf \ - health.d/mysql.conf \ - health.d/named.conf \ - health.d/net.conf \ - health.d/nginx.conf \ - health.d/qos.conf \ - health.d/ram.conf \ - health.d/redis.conf \ - health.d/retroshare.conf \ - health.d/softnet.conf \ - health.d/swap.conf \ - health.d/squid.conf \ - $(NULL) + health.d/apache.conf \ + health.d/cpu.conf \ + health.d/disks.conf \ + health.d/entropy.conf \ + health.d/ipc.conf \ + health.d/memcached.conf \ + health.d/mysql.conf \ + health.d/named.conf \ + health.d/net.conf \ + health.d/nginx.conf \ + health.d/postgres.conf \ + health.d/qos.conf \ + health.d/ram.conf \ + health.d/redis.conf \ + health.d/retroshare.conf \ + health.d/softnet.conf \ + health.d/squid.conf \ + health.d/swap.conf \ + health.d/tcp_resets.conf \ + $(NULL) diff --git a/conf.d/apps_groups.conf b/conf.d/apps_groups.conf index 57357a87..23131e35 100644 --- a/conf.d/apps_groups.conf +++ b/conf.d/apps_groups.conf @@ -202,7 +202,7 @@ ksmd: ksmd # ----------------------------------------------------------------------------- # media players, servers, clients -media: mplayer vlc xine mediatomb omxplayer* kodi* xbmc* mediacenter eventlircd mpd minidlnad mt-daapd avahi* +media: mplayer vlc xine mediatomb omxplayer* kodi* xbmc* mediacenter eventlircd mpd minidlnad mt-daapd avahi* Plex* # ----------------------------------------------------------------------------- # X diff --git a/conf.d/fping.conf b/conf.d/fping.conf index 3bf80477..82ee2332 100644 --- a/conf.d/fping.conf +++ b/conf.d/fping.conf @@ -1,32 +1,44 @@ -# This plugin requires a special version of fping. -# Get it from https://github.com/ktsaou/fping -# and build it, like this: +# no need for shebang - this file is sourced from fping.plugin + +# fping.plugin requires a recent version of fping. # -# cd /usr/src -# git clone https://github.com/ktsaou/fping.git fping-netdata.git -# cd fping-netdata.git -# ./autogen.sh -# ./configure --prefix=/usr/local -# make -# cp src/fping /usr/local/bin/ -# chown root:root /usr/local/bin/fping -# chmod 4755 /usr/local/bin/fping +# You can get it on your system, by running: # +# /usr/libexec/netdata/plugins.d/fping.plugin install + # ----------------------------------------------------------------------------- # configuration options -# can be overwritten at /etc/netdata/fping.conf -# the fping binary to use -# we need one that can output netdata friendly info -fping="$(which fping || command -v fping)" +# The fping binary to use. We need one that can output netdata friendly info +# (supporting: -N). If you have multiple versions, put here the full filename +# of the right one + +#fping="/usr/local/bin/fping" + # a space separated list of hosts to fping -# it is best to put hostnames here +# we suggest to put names here and the IPs of these names in /etc/hosts + hosts="" -# the time in milliseconds (1 sec = 1000 ms) -# to ping the hosts - by default 2 pings per iteration -ping_every="$((update_every * 1000 / 2))" -# how many retries to make if a host does not respond -retries=1 +# The update frequency of the chart - the default is inherited from netdata + +#update_every=2 + + +# The time in milliseconds (1 sec = 1000 ms) to ping the hosts +# by default 5 pings per host per iteration +# fping will now allow this to be below 20ms + +#ping_every="200" + + +# other fping options - defaults: +# -R = send packets with random data +# -b 56 = the number of bytes per packet +# -i 1 = 1 ms when sending packets to others hosts (switching hosts) +# -r 0 = never retry packets +# -t 5000 = per packet timeout at 5000 ms + +#fping_opts="-R -b 56 -i 1 -r 0 -t 5000" diff --git a/conf.d/health.d/apache.conf b/conf.d/health.d/apache.conf index 0aaf0e00..0c98b877 100644 --- a/conf.d/health.d/apache.conf +++ b/conf.d/health.d/apache.conf @@ -6,8 +6,8 @@ template: apache_last_collected_secs calc: $now - $last_collected_t units: seconds ago every: 10s - warn: $this > (($status >= $WARNING) ? (0) : ( 5 * $update_every)) - crit: $this > (($status == $CRITICAL) ? (0) : (60 * $update_every)) + warn: $this > (($status >= $WARNING) ? ($update_every) : ( 5 * $update_every)) + crit: $this > (($status == $CRITICAL) ? ($update_every) : (60 * $update_every)) delay: down 5m multiplier 1.5 max 1h info: number of seconds since the last successful data collection to: webmaster diff --git a/conf.d/health.d/cpu.conf b/conf.d/health.d/cpu.conf index 4d79fc79..2b04c794 100644 --- a/conf.d/health.d/cpu.conf +++ b/conf.d/health.d/cpu.conf @@ -4,8 +4,8 @@ template: 10min_cpu_usage lookup: average -10m unaligned of user,system,nice,softirq,irq,guest,guest_nice units: % every: 1m - warn: $this > (($status >= $WARNING) ? (70) : (80)) - crit: $this > (($status == $CRITICAL) ? (80) : (90)) + warn: $this > (($status >= $WARNING) ? (75) : (85)) + crit: $this > (($status == $CRITICAL) ? (85) : (95)) delay: down 15m multiplier 1.5 max 1h info: average cpu utilization for the last 10 minutes to: sysadmin @@ -15,8 +15,8 @@ template: 10min_cpu_iowait lookup: average -10m unaligned of iowait units: % every: 1m - warn: $this > (($status >= $WARNING) ? (5) : (10)) - crit: $this > (($status == $CRITICAL) ? (20) : (30)) + warn: $this > (($status >= $WARNING) ? (20) : (40)) + crit: $this > (($status == $CRITICAL) ? (40) : (50)) delay: down 15m multiplier 1.5 max 1h info: average CPU wait I/O for the last 10 minutes to: sysadmin diff --git a/conf.d/health.d/disks.conf b/conf.d/health.d/disks.conf index cc7a4766..8e375316 100644 --- a/conf.d/health.d/disks.conf +++ b/conf.d/health.d/disks.conf @@ -7,8 +7,8 @@ template: disk_space_last_collected_secs calc: $now - $last_collected_t units: seconds ago every: 10s - warn: $this > (($status >= $WARNING) ? (0) : ( 5 * $update_every)) - crit: $this > (($status == $CRITICAL) ? (0) : (60 * $update_every)) + warn: $this > (($status >= $WARNING) ? ($update_every) : ( 5 * $update_every)) + crit: $this > (($status == $CRITICAL) ? ($update_every) : (60 * $update_every)) delay: down 5m multiplier 1.5 max 1h info: number of seconds since the last successful data collection of the mount point to: sysadmin @@ -19,8 +19,8 @@ template: disk_last_collected_secs calc: $now - $last_collected_t units: seconds ago every: 10s - warn: $this > (($status >= $WARNING) ? (0) : ( 5 * $update_every)) - crit: $this > (($status == $CRITICAL) ? (0) : (60 * $update_every)) + warn: $this > (($status >= $WARNING) ? ($update_every) : ( 5 * $update_every)) + crit: $this > (($status == $CRITICAL) ? ($update_every) : (60 * $update_every)) delay: down 5m multiplier 1.5 max 1h info: number of seconds since the last successful data collection of the block device to: sysadmin @@ -38,8 +38,8 @@ template: disk_space_usage calc: $used * 100 / ($avail + $used) units: % every: 1m - warn: $this > (($status >= $WARNING ) ? (70) : (80)) - crit: $this > (($status == $CRITICAL) ? (85) : (95)) + warn: $this > (($status >= $WARNING ) ? (80) : (90)) + crit: $this > (($status == $CRITICAL) ? (90) : (98)) delay: up 1m down 15m multiplier 1.5 max 1h info: current disk space usage to: sysadmin @@ -49,8 +49,8 @@ template: disk_inode_usage calc: $used * 100 / ($avail + $used) units: % every: 1m - warn: $this > (($status >= $WARNING) ? (75) : (80)) - crit: $this > (($status == $CRITICAL) ? (90) : (95)) + warn: $this > (($status >= $WARNING) ? (80) : (90)) + crit: $this > (($status == $CRITICAL) ? (90) : (98)) delay: up 1m down 15m multiplier 1.5 max 1h info: current disk inode usage to: sysadmin @@ -82,7 +82,7 @@ template: disk_fill_rate template: out_of_disk_space_time on: disk.space - calc: $avail / $disk_fill_rate + calc: ($disk_fill_rate > 0) ? ($avail / $disk_fill_rate) : (0) units: hours every: 10s warn: $this > 0 and $this < (($status >= $WARNING) ? (48) : (8)) diff --git a/conf.d/health.d/ipc.conf b/conf.d/health.d/ipc.conf new file mode 100644 index 00000000..ee7c4bad --- /dev/null +++ b/conf.d/health.d/ipc.conf @@ -0,0 +1,22 @@ + + alarm: semaphores_used + on: system.ipc_semaphores + calc: $semaphores * 100 / $ipc.semaphores.max + units: % + every: 10s + warn: $this > (($status >= $WARNING) ? (70) : (80)) + crit: $this > (($status == $CRITICAL) ? (70) : (90)) + delay: down 5m multiplier 1.5 max 1h + info: the percentage of IPC semaphores used + to: sysadmin + + alarm: semaphore_arrays_used + on: system.ipc_semaphore_arrays + calc: $arrays * 100 / $ipc.semaphores.arrays.max + units: % + every: 10s + warn: $this > (($status >= $WARNING) ? (70) : (80)) + crit: $this > (($status == $CRITICAL) ? (70) : (90)) + delay: down 5m multiplier 1.5 max 1h + info: the percentage of IPC semaphore arrays used + to: sysadmin diff --git a/conf.d/health.d/memcached.conf b/conf.d/health.d/memcached.conf index 46a8ca0e..7917e36a 100644 --- a/conf.d/health.d/memcached.conf +++ b/conf.d/health.d/memcached.conf @@ -6,8 +6,8 @@ template: memcached_last_collected_secs calc: $now - $last_collected_t units: seconds ago every: 10s - warn: $this > (($status >= $WARNING) ? (0) : ( 5 * $update_every)) - crit: $this > (($status == $CRITICAL) ? (0) : (60 * $update_every)) + warn: $this > (($status >= $WARNING) ? ($update_every) : ( 5 * $update_every)) + crit: $this > (($status == $CRITICAL) ? ($update_every) : (60 * $update_every)) delay: down 5m multiplier 1.5 max 1h info: number of seconds since the last successful data collection to: dba @@ -42,7 +42,7 @@ template: cache_fill_rate template: out_of_cache_space_time on: memcached.cache - calc: $available / $cache_fill_rate + calc: ($cache_fill_rate > 0) ? ($available / $cache_fill_rate) : (0) units: hours every: 10s warn: $this > 0 and $this < (($status >= $WARNING) ? (48) : (8)) diff --git a/conf.d/health.d/mysql.conf b/conf.d/health.d/mysql.conf index a2cfa3ec..f95d7c59 100644 --- a/conf.d/health.d/mysql.conf +++ b/conf.d/health.d/mysql.conf @@ -6,8 +6,8 @@ template: mysql_last_collected_secs calc: $now - $last_collected_t units: seconds ago every: 10s - warn: $this > (($status >= $WARNING) ? (0) : ( 5 * $update_every)) - crit: $this > (($status == $CRITICAL) ? (0) : (60 * $update_every)) + warn: $this > (($status >= $WARNING) ? ($update_every) : ( 5 * $update_every)) + crit: $this > (($status == $CRITICAL) ? ($update_every) : (60 * $update_every)) delay: down 5m multiplier 1.5 max 1h info: number of seconds since the last successful data collection to: dba diff --git a/conf.d/health.d/named.conf b/conf.d/health.d/named.conf index f2eaa83c..4fc65c8e 100644 --- a/conf.d/health.d/named.conf +++ b/conf.d/health.d/named.conf @@ -6,8 +6,8 @@ template: named_last_collected_secs calc: $now - $last_collected_t units: seconds ago every: 10s - warn: $this > (($status >= $WARNING) ? (0) : ( 5 * $update_every)) - crit: $this > (($status == $CRITICAL) ? (0) : (60 * $update_every)) + warn: $this > (($status >= $WARNING) ? ($update_every) : ( 5 * $update_every)) + crit: $this > (($status == $CRITICAL) ? ($update_every) : (60 * $update_every)) delay: down 5m multiplier 1.5 max 1h info: number of seconds since the last successful data collection to: domainadmin diff --git a/conf.d/health.d/net.conf b/conf.d/health.d/net.conf index 7753aa18..f969f17b 100644 --- a/conf.d/health.d/net.conf +++ b/conf.d/health.d/net.conf @@ -6,31 +6,67 @@ template: interface_last_collected_secs calc: $now - $last_collected_t units: seconds ago every: 10s - warn: $this > (($status >= $WARNING) ? (0) : ( 5 * $update_every)) - crit: $this > (($status == $CRITICAL) ? (0) : (60 * $update_every)) + warn: $this > (($status >= $WARNING) ? ($update_every) : ( 5 * $update_every)) + crit: $this > (($status == $CRITICAL) ? ($update_every) : (60 * $update_every)) delay: down 5m multiplier 1.5 max 1h info: number of seconds since the last successful data collection to: sysadmin # ----------------------------------------------------------------------------- +# dropped packets # check if an interface is dropping packets # the alarm is checked every 1 minute # and examines the last hour of data -template: 1hour_packet_drops +template: 1hour_packet_drops_inbound on: net.drops - lookup: sum -1h unaligned absolute + lookup: sum -1h unaligned absolute of inbound units: packets every: 1m warn: $this > 0 delay: down 30m multiplier 1.5 max 1h - info: interface dropped packets in the last hour + info: interface inbound dropped packets in the last hour + to: sysadmin + +template: 1hour_packet_drops_outbound + on: net.drops + lookup: sum -1h unaligned absolute of outbound + units: packets + every: 1m + warn: $this > 0 + delay: down 30m multiplier 1.5 max 1h + info: interface outbound dropped packets in the last hour + to: sysadmin + +template: 1hour_packet_drops_ratio_inbound + on: net.packets + lookup: sum -1h unaligned absolute of received + calc: (($1hour_packet_drops_inbound != nan AND $this > 0) ? ($1hour_packet_drops_inbound * 100 / $this) : (0)) + units: % + every: 1m + warn: $this > 0.5 + crit: $this > 3 + delay: down 30m multiplier 1.5 max 1h + info: the ratio of inbound dropped packets vs the total number of received packets of the network interface, during the last hour + to: sysadmin + +template: 1hour_packet_drops_ratio_outbound + on: net.packets + lookup: sum -1h unaligned absolute of sent + calc: (($1hour_packet_drops_outbound != nan AND $this > 0) ? ($1hour_packet_drops_outbound * 100 / $this) : (0)) + units: % + every: 1m + warn: $this > 0.5 + crit: $this > 3 + delay: down 30m multiplier 1.5 max 1h + info: the ratio of outbound dropped packets vs the total number of sent packets of the network interface, during the last hour to: sysadmin # ----------------------------------------------------------------------------- +# FIFO errors # check if an interface is having FIFO # buffer errors @@ -46,3 +82,32 @@ template: 1hour_fifo_errors delay: down 30m multiplier 1.5 max 1h info: interface fifo errors in the last hour to: sysadmin + + +# ----------------------------------------------------------------------------- +# check for packet storms + +# 1. calculate the rate packets are received in 1m: 1m_received_packets_rate +# 2. do the same for the last 10s +# 3. raise an alarm if the later is 10x or 20x the first +# we assume the minimum packet storm should at least have +# 10000 packets/s, average of the last 10 seconds + +template: 1m_received_packets_rate + on: net.packets + lookup: average -1m of received + units: packets + every: 10s + info: the average number of packets received during the last minute + +template: 10s_received_packets_storm + on: net.packets + lookup: average -10s of received + calc: $this * 100 / (($1m_received_packets_rate < 1000)?(1000):($1m_received_packets_rate)) + every: 10s + units: % + warn: $this > (($status >= $WARNING)?(200):(1000)) + crit: $this > (($status >= $WARNING)?(1000):(2000)) + info: the % of the rate of received packets in the last 10 seconds, compared to the rate of the last minute + to: silent + diff --git a/conf.d/health.d/nginx.conf b/conf.d/health.d/nginx.conf index d70d6a59..a686c3d9 100644 --- a/conf.d/health.d/nginx.conf +++ b/conf.d/health.d/nginx.conf @@ -6,8 +6,8 @@ template: nginx_last_collected_secs calc: $now - $last_collected_t units: seconds ago every: 10s - warn: $this > (($status >= $WARNING) ? (0) : ( 5 * $update_every)) - crit: $this > (($status == $CRITICAL) ? (0) : (60 * $update_every)) + warn: $this > (($status >= $WARNING) ? ($update_every) : ( 5 * $update_every)) + crit: $this > (($status == $CRITICAL) ? ($update_every) : (60 * $update_every)) delay: down 5m multiplier 1.5 max 1h info: number of seconds since the last successful data collection to: webmaster diff --git a/conf.d/health.d/postgres.conf b/conf.d/health.d/postgres.conf new file mode 100644 index 00000000..4e0583b8 --- /dev/null +++ b/conf.d/health.d/postgres.conf @@ -0,0 +1,13 @@ + +# make sure postgres is running + +template: postgres_last_collected_secs + on: postgres.db_stat_transactions + 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)) + delay: down 5m multiplier 1.5 max 1h + info: number of seconds since the last successful data collection + to: dba diff --git a/conf.d/health.d/ram.conf b/conf.d/health.d/ram.conf index 216b82fe..d60df75b 100644 --- a/conf.d/health.d/ram.conf +++ b/conf.d/health.d/ram.conf @@ -4,8 +4,8 @@ calc: $used * 100 / ($used + $cached + $free) units: % every: 10s - warn: $this > (($status >= $WARNING) ? (70) : (80)) - crit: $this > (($status == $CRITICAL) ? (80) : (90)) + warn: $this > (($status >= $WARNING) ? (80) : (90)) + crit: $this > (($status == $CRITICAL) ? (90) : (98)) delay: down 15m multiplier 1.5 max 1h info: system RAM usage to: sysadmin diff --git a/conf.d/health.d/redis.conf b/conf.d/health.d/redis.conf index 3e648d85..5f6d397e 100644 --- a/conf.d/health.d/redis.conf +++ b/conf.d/health.d/redis.conf @@ -6,8 +6,8 @@ template: redis_last_collected_secs calc: $now - $last_collected_t units: seconds ago every: 10s - warn: $this > (($status >= $WARNING) ? (0) : ( 5 * $update_every)) - crit: $this > (($status == $CRITICAL) ? (0) : (60 * $update_every)) + warn: $this > (($status >= $WARNING) ? ($update_every) : ( 5 * $update_every)) + crit: $this > (($status == $CRITICAL) ? ($update_every) : (60 * $update_every)) delay: down 5m multiplier 1.5 max 1h info: number of seconds since the last successful data collection to: dba diff --git a/conf.d/health.d/retroshare.conf b/conf.d/health.d/retroshare.conf index 1af7b468..2344b60e 100644 --- a/conf.d/health.d/retroshare.conf +++ b/conf.d/health.d/retroshare.conf @@ -5,8 +5,8 @@ template: retroshare_last_collected_secs calc: $now - $last_collected_t units: seconds ago every: 10s - warn: $this > (($status >= $WARNING) ? (0) : ( 5 * $update_every)) - crit: $this > (($status == $CRITICAL) ? (0) : (60 * $update_every)) + warn: $this > (($status >= $WARNING) ? ($update_every) : ( 5 * $update_every)) + crit: $this > (($status == $CRITICAL) ? ($update_every) : (60 * $update_every)) delay: down 5m multiplier 1.5 max 1h info: number of seconds since the last successful data collection to: sysadmin diff --git a/conf.d/health.d/squid.conf b/conf.d/health.d/squid.conf index 76143c5d..06cc9678 100644 --- a/conf.d/health.d/squid.conf +++ b/conf.d/health.d/squid.conf @@ -6,8 +6,8 @@ template: squid_last_collected_secs calc: $now - $last_collected_t units: seconds ago every: 10s - warn: $this > (($status >= $WARNING) ? (0) : ( 5 * $update_every)) - crit: $this > (($status == $CRITICAL) ? (0) : (60 * $update_every)) + warn: $this > (($status >= $WARNING) ? ($update_every) : ( 5 * $update_every)) + crit: $this > (($status == $CRITICAL) ? ($update_every) : (60 * $update_every)) delay: down 5m multiplier 1.5 max 1h info: number of seconds since the last successful data collection to: proxyadmin diff --git a/conf.d/health.d/swap.conf b/conf.d/health.d/swap.conf index 0cfa888c..7f57560e 100644 --- a/conf.d/health.d/swap.conf +++ b/conf.d/health.d/swap.conf @@ -6,13 +6,13 @@ calc: $this / 1024 * 100 / ( $system.ram.used + $system.ram.cached + $system.ram.free ) units: % of RAM every: 1m - warn: $this > (($status >= $WARNING) ? (5) : (10)) - crit: $this > (($status == $CRITICAL) ? (15) : (20)) + warn: $this > (($status >= $WARNING) ? (10) : (20)) + crit: $this > (($status == $CRITICAL) ? (20) : (30)) delay: up 0 down 15m multiplier 1.5 max 1h info: the amount of memory swapped in the last 30 minutes, as a percentage of the system RAM to: sysadmin - alarm: used_swap_space + alarm: ram_in_swap on: system.swap calc: $used * 100 / ( $system.ram.used + $system.ram.cached + $system.ram.free ) units: % of RAM @@ -22,3 +22,14 @@ delay: up 0 down 15m multiplier 1.5 max 1h info: the swap memory used, as a percentage of the system RAM to: sysadmin + + alarm: used_swap + on: system.swap + calc: $used * 100 / ( $used + $free ) + units: % + every: 10s + warn: $this > (($status >= $WARNING) ? (80) : (90)) + crit: $this > (($status == $CRITICAL) ? (90) : (98)) + delay: up 0 down 15m multiplier 1.5 max 1h + info: the percentage of swap memory used + to: sysadmin diff --git a/conf.d/health.d/tcp_resets.conf b/conf.d/health.d/tcp_resets.conf index fbb7b389..a7cb325f 100644 --- a/conf.d/health.d/tcp_resets.conf +++ b/conf.d/health.d/tcp_resets.conf @@ -5,8 +5,8 @@ calc: $now - $last_collected_t units: seconds ago every: 10s - warn: $this > (($status >= $WARNING) ? (0) : ( 5 * $update_every)) - crit: $this > (($status == $CRITICAL) ? (0) : (60 * $update_every)) + warn: $this > (($status >= $WARNING) ? ($update_every) : ( 5 * $update_every)) + crit: $this > (($status == $CRITICAL) ? ($update_every) : (60 * $update_every)) delay: up 0 down 5m multiplier 1.5 max 1h info: number of seconds since the last successful data collection to: sysadmin diff --git a/conf.d/health_alarm_notify.conf b/conf.d/health_alarm_notify.conf index 3f0876e6..33a752f9 100644 --- a/conf.d/health_alarm_notify.conf +++ b/conf.d/health_alarm_notify.conf @@ -8,6 +8,7 @@ # - push notifications to your mobile phone (pushover.net), # - 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) # # The 'to' line given at netdata alarms defines a *role*, so that many # people can be notified for each role. @@ -60,6 +61,7 @@ curl="" # - pushover user tokens # - telegram chat ids # - slack channels +# - sms phone numbers # # You can append |critical to limit the notifications to be sent. # @@ -70,6 +72,7 @@ curl="" # pushover: "2987343...9437837 8756278...2362736|critical" # telegram: "111827421 112746832|critical" # slack : "alarms disasters|critical" +# twilio : "+15555555555 +17777777777|critical" # # If a recipient is set to empty string, the default recipient of the given # notification method (email, pushover, telegram, slack) will be used. @@ -133,6 +136,26 @@ SEND_PUSHBULLET="YES" PUSHBULLET_ACCESS_TOKEN="" DEFAULT_RECIPIENT_PUSHBULLET="" +############################################################################### +# Twilio (twilio.com) SMS options + +# multiple recipients can be given like this: +# "+15555555555 +17777777777" + +# enable/disable sending twilio SMS +SEND_TWILIO="YES" + +# Signup for free trial and select a SMS capable Twilio Number +# To get your Account SID and Token, go to https://www.twilio.com/console +# Place your sid, token and number below. +# Then just set the recipients' phone numbers. +# The trial account is only allowed to use the number specified when set up. + +# Without an account sid and token, netdata cannot send Twilio text messages. +TWILIO_ACCOUNT_SID="" +TWILIO_ACCOUNT_TOKEN="" +TWILIO_NUMBER="" +DEFAULT_RECIPIENT_TWILIO="" ############################################################################### # telegram (telegram.org) global notification options @@ -193,6 +216,7 @@ role_recipients_telegram[sysadmin]="${DEFAULT_RECIPIENT_TELEGRAM}" role_recipients_slack[sysadmin]="${DEFAULT_RECIPIENT_SLACK}" +role_recipients_twilio[sysadmin]="${DEFAULT_RECIPIENT_TWILIO}" # ----------------------------------------------------------------------------- # DNS related alarms @@ -207,6 +231,7 @@ role_recipients_telegram[domainadmin]="${DEFAULT_RECIPIENT_TELEGRAM}" role_recipients_slack[domainadmin]="${DEFAULT_RECIPIENT_SLACK}" +role_recipients_twilio[domainadmin]="${DEFAULT_RECIPIENT_TWILIO}" # ----------------------------------------------------------------------------- # database servers alarms @@ -222,6 +247,7 @@ role_recipients_telegram[dba]="${DEFAULT_RECIPIENT_TELEGRAM}" role_recipients_slack[dba]="${DEFAULT_RECIPIENT_SLACK}" +role_recipients_twilio[dba]="${DEFAULT_RECIPIENT_TWILIO}" # ----------------------------------------------------------------------------- # web servers alarms @@ -237,6 +263,7 @@ role_recipients_telegram[webmaster]="${DEFAULT_RECIPIENT_TELEGRAM}" role_recipients_slack[webmaster]="${DEFAULT_RECIPIENT_SLACK}" +role_recipients_twilio[webmaster]="${DEFAULT_RECIPIENT_TWILIO}" # ----------------------------------------------------------------------------- # proxy servers alarms @@ -251,3 +278,5 @@ role_recipients_pushbullet[proxyadmin]="${DEFAULT_RECIPIENT_PUSHBULLET}" role_recipients_telegram[proxyadmin]="${DEFAULT_RECIPIENT_TELEGRAM}" role_recipients_slack[proxyadmin]="${DEFAULT_RECIPIENT_SLACK}" + +role_recipients_twilio[proxyadmin]="${DEFAULT_RECIPIENT_TWILIO}" diff --git a/conf.d/python.d/postgres.conf b/conf.d/python.d/postgres.conf index 392c3fef..109f261c 100644 --- a/conf.d/python.d/postgres.conf +++ b/conf.d/python.d/postgres.conf @@ -55,22 +55,45 @@ # retries: 5 # the JOB's number of restoration attempts # # A single connection is required in order to pull statistics. +# # Connections can be configured with the following options: -# name : example_database_job_name -# database : example_db_name -# user : example_user -# password : example_pass -# host: localhost -# port: 5432 +# +# database : 'example_db_name' +# user : 'example_user' +# password : 'example_pass' +# host : 'localhost' +# port : 5432 # # Additionally, the following options allow selective disabling of charts # -# table_stats: false -# index_stats: false +# table_stats : false +# index_stats : false +# # ---------------------------------------------------------------------- -# Attempt to connect via the Unix socket as the postgres user. -unix_socket_superuser: - name : postgres - database : postgres +socket: + name : 'local' + user : 'postgres' + database : 'postgres' + +tcp: + name : 'local' + database : 'postgres' + user : 'postgres' + host : 'localhost' + port : 5432 + +tcpipv4: + name : 'local' + database : 'postgres' + user : 'postgres' + host : '127.0.0.1' + port : 5432 + +tcpipv6: + name : 'local' + database : 'postgres' + user : 'postgres' + host : '::1' + port : 5432 diff --git a/configs.signatures b/configs.signatures index 9a30f493..1c6d8068 100644 --- a/configs.signatures +++ b/configs.signatures @@ -1,259 +1,291 @@ declare -A configs_signatures=( ['0056936ce99788ed9ae1c611c87aa6d8']='apps_groups.conf' + ['02fa10fa85ab88e9723998de48d1aca0']='health.d/disks.conf' + ['0388b873d0d7e47c19005b7241db77d8']='python.d/tomcat.conf' + ['04138a3d8e907c75329fe60ce2e27c1c']='health.d/tcp_resets.conf' + ['0433d98a19d3b08e6f13884e46d39b47']='health.d/disks.conf' + ['043f0a35dde85837fabeb85b990a41c1']='health.d/swap.conf' + ['0529b679d3c0e7e6332753c7f6484731']='health.d/net.conf' + ['057d12aaff0467e64529e839a258806b']='health.d/entropy.conf' + ['061c45b0e34170d357e47883166ecf40']='python.d/nginx.conf' + ['074df527cc70b5f38c0714f08f20e57c']='health.d/apache.conf' + ['08042325ab27256b938575deafee8ecf']='python.d/nginx.conf' + ['084ee72d64760f2641b0720e79c922f3']='health.d/cpu.conf' + ['0856124b1eecf01681b4fdf4e21efb3f']='health.d/net.conf' + ['08ff5218f938fc48e09e718821169d14']='health.d/redis.conf' + ['091572888425bc3b8b559c3c53367ec7']='apps_groups.conf' + ['09264cec953ae1c4c2985e6446abb386']='health.d/mysql.conf' + ['0cd4e1fb57497e4d4c2451a9e58f724d']='python.d/redis.conf' + ['0e59bc11d0a869ea0247c04c08c8d72e']='python.d/ipfs.conf' + ['13141998a5d71308d9c119834c27bfd3']='python.d.conf' + ['142a5b693d34b0308bb0b8aec71fad79']='python.d/postfix.conf' + ['15d8401b56a74120f9f832873ec9c578']='health.d/postgres.conf' + ['15e32114994b92be7853b88091e7c6fb']='python.d/exim.conf' + ['174c21a6ce5de97bda83d502aa47a9f8']='health.d/apache.conf' ['18ee1c6197a4381b1c1631ef6129824f']='apps_groups.conf' + ['1c12b678ab65f271a96da1bbd0a1ab1c']='health.d/softnet.conf' + ['1ea8e8ef1fa8a3a0fcdfba236f4cb195']='python.d/mysql.conf' + ['1f5545b3ff52b3eb75ee05401f67a9bc']='fping.conf' + ['1fa47f32ab52a22f8e7087cae85dd25e']='health.d/net.conf' + ['20be73f473e59bc7de1fe61d53466aba']='health.d/ram.conf' + ['21924a6ab8008d16ffac340f226ebad9']='python.d/nginx.conf' + ['22952dbf42647c583b005054b23b545f']='health.d/disks.conf' + ['22ceb822983134a7ca67343241f30341']='health.d/disks.conf' + ['2385e5d35b440619621c4af62492d91b']='health.d/disks.conf' + ['23ae815aefa221b1929f96752a1f7556']='health.d/squid.conf' + ['2472e49550326f7142e2c425ccbca005']='health.d/softnet.conf' + ['254de8ec49602bea2da3631676d7cfec']='health.d/cpu.conf' + ['2827de41cf34a91b7a8e4d8724f59668']='health.d/net.conf' + ['28df44a90e8ea4c6156314c03e88bf44']='health.d/softnet.conf' + ['297160ae7ee01a547ed14f857b4f2c8d']='health.d/memcached.conf' + ['29f97e10b92333790fbe0d2a3617b736']='health_alarm_notify.conf' + ['2a0794fd43eadf30a51805bc9ba2c64d']='python.d/hddtemp.conf' + ['2ad55a5d1e885cf142849a78d4b00401']='health.d/net.conf' + ['2bbbebf52f84fd27fbefecd2a8a8076f']='health.d/memcached.conf' + ['2d1d7498c72f4245cf32902c2b7e71e0']='health.d/entropy.conf' ['2f4a85fedecce1bf425fa1039f6b021e']='apps_groups.conf' + ['2fa8fb929fd597f2ab97b6efc540a043']='health_alarm_notify.conf' + ['312b4b8e2805e19cf9be554b319567d6']='health.d/softnet.conf' + ['318bb45755726a25120bb33413d4b582']='health.d/net.conf' + ['325617412a628e3bc776e3fbb777a2a6']='health.d/redis.conf' + ['32fde0057c790964f2c743cb3c9aad29']='health.d/nginx.conf' + ['33b135e28aeaef2b8224ba69a0fde245']='health.d/cpu.conf' + ['3634d5eddc46fb0d50cf47f370670c2c']='health.d/redis.conf' + ['367d1463e520eb9dc89223bab161c6d1']='python.d/postgres.conf' + ['36fdd55665cf10b0db164c2a0cca5e57']='health.d/qos.conf' + ['373160658e7d5f1a129de397b9347365']='health.d/entropy.conf' + ['373c1276dc9e65884ff2b26e1f08afe7']='health.d/named.conf' + ['3848172053221b95279ba9bf789cd4e0']='health.d/apache.conf' + ['3866efafd38e161136428d0f818cac43']='health.d/net.conf' + ['38d1bf04fe9901481dd6febcc0404a86']='python.d.conf' + ['39571e9fad9b759200c5d5b2ee13feb4']='python.d/redis.conf' + ['39f9422b0f0c3eec11a31aff79d89514']='health.d/retroshare.conf' ['3af522d65b50a5e447607ffb28c81ff5']='apps_groups.conf' ['3b1bfa40a4ff6a200bb2fc00bc51a664']='apps_groups.conf' + ['3bc2776623889744a98178bad6fb3b79']='health.d/disks.conf' + ['3bc65e997ab59b9de390fdf63d77f5e1']='python.d/postgres.conf' + ['3ca696189911fb38a0319ddd71e9a395']='python.d/phpfpm.conf' + ['3cc6255457d4cba881ae0554ae5d9190']='health.d/squid.conf' + ['3f170e3343cd784983b019163393f5af']='health.d/nginx.conf' + ['3fc45cc18e884c22482524dff6d27833']='python.d/hddtemp.conf' + ['4063a01bffb43b0423425d1ba3004967']='health.d/tcp_resets.conf' + ['421d5dc6c2fce22d0816b6e6363bea57']='python.d/hddtemp.conf' + ['42ad0e70b1365b6e7244cc305dbaa529']='health_alarm_notify.conf' + ['42bf1c7c64ed77038a0aa094d792a9e2']='python.d/mysql.conf' + ['43ebb7f224c3b232d8ad044d7e9508b6']='health.d/net.conf' + ['450667c552ab7a7d8d4a2c214fdacca5']='health.d/entropy.conf' + ['45a77ac36ba9f1898144b902de17204b']='health.d/memcached.conf' + ['46798cda21e1a5faa769abf4e5d27c48']='health.d/disks.conf' + ['46ef6c1b638e40a7dfd62defdc5f99a3']='health.d/retroshare.conf' + ['47180421d580baeaedf8c0ef3d647fb5']='python.d/hddtemp.conf' + ['48195c5c8c0476a49b714b4c76bdb570']='python.d/squid.conf' ['4a448831776de8acf2e0bdc4cc994cb4']='apps_groups.conf' - ['5bf51bb24fb41db9b1e448bd060d3f8c']='apps_groups.conf' - ['636d032928ea0f4741eab264fb49c099']='apps_groups.conf' - ['647361e99b5f4e0d73470c569bb9461c']='apps_groups.conf' - ['6a47af861ad3dd112124c37fbf09672b']='apps_groups.conf' - ['79a37756869d9b4629285922572d6b9b']='apps_groups.conf' - ['99c1617448abbdc493976ab9bda5ce02']='apps_groups.conf' - ['9c0185ceff15415bc59b2ce2c1f04367']='apps_groups.conf' - ['a0ee8f351f213c0e8af9eb7a4a09cb95']='apps_groups.conf' - ['a7cceeafb1e6ef1ead503ab65f687902']='apps_groups.conf' - ['a837986be634fd7648bcdf939019424a']='apps_groups.conf' - ['a9cd91675467c5426f5b51c47602c889']='apps_groups.conf' - ['acaa6731a272f6d251afb357e99b518f']='apps_groups.conf' - ['bb51112d01ff20053196a57632df8962']='apps_groups.conf' - ['d9036091e2232fc2b8bfa8c7484dea28']='apps_groups.conf' - ['d9258e671d0d0b6498af1ce16ef030d2']='apps_groups.conf' - ['ebd0612ccc5807524ebb2b647e3e56c9']='apps_groups.conf' - ['f2f1b8656f5011e965ac45b818cf668d']='apps_groups.conf' - ['fdea185e0e52b459b48852aa37f20e0f']='apps_groups.conf' + ['4b775fb31342f1478b3773d041a72911']='python.d.conf' ['4ccb06fff1ce06dc5bc80e0a9f568f6e']='charts.d.conf' + ['4d13684cadfa90e73ab465409bf7263b']='health.d/mysql.conf' ['4e995acb0d6fd77403a2a9dca984b55b']='charts.d.conf' + ['4f6a5b47a13f5912cc89e9286701dd08']='health.d/redis.conf' + ['4f6f4d39c19d7d954f769d3f9d3b4da5']='health.d/memcached.conf' + ['4fdf72784296326e0b46cb526a5d77a1']='python.d.conf' + ['501eb2484b459b410b3f792c2dbaa955']='health.d/swap.conf' + ['508771d8e4611a058991a1bc11039dea']='health.d/disks.conf' + ['5271cf9fc0fd10915a9759add70f7d78']='health.d/swap.conf' + ['5278ebbae19c60db600f0a119cb3664e']='python.d/apache.conf' + ['52d4131cf9df84e2550b1a5d899ec61d']='health.d/swap.conf' + ['53160707fdc6ce46c195b1b55bb0bcb1']='health.d/swap.conf' ['535e5113b07b0fc6f3abd59546c276f6']='charts.d.conf' - ['7cf6402b51e5070f2be3ad6fe059ff89']='charts.d.conf' - ['a02d14124b19c635c1426cee2e98bac5']='charts.d.conf' - ['ca026d7c779f0a7cb7787713c5be5c47']='charts.d.conf' - ['1f5545b3ff52b3eb75ee05401f67a9bc']='fping.conf' - ['29f97e10b92333790fbe0d2a3617b736']='health_alarm_notify.conf' - ['2fa8fb929fd597f2ab97b6efc540a043']='health_alarm_notify.conf' - ['42ad0e70b1365b6e7244cc305dbaa529']='health_alarm_notify.conf' - ['6a18f61a595c0d48c3363bcc0dbfa6b9']='health_alarm_notify.conf' - ['707a63f53f4b32e01d134ae90ba94aad']='health_alarm_notify.conf' - ['8810140ce9c09af1d18b9602c4003904']='health_alarm_notify.conf' - ['8fd472a854b0996327e8ed3562161182']='health_alarm_notify.conf' - ['a55133f1b0be0a4255057849dd451b09']='health_alarm_notify.conf' - ['a89c516a1144435a88decf25509318ac']='health_alarm_notify.conf' - ['b07eebc6f58d19721ac069171b911d2a']='health_alarm_notify.conf' - ['b68706bb8101ef85192db92f865a5d80']='health_alarm_notify.conf' - ['c080e006f544c949baca33cc24a9c126']='health_alarm_notify.conf' - ['ce2e8768964a936f58c4c2144aee8a01']='health_alarm_notify.conf' - ['e3023092e3b2bbb5351e0fe6682f4fe9']='health_alarm_notify.conf' - ['f8dade4484f1b6a48655388502df7d5a']='health_alarm_notify.conf' - ['fd3164e6e8cb6726706267eae49aa082']='health_alarm_notify.conf' - ['fe478efe2e721724edb1fe2ef1addf93']='health_alarm_notify.conf' - ['ff1b3d8ae8b2149c711d8da9b7a9c4bd']='health_alarm_notify.conf' - ['074df527cc70b5f38c0714f08f20e57c']='health.d/apache.conf' - ['174c21a6ce5de97bda83d502aa47a9f8']='health.d/apache.conf' - ['3848172053221b95279ba9bf789cd4e0']='health.d/apache.conf' - ['80266bddd3df374923c750a6de91d120']='health.d/apache.conf' - ['842b1ad5b89bfa5f421d9c5b72e001a4']='health.d/apache.conf' - ['a6d5ce2572bf7a1dce9e545fcd29273e']='health.d/apache.conf' - ['084ee72d64760f2641b0720e79c922f3']='health.d/cpu.conf' - ['254de8ec49602bea2da3631676d7cfec']='health.d/cpu.conf' - ['5eb670b6fe39da5fec2523d910b0dd1e']='health.d/cpu.conf' - ['623771eecb3c277fc728b5304793f93b']='health.d/cpu.conf' - ['7596ae54d46ce199ac599429ef753caf']='health.d/cpu.conf' - ['8d0552371a7c9725a04196fa560813d1']='health.d/cpu.conf' - ['c3296c08260bcd556e74711c820817be']='health.d/cpu.conf' - ['fdd11640ba626cc2064c2fe3ea3eee4c']='health.d/cpu.conf' - ['02fa10fa85ab88e9723998de48d1aca0']='health.d/disks.conf' - ['0433d98a19d3b08e6f13884e46d39b47']='health.d/disks.conf' - ['22ceb822983134a7ca67343241f30341']='health.d/disks.conf' - ['2385e5d35b440619621c4af62492d91b']='health.d/disks.conf' - ['3bc2776623889744a98178bad6fb3b79']='health.d/disks.conf' - ['46798cda21e1a5faa769abf4e5d27c48']='health.d/disks.conf' + ['5379cdc26d7725e2b0d688d785816cef']='python.d/mysql.conf' + ['54614490a14e1a4b7b3d9fecb6b4cfa5']='python.d/exim.conf' + ['55608bdd908a3806df1468f6ee318b2b']='health.d/qos.conf' + ['565f11c38ae6bd5cc9d3c2adb542bc1b']='health.d/softnet.conf' + ['5664a814f9351b55da76edd472169a73']='health_alarm_notify.conf' ['573398335c0c71c075fa57f702bce287']='health.d/disks.conf' + ['5829812db29598db5857c9f433e96fef']='python.d/apache.conf' + ['58e835b7176865ec5a6f59f7aba832bf']='health.d/named.conf' + ['5b917d894bb6a755d59264e9d48e9d56']='fping.conf' + ['5bf51bb24fb41db9b1e448bd060d3f8c']='apps_groups.conf' ['5da15d6e17a15213a720749045e5d419']='health.d/disks.conf' - ['7aa209fa287c95b3ca04c23681b40770']='health.d/disks.conf' - ['80d242d619eb7e91cebfdbf58d79b0f8']='health.d/disks.conf' - ['8989b5e2f4ef9cd278ef58be0fae4074']='health.d/disks.conf' - ['8a1b95d375992d7b11330a0ac46f369c']='health.d/disks.conf' - ['8dc0bd0a70b5117454bd5f5b98f91c2c']='health.d/disks.conf' - ['a4407787e4beb23a701a8a614dca461d']='health.d/disks.conf' - ['a5114d5b0d3816dba75024b9444f4b40']='health.d/disks.conf' - ['a8167dafeac0b66696a1d9b08e815cda']='health.d/disks.conf' - ['afdae4646c755ff2d117527fbf761c8e']='health.d/disks.conf' - ['cb60badf376d246ad8ec9d3f524db430']='health.d/disks.conf' - ['dd8254ef74509a3e38cb2838e30f7e63']='health.d/disks.conf' - ['e8ec8046c7007af6ca3e8c51e62c99f8']='health.d/disks.conf' - ['057d12aaff0467e64529e839a258806b']='health.d/entropy.conf' - ['2d1d7498c72f4245cf32902c2b7e71e0']='health.d/entropy.conf' - ['373160658e7d5f1a129de397b9347365']='health.d/entropy.conf' - ['450667c552ab7a7d8d4a2c214fdacca5']='health.d/entropy.conf' + ['5e6fd588ef6934cf04ddb5e662aa02ea']='health.d/postgres.conf' + ['5eb670b6fe39da5fec2523d910b0dd1e']='health.d/cpu.conf' ['5ff1bcaa58695754e2f6980bfe19f579']='health.d/entropy.conf' - ['a8feb36776005bf419c90278787a1be8']='health.d/entropy.conf' - ['b636e5e603f9d93e52c7577ac8c6bf0c']='health.d/entropy.conf' - ['d8dc489e32f7114c6298fce94e86a8ef']='health.d/entropy.conf' - ['def883f35986c9d25de63b1a8e7d0f46']='health.d/entropy.conf' - ['e449e5582279742496550df14b6fca95']='health.d/entropy.conf' - ['297160ae7ee01a547ed14f857b4f2c8d']='health.d/memcached.conf' - ['2bbbebf52f84fd27fbefecd2a8a8076f']='health.d/memcached.conf' - ['45a77ac36ba9f1898144b902de17204b']='health.d/memcached.conf' ['621f10b257a11add5ff5aff41e9662e3']='health.d/memcached.conf' - ['7e5fc1644aa7a54f9dbb1bd102521b09']='health.d/memcached.conf' - ['9c981c75bdf4b1637f7113e7e45eb2bf']='health.d/memcached.conf' - ['a731b7b164f42717c1c9a778ee637ff3']='health.d/memcached.conf' - ['b81b8f331161b0d48e03f6fbf6b6d062']='health.d/memcached.conf' - ['c1a7e634b5b8aad523a0d115a93379cd']='health.d/memcached.conf' - ['dd7764507804a2296bfd091a58ad4ad7']='health.d/memcached.conf' - ['f8c30f22df92765e2c0fab3c8174e2fc']='health.d/memcached.conf' - ['09264cec953ae1c4c2985e6446abb386']='health.d/mysql.conf' - ['4d13684cadfa90e73ab465409bf7263b']='health.d/mysql.conf' - ['97eee7a30e6419df4537242e9d4a719d']='health.d/mysql.conf' - ['373c1276dc9e65884ff2b26e1f08afe7']='health.d/named.conf' - ['58e835b7176865ec5a6f59f7aba832bf']='health.d/named.conf' + ['623771eecb3c277fc728b5304793f93b']='health.d/cpu.conf' + ['636d032928ea0f4741eab264fb49c099']='apps_groups.conf' + ['6398ef37a15cb6a0bc921f58948d2b39']='health.d/softnet.conf' + ['64070d856ab1b47a18ec871e49bbc13b']='python.d/squid.conf' + ['647361e99b5f4e0d73470c569bb9461c']='apps_groups.conf' + ['64ac37868097a462e5ee6905c350267e']='python.d/postgres.conf' + ['64c48f9726ab987baec9c617a9fef7a6']='health.d/nginx.conf' + ['6608c6546b3c6bde084fc1d34b1163c1']='health.d/retroshare.conf' ['669ebef43ee341f6889d382e86d0e200']='health.d/named.conf' + ['66dfe138058ca26a31a118007eb31f35']='health.d/nginx.conf' + ['6a18f61a595c0d48c3363bcc0dbfa6b9']='health_alarm_notify.conf' + ['6a47af861ad3dd112124c37fbf09672b']='apps_groups.conf' ['6b39de5d85db45115db236347a6896d4']='health.d/named.conf' - ['846ce94bfeeb90c0dc6a89e8d25f1a68']='health.d/named.conf' - ['ddda2bb1c88be03b637d3285406f7910']='health.d/named.conf' - ['0529b679d3c0e7e6332753c7f6484731']='health.d/net.conf' - ['0856124b1eecf01681b4fdf4e21efb3f']='health.d/net.conf' - ['2827de41cf34a91b7a8e4d8724f59668']='health.d/net.conf' - ['2ad55a5d1e885cf142849a78d4b00401']='health.d/net.conf' - ['318bb45755726a25120bb33413d4b582']='health.d/net.conf' - ['43ebb7f224c3b232d8ad044d7e9508b6']='health.d/net.conf' - ['cb178b15427274d7def5b14bc4c09441']='health.d/net.conf' - ['d11711b3647bc2bdd0292dd7deebbeb1']='health.d/net.conf' - ['dc9c2a66778623a759706c14c3d91983']='health.d/net.conf' - ['de02f899a61f21b86adb646940f0bcae']='health.d/net.conf' - ['feb8bcf828aa2529a7ee4a140feeb12d']='health.d/net.conf' - ['32fde0057c790964f2c743cb3c9aad29']='health.d/nginx.conf' - ['3f170e3343cd784983b019163393f5af']='health.d/nginx.conf' - ['64c48f9726ab987baec9c617a9fef7a6']='health.d/nginx.conf' + ['6b917300747e7e8314844237e2462261']='python.d/apache_cache.conf' + ['6bf0de6e3b251b765b10a71d8c5c319d']='python.d/apache.conf' + ['6cba40e32a7e98a98c31a209913839cc']='python.d/nginx_log.conf' + ['70105b1744a8e13f49083d7f1981aea2']='python.d/ipfs.conf' + ['707a63f53f4b32e01d134ae90ba94aad']='health_alarm_notify.conf' + ['707a63f53f4b32e01d134ae90ba94aad']='health_email_recipients.conf' + ['73125ae64d5c6e9361944cd9bd14844e']='python.d/exim.conf' + ['731a1fcfe9b2da1b9d685056a59541b8']='python.d/hddtemp.conf' + ['73a8e10dfe4183aca751e9e2a80dabe3']='node.d.conf' + ['749fe31362969d75f1ea66d15231d98d']='python.d/retroshare.conf' + ['7596ae54d46ce199ac599429ef753caf']='health.d/cpu.conf' + ['777f4da70f461ef675bde07fb3644312']='python.d/redis.conf' + ['7830066c46a7e5f9682b8d3f4566b4e5']='python.d/cpufreq.conf' + ['78bb08809dffcb62e9bc493840f9c039']='python.d/squid.conf' + ['78e0065738394f5bf15023f41d66ed4b']='python.d/squid.conf' + ['79a37756869d9b4629285922572d6b9b']='apps_groups.conf' + ['7a21ccc76be2968ce5d0b52ec1166788']='python.d.conf' ['7a985528cc9176564640001aa73e3492']='health.d/nginx.conf' - ['81255035f6d53534938085df72cdef23']='health.d/nginx.conf' - ['eb5168f0b516bc982aac45e59da6e52e']='health.d/nginx.conf' - ['36fdd55665cf10b0db164c2a0cca5e57']='health.d/qos.conf' - ['55608bdd908a3806df1468f6ee318b2b']='health.d/qos.conf' + ['7aa209fa287c95b3ca04c23681b40770']='health.d/disks.conf' + ['7cf6402b51e5070f2be3ad6fe059ff89']='charts.d.conf' + ['7d8bd884ec26cb35d16c4fc05f969799']='python.d/squid.conf' + ['7deb236ec68a512b9bdd18e6a51d76f7']='python.d/mysql.conf' + ['7e5fc1644aa7a54f9dbb1bd102521b09']='health.d/memcached.conf' + ['80266bddd3df374923c750a6de91d120']='health.d/apache.conf' + ['80d242d619eb7e91cebfdbf58d79b0f8']='health.d/disks.conf' ['80f109ff293ac94222bf3959432751bd']='health.d/qos.conf' - ['b735732fbe993d8191d6b3317082efa2']='health.d/qos.conf' - ['eb748d6fb69d11b0d29c5794657e206c']='health.d/qos.conf' - ['20be73f473e59bc7de1fe61d53466aba']='health.d/ram.conf' + ['81255035f6d53534938085df72cdef23']='health.d/nginx.conf' + ['8214bb8f4b005aa4691fcd38f7331e8f']='health.d/swap.conf' + ['837480f77ba1a85677a36747fbc2cd2e']='python.d/sensors.conf' + ['842b1ad5b89bfa5f421d9c5b72e001a4']='health.d/apache.conf' + ['845023f9b4a526aa0e6493756dbe6034']='health.d/squid.conf' + ['846ce94bfeeb90c0dc6a89e8d25f1a68']='health.d/named.conf' + ['8810140ce9c09af1d18b9602c4003904']='health_alarm_notify.conf' + ['88f77865f75c9fb61c97d700bd4561ee']='python.d/mysql.conf' + ['8989b5e2f4ef9cd278ef58be0fae4074']='health.d/disks.conf' + ['899bcb0b3f4375b0a1280296be930201']='health.d/named.conf' + ['8a1b95d375992d7b11330a0ac46f369c']='health.d/disks.conf' + ['8c1d41e2c88aeca78bc319ed74c8748c']='python.d/phpfpm.conf' + ['8d0552371a7c9725a04196fa560813d1']='health.d/cpu.conf' + ['8dc0bd0a70b5117454bd5f5b98f91c2c']='health.d/disks.conf' + ['8fd472a854b0996327e8ed3562161182']='health_alarm_notify.conf' ['919911d13901d60a7580f5dfd7fc87bb']='health.d/ram.conf' - ['a09714b5942cf25a89ec3da1dbc18063']='health.d/ram.conf' - ['b7d769ce86a7aebba01315da5c0799e6']='health.d/ram.conf' - ['cd08e5534c94bf1f2cd28396c76b8bbc']='health.d/ram.conf' - ['d55bdb83b9ff606852f6a97c1430258c']='health.d/ram.conf' - ['325617412a628e3bc776e3fbb777a2a6']='health.d/redis.conf' - ['3634d5eddc46fb0d50cf47f370670c2c']='health.d/redis.conf' - ['4f6a5b47a13f5912cc89e9286701dd08']='health.d/redis.conf' + ['91c757ef6be3abdb86906d9dbb9c217a']='fping.conf' + ['91cf3b3d42cac969b8b3fd4f531ecfb3']='python.d/squid.conf' + ['97eee7a30e6419df4537242e9d4a719d']='health.d/mysql.conf' + ['97f337eb96213f3ede05e522e3743a6c']='python.d/memcached.conf' + ['99a3de85d1e7826ed64a5f8576712e5d']='python.d.conf' ['99b6030ce25c8fee4598179c0f95fb0b']='health.d/redis.conf' - ['a4be524cc5b7192878c292a17c767c28']='health.d/redis.conf' - ['39f9422b0f0c3eec11a31aff79d89514']='health.d/retroshare.conf' - ['46ef6c1b638e40a7dfd62defdc5f99a3']='health.d/retroshare.conf' - ['6608c6546b3c6bde084fc1d34b1163c1']='health.d/retroshare.conf' - ['1c12b678ab65f271a96da1bbd0a1ab1c']='health.d/softnet.conf' - ['2472e49550326f7142e2c425ccbca005']='health.d/softnet.conf' - ['28df44a90e8ea4c6156314c03e88bf44']='health.d/softnet.conf' - ['312b4b8e2805e19cf9be554b319567d6']='health.d/softnet.conf' - ['565f11c38ae6bd5cc9d3c2adb542bc1b']='health.d/softnet.conf' - ['6398ef37a15cb6a0bc921f58948d2b39']='health.d/softnet.conf' + ['99c1617448abbdc493976ab9bda5ce02']='apps_groups.conf' + ['9c0185ceff15415bc59b2ce2c1f04367']='apps_groups.conf' + ['9c981c75bdf4b1637f7113e7e45eb2bf']='health.d/memcached.conf' + ['9e0553ebdc21b64295873fc104cfa79d']='python.d.conf' + ['a02d14124b19c635c1426cee2e98bac5']='charts.d.conf' + ['a09714b5942cf25a89ec3da1dbc18063']='health.d/ram.conf' + ['a0ee8f351f213c0e8af9eb7a4a09cb95']='apps_groups.conf' + ['a2944a309f8ce1a3195451856478d6ae']='python.d.conf' ['a305b400378d6492efd15f9940c2779b']='health.d/softnet.conf' - ['e734c5951a8764d4d9de046dd7cf7407']='health.d/softnet.conf' - ['23ae815aefa221b1929f96752a1f7556']='health.d/squid.conf' - ['3cc6255457d4cba881ae0554ae5d9190']='health.d/squid.conf' - ['845023f9b4a526aa0e6493756dbe6034']='health.d/squid.conf' - ['a4a8660728c6afcb528cc6b378897d6b']='health.d/squid.conf' - ['d162b7465a56151312e60151c1d74fba']='health.d/squid.conf' - ['ef9916ea144878a9f37cbb6b1b29da10']='health.d/squid.conf' - ['043f0a35dde85837fabeb85b990a41c1']='health.d/swap.conf' - ['52d4131cf9df84e2550b1a5d899ec61d']='health.d/swap.conf' - ['53160707fdc6ce46c195b1b55bb0bcb1']='health.d/swap.conf' - ['8214bb8f4b005aa4691fcd38f7331e8f']='health.d/swap.conf' + ['a4407787e4beb23a701a8a614dca461d']='health.d/disks.conf' ['a44899a5795bed2863c1d11aa3e85586']='health.d/swap.conf' + ['a4a8660728c6afcb528cc6b378897d6b']='health.d/squid.conf' + ['a4be524cc5b7192878c292a17c767c28']='health.d/redis.conf' + ['a5114d5b0d3816dba75024b9444f4b40']='health.d/disks.conf' + ['a55133f1b0be0a4255057849dd451b09']='health_alarm_notify.conf' + ['a6d5ce2572bf7a1dce9e545fcd29273e']='health.d/apache.conf' + ['a71d9082410200bf92e823675d78121c']='python.d/retroshare.conf' + ['a731b7b164f42717c1c9a778ee637ff3']='health.d/memcached.conf' ['a7320c6f26191b9599ec3bc4be007a93']='health.d/swap.conf' - ['c9b792755de59d842ba95f8c315d94c8']='health.d/swap.conf' - ['ca08a9b18d38ae0a0f5081a7cdc96863']='health.d/swap.conf' - ['da29d2ab1ab7b8fda189960c840e5144']='health.d/swap.conf' - ['4063a01bffb43b0423425d1ba3004967']='health.d/tcp_resets.conf' - ['b3fc4749b132e55ac0d3a0f92859237e']='health.d/tcp_resets.conf' - ['707a63f53f4b32e01d134ae90ba94aad']='health_email_recipients.conf' ['a752e51d923e15add4a11fa8f3be935a']='health_email_recipients.conf' - ['73a8e10dfe4183aca751e9e2a80dabe3']='node.d.conf' - ['6b917300747e7e8314844237e2462261']='python.d/apache_cache.conf' - ['e0e96cc47ed61d6492416be5236cd4d3']='python.d/apache_cache.conf' - ['5278ebbae19c60db600f0a119cb3664e']='python.d/apache.conf' - ['5829812db29598db5857c9f433e96fef']='python.d/apache.conf' - ['6bf0de6e3b251b765b10a71d8c5c319d']='python.d/apache.conf' - ['13141998a5d71308d9c119834c27bfd3']='python.d.conf' - ['38d1bf04fe9901481dd6febcc0404a86']='python.d.conf' - ['4b775fb31342f1478b3773d041a72911']='python.d.conf' - ['4fdf72784296326e0b46cb526a5d77a1']='python.d.conf' - ['7a21ccc76be2968ce5d0b52ec1166788']='python.d.conf' - ['99a3de85d1e7826ed64a5f8576712e5d']='python.d.conf' - ['9e0553ebdc21b64295873fc104cfa79d']='python.d.conf' - ['a2944a309f8ce1a3195451856478d6ae']='python.d.conf' + ['a7cceeafb1e6ef1ead503ab65f687902']='apps_groups.conf' + ['a8167dafeac0b66696a1d9b08e815cda']='health.d/disks.conf' + ['a837986be634fd7648bcdf939019424a']='apps_groups.conf' + ['a89c516a1144435a88decf25509318ac']='health_alarm_notify.conf' + ['a8bb4e1d0525f59692778ad8f675a77a']='python.d/example.conf' + ['a8feb36776005bf419c90278787a1be8']='health.d/entropy.conf' + ['a94af1c808aafdf00537d85ff2197ec8']='python.d/exim.conf' + ['a9cd91675467c5426f5b51c47602c889']='apps_groups.conf' + ['aa4bee249bfc0c4a88ac8c2ffb97aa0d']='health.d/squid.conf' + ['acaa6731a272f6d251afb357e99b518f']='apps_groups.conf' + ['ade389c1b6efe0cff47c33e662731f0a']='python.d/squid.conf' + ['ae5ac0a3521e50aa6f6eda2a330b4075']='python.d/example.conf' ['af44cc53aa2bc5cc8935667119567522']='python.d.conf' + ['afdae4646c755ff2d117527fbf761c8e']='health.d/disks.conf' + ['b07eebc6f58d19721ac069171b911d2a']='health_alarm_notify.conf' + ['b0f0a0ac415e4b1a82187b80d211e83b']='python.d/mysql.conf' ['b27f10a38a95edbbec20f44a4728b7c4']='python.d.conf' ['b32164929eda7449a9677044e11151bf']='python.d.conf' + ['b3fc4749b132e55ac0d3a0f92859237e']='health.d/tcp_resets.conf' + ['b5b5a8d6d991fb1cef8d80afa23ba114']='python.d/cpufreq.conf' + ['b636e5e603f9d93e52c7577ac8c6bf0c']='health.d/entropy.conf' + ['b68706bb8101ef85192db92f865a5d80']='health_alarm_notify.conf' + ['b735732fbe993d8191d6b3317082efa2']='health.d/qos.conf' + ['b7d769ce86a7aebba01315da5c0799e6']='health.d/ram.conf' + ['b81b8f331161b0d48e03f6fbf6b6d062']='health.d/memcached.conf' + ['b846ca1f99fa6a65303b58186f47d7a4']='python.d/squid.conf' ['b8969be5b3ceb4a99477937119bd4323']='python.d.conf' + ['b8b87574fd496a66ede884c5336493bd']='python.d/phpfpm.conf' + ['b915126262d08aa9da81de539a58a3fb']='python.d/redis.conf' + ['bb51112d01ff20053196a57632df8962']='apps_groups.conf' ['bba2f3886587f137ea08a6e63dd3d376']='python.d.conf' - ['d55be5bb5e108da1e7645da007c53cd4']='python.d.conf' - ['f82924563e41d99cdae5431f0af69155']='python.d.conf' - ['7830066c46a7e5f9682b8d3f4566b4e5']='python.d/cpufreq.conf' - ['b5b5a8d6d991fb1cef8d80afa23ba114']='python.d/cpufreq.conf' - ['dc0d2b96378f290eec3fcf98b89ad824']='python.d/cpufreq.conf' - ['e40947d22f7ed5359f12fc89e3512963']='python.d/dovecot.conf' - ['a8bb4e1d0525f59692778ad8f675a77a']='python.d/example.conf' - ['ae5ac0a3521e50aa6f6eda2a330b4075']='python.d/example.conf' - ['e5f32f54d6d6728f21f9ac26f37d6573']='python.d/example.conf' - ['15e32114994b92be7853b88091e7c6fb']='python.d/exim.conf' - ['54614490a14e1a4b7b3d9fecb6b4cfa5']='python.d/exim.conf' - ['73125ae64d5c6e9361944cd9bd14844e']='python.d/exim.conf' - ['a94af1c808aafdf00537d85ff2197ec8']='python.d/exim.conf' - ['2a0794fd43eadf30a51805bc9ba2c64d']='python.d/hddtemp.conf' - ['3fc45cc18e884c22482524dff6d27833']='python.d/hddtemp.conf' - ['421d5dc6c2fce22d0816b6e6363bea57']='python.d/hddtemp.conf' - ['47180421d580baeaedf8c0ef3d647fb5']='python.d/hddtemp.conf' - ['731a1fcfe9b2da1b9d685056a59541b8']='python.d/hddtemp.conf' - ['d74dc63fbe631dab9a2ff1b0f5d71719']='python.d/hddtemp.conf' - ['0e59bc11d0a869ea0247c04c08c8d72e']='python.d/ipfs.conf' - ['70105b1744a8e13f49083d7f1981aea2']='python.d/ipfs.conf' - ['97f337eb96213f3ede05e522e3743a6c']='python.d/memcached.conf' - ['1ea8e8ef1fa8a3a0fcdfba236f4cb195']='python.d/mysql.conf' - ['42bf1c7c64ed77038a0aa094d792a9e2']='python.d/mysql.conf' - ['5379cdc26d7725e2b0d688d785816cef']='python.d/mysql.conf' - ['7deb236ec68a512b9bdd18e6a51d76f7']='python.d/mysql.conf' - ['88f77865f75c9fb61c97d700bd4561ee']='python.d/mysql.conf' - ['b0f0a0ac415e4b1a82187b80d211e83b']='python.d/mysql.conf' - ['df381f3a7ca9fb2b4b43ae7cb7a4c492']='python.d/mysql.conf' - ['061c45b0e34170d357e47883166ecf40']='python.d/nginx.conf' - ['08042325ab27256b938575deafee8ecf']='python.d/nginx.conf' - ['21924a6ab8008d16ffac340f226ebad9']='python.d/nginx.conf' + ['bda5517ea01640cfdfa0a27549619d6a']='health.d/memcached.conf' + ['c080e006f544c949baca33cc24a9c126']='health_alarm_notify.conf' + ['c1a7e634b5b8aad523a0d115a93379cd']='health.d/memcached.conf' + ['c3296c08260bcd556e74711c820817be']='health.d/cpu.conf' ['c61948101e0e6846679682794ee48c5b']='python.d/nginx.conf' - ['ce3b65eac6c472b21905f7f72104f4c9']='python.d/nginx.conf' - ['6cba40e32a7e98a98c31a209913839cc']='python.d/nginx_log.conf' - ['3ca696189911fb38a0319ddd71e9a395']='python.d/phpfpm.conf' - ['8c1d41e2c88aeca78bc319ed74c8748c']='python.d/phpfpm.conf' - ['b8b87574fd496a66ede884c5336493bd']='python.d/phpfpm.conf' ['c88fb430f35b7d8f08775d84debffbd2']='python.d/phpfpm.conf' - ['d2b2ad30e277a69d8713e620dabc18bc']='python.d/phpfpm.conf' - ['d7e0bd12d4a60a761dcab3531a841711']='python.d/phpfpm.conf' - ['142a5b693d34b0308bb0b8aec71fad79']='python.d/postfix.conf' + ['c9b792755de59d842ba95f8c315d94c8']='health.d/swap.conf' + ['ca026d7c779f0a7cb7787713c5be5c47']='charts.d.conf' + ['ca08a9b18d38ae0a0f5081a7cdc96863']='health.d/swap.conf' ['ca249db7a0637d55abb938d969f9b486']='python.d/postfix.conf' - ['0cd4e1fb57497e4d4c2451a9e58f724d']='python.d/redis.conf' - ['39571e9fad9b759200c5d5b2ee13feb4']='python.d/redis.conf' - ['777f4da70f461ef675bde07fb3644312']='python.d/redis.conf' - ['b915126262d08aa9da81de539a58a3fb']='python.d/redis.conf' - ['749fe31362969d75f1ea66d15231d98d']='python.d/retroshare.conf' - ['a71d9082410200bf92e823675d78121c']='python.d/retroshare.conf' - ['837480f77ba1a85677a36747fbc2cd2e']='python.d/sensors.conf' + ['cb178b15427274d7def5b14bc4c09441']='health.d/net.conf' + ['cb60badf376d246ad8ec9d3f524db430']='health.d/disks.conf' + ['ccde91d209aeb02c4a6be0e43a8d92b3']='health.d/apache.conf' + ['cd08e5534c94bf1f2cd28396c76b8bbc']='health.d/ram.conf' + ['ce2e8768964a936f58c4c2144aee8a01']='health_alarm_notify.conf' + ['ce3b65eac6c472b21905f7f72104f4c9']='python.d/nginx.conf' ['cfecf298bdafaa7e0a3a263548e82132']='python.d/sensors.conf' - ['48195c5c8c0476a49b714b4c76bdb570']='python.d/squid.conf' - ['64070d856ab1b47a18ec871e49bbc13b']='python.d/squid.conf' - ['78bb08809dffcb62e9bc493840f9c039']='python.d/squid.conf' - ['78e0065738394f5bf15023f41d66ed4b']='python.d/squid.conf' - ['7d8bd884ec26cb35d16c4fc05f969799']='python.d/squid.conf' - ['91cf3b3d42cac969b8b3fd4f531ecfb3']='python.d/squid.conf' - ['ade389c1b6efe0cff47c33e662731f0a']='python.d/squid.conf' - ['b846ca1f99fa6a65303b58186f47d7a4']='python.d/squid.conf' + ['d11711b3647bc2bdd0292dd7deebbeb1']='health.d/net.conf' + ['d162b7465a56151312e60151c1d74fba']='health.d/squid.conf' + ['d1e79707cd9b51a14288e8dd40694fcc']='fping.conf' + ['d2b2ad30e277a69d8713e620dabc18bc']='python.d/phpfpm.conf' + ['d55bdb83b9ff606852f6a97c1430258c']='health.d/ram.conf' + ['d55be5bb5e108da1e7645da007c53cd4']='python.d.conf' + ['d5dab509d8792f795bece27de39dd476']='health.d/mysql.conf' + ['d74dc63fbe631dab9a2ff1b0f5d71719']='python.d/hddtemp.conf' + ['d7e0bd12d4a60a761dcab3531a841711']='python.d/phpfpm.conf' + ['d8dc489e32f7114c6298fce94e86a8ef']='health.d/entropy.conf' + ['d9036091e2232fc2b8bfa8c7484dea28']='apps_groups.conf' + ['d9258e671d0d0b6498af1ce16ef030d2']='apps_groups.conf' + ['da29d2ab1ab7b8fda189960c840e5144']='health.d/swap.conf' + ['dad303c5cca7a69345811a01a74f5892']='health.d/net.conf' + ['dc0d2b96378f290eec3fcf98b89ad824']='python.d/cpufreq.conf' + ['dc9c2a66778623a759706c14c3d91983']='health.d/net.conf' + ['dd7764507804a2296bfd091a58ad4ad7']='health.d/memcached.conf' + ['dd8254ef74509a3e38cb2838e30f7e63']='health.d/disks.conf' + ['ddda2bb1c88be03b637d3285406f7910']='health.d/named.conf' + ['dddc4f93e6187fe4220eb6bf5e20f095']='health.d/ram.conf' + ['de02f899a61f21b86adb646940f0bcae']='health.d/net.conf' + ['def883f35986c9d25de63b1a8e7d0f46']='health.d/entropy.conf' + ['df381f3a7ca9fb2b4b43ae7cb7a4c492']='python.d/mysql.conf' + ['e0e96cc47ed61d6492416be5236cd4d3']='python.d/apache_cache.conf' + ['e2f3388c06726154c10ec22bad5bc7ec']='fping.conf' + ['e3023092e3b2bbb5351e0fe6682f4fe9']='health_alarm_notify.conf' ['e3e5bc57335c489f01b8559f5c70e112']='python.d/squid.conf' - ['0388b873d0d7e47c19005b7241db77d8']='python.d/tomcat.conf' + ['e40947d22f7ed5359f12fc89e3512963']='python.d/dovecot.conf' + ['e449e5582279742496550df14b6fca95']='health.d/entropy.conf' + ['e5f32f54d6d6728f21f9ac26f37d6573']='python.d/example.conf' + ['e734c5951a8764d4d9de046dd7cf7407']='health.d/softnet.conf' + ['e8ec8046c7007af6ca3e8c51e62c99f8']='health.d/disks.conf' + ['eb5168f0b516bc982aac45e59da6e52e']='health.d/nginx.conf' + ['eb748d6fb69d11b0d29c5794657e206c']='health.d/qos.conf' + ['ebd0612ccc5807524ebb2b647e3e56c9']='apps_groups.conf' + ['ee5343881744e6a97e6ee5cdd329cfb8']='health.d/retroshare.conf' + ['ef9916ea144878a9f37cbb6b1b29da10']='health.d/squid.conf' + ['f2f1b8656f5011e965ac45b818cf668d']='apps_groups.conf' + ['f6c6656f900ff52d159dca12d624016a']='python.d/postgres.conf' ['f7a99e94231beda85c6254912d8d31c1']='python.d/tomcat.conf' + ['f82924563e41d99cdae5431f0af69155']='python.d.conf' + ['f8c30f22df92765e2c0fab3c8174e2fc']='health.d/memcached.conf' + ['f8dade4484f1b6a48655388502df7d5a']='health_alarm_notify.conf' + ['fa4396513b358d6ec6a7f5bfb08439b8']='health.d/net.conf' + ['fd3164e6e8cb6726706267eae49aa082']='health_alarm_notify.conf' + ['fdd11640ba626cc2064c2fe3ea3eee4c']='health.d/cpu.conf' + ['fdea185e0e52b459b48852aa37f20e0f']='apps_groups.conf' + ['fe478efe2e721724edb1fe2ef1addf93']='health_alarm_notify.conf' + ['feb8bcf828aa2529a7ee4a140feeb12d']='health.d/net.conf' + ['ff1b3d8ae8b2149c711d8da9b7a9c4bd']='health_alarm_notify.conf' ) diff --git a/contrib/debian/netdata.postinst.in b/contrib/debian/netdata.postinst.in index 97341774..c7618a59 100644 --- a/contrib/debian/netdata.postinst.in +++ b/contrib/debian/netdata.postinst.in @@ -21,8 +21,6 @@ case "$1" in dpkg-statoverride --update --add root netdata 0755 /var/lib/netdata/www fi - fi - if ! dpkg-statoverride --list /var/cache/netdata >/dev/null 2>&1; then dpkg-statoverride --update --add netdata netdata 0755 /var/cache/netdata fi diff --git a/netdata-installer.sh b/netdata-installer.sh index 930243c4..502eb8c8 100755 --- a/netdata-installer.sh +++ b/netdata-installer.sh @@ -139,7 +139,7 @@ get_git_config_signatures() { echo >configs.signatures.tmp - for x in $(find conf.d -name \*.conf | sort) + for x in $(find conf.d -name \*.conf) do x="${x/conf.d\//}" echo "${x}" @@ -147,7 +147,7 @@ get_git_config_signatures() { do git checkout ${c} "conf.d/${x}" || continue s="$(cat "conf.d/${x}" | md5sum | cut -d ' ' -f 1)" - echo >>configs.signatures.tmp "${x}:${s}" + echo >>configs.signatures.tmp "${s}:${x}" echo " ${s}" done git checkout HEAD "conf.d/${x}" || break @@ -159,7 +159,7 @@ get_git_config_signatures() { { echo "declare -A configs_signatures=(" IFS=":" - while read file md5 + while read md5 file do echo " ['${md5}']='${file}'" done @@ -561,7 +561,7 @@ if [ ${UID} -eq 0 ] if [ $? -ne 0 ] then echo >&2 "Adding netdata user account ..." - run useradd -r -g netdata -c netdata -s $(which nologin || echo '/bin/false') -d / netdata + run useradd -r -g netdata -c netdata -s $(which nologin 2>/dev/null || command -v nologin 2>/dev/null || echo '/bin/false') -d / netdata fi getent group docker > /dev/null @@ -752,7 +752,9 @@ stop_netdata_on_pid() { } stop_all_netdata() { - local p + local p myns ns + + myns="$(readlink /proc/self/ns/pid 2>/dev/null)" echo >&2 "Stopping a (possibly) running netdata..." @@ -761,27 +763,93 @@ stop_all_netdata() { $(cat /var/run/netdata/netdata.pid 2>/dev/null) \ $(pidof netdata 2>/dev/null) do - stop_netdata_on_pid ${p} + ns="$(readlink /proc/${p}/ns/pid 2>/dev/null)" + + if [ -z "${myns}" -o -z "${ns}" -o "${myns}" = "${ns}" ] + then + stop_netdata_on_pid ${p} + fi done } # ----------------------------------------------------------------------------- -# check netdata for systemd +# check for systemd issystemd() { + local pids p myns ns systemctl + # if the directory /etc/systemd/system does not exit, it is not systemd [ ! -d /etc/systemd/system ] && return 1 + # if there is no systemctl command, it is not systemd + systemctl=$(which systemctl 2>/dev/null || command -v systemctl 2>/dev/null) + [ -z "${systemctl}" -o ! -x "${systemctl}" ] && return 1 + # if pid 1 is systemd, it is systemd [ "$(basename $(readlink /proc/1/exe) 2>/dev/null)" = "systemd" ] && return 0 - # if systemd is running, it is systemd - pidof systemd >/dev/null 2>&1 && return 0 + # if systemd is not running, it is not systemd + pids=$(pidof systemd 2>/dev/null) + [ -z "${pids}" ] && return 1 + + # check if the running systemd processes are not in our namespace + myns="$(readlink /proc/self/ns/pid 2>/dev/null)" + for p in ${pids} + do + ns="$(readlink /proc/${p}/ns/pid 2>/dev/null)" + + # if pid of systemd is in our namespace, it is systemd + [ ! -z "${myns}" && "${myns}" = "${ns}" ] && return 0 + done # else, it is not systemd return 1 } +installed_init_d=0 +install_non_systemd_init() { + [ "${UID}" != 0 ] && return 1 + + local key="unknown" + if [ -f /etc/os-release ] + then + source /etc/os-release || return 1 + key="${ID}-${VERSION_ID}" + + elif [ -f /etc/centos-release ] + then + key=$( /dev/null if [ $? -eq 0 ] then diff --git a/netdata.spec.in b/netdata.spec.in index e5677510..4012fb7f 100644 --- a/netdata.spec.in +++ b/netdata.spec.in @@ -157,6 +157,10 @@ rm -rf $RPM_BUILD_ROOT %config(noreplace) %{_sysconfdir}/%{name}/python.d/*.conf %config(noreplace) %{_sysconfdir}/logrotate.d/%{name} +# node.js config files are JSON (which do not support comments) +# so, we only supply markdown files +%{_sysconfdir}/%{name}/node.d/*.md + %{_libexecdir}/%{name} %{_sbindir}/%{name} diff --git a/plugins.d/alarm-notify.sh b/plugins.d/alarm-notify.sh index a2e3f8e7..01362575 100755 --- a/plugins.d/alarm-notify.sh +++ b/plugins.d/alarm-notify.sh @@ -169,6 +169,7 @@ sendmail= # enable / disable features SEND_SLACK="YES" SEND_PUSHOVER="YES" +SEND_TWILIO="YES" SEND_TELEGRAM="YES" SEND_EMAIL="YES" SEND_PUSHBULLET="YES" @@ -188,6 +189,13 @@ PUSHBULLET_ACCESS_TOKEN= DEFAULT_RECIPIENT_PUSHBULLET= declare -A role_recipients_pushbullet=() +# twilio configs +TWILIO_ACCOUNT_SID= +TWILIO_ACCOUNT_TOKEN= +TWILIO_NUMBER= +DEFAULT_RECIPIENT_TWILIO= +declare -A role_recipients_twilio=() + # telegram configs TELEGRAM_BOT_TOKEN= DEFAULT_RECIPIENT_TELEGRAM= @@ -250,6 +258,7 @@ filter_recipient_by_criticality() { declare -A arr_slack=() declare -A arr_pushover=() declare -A arr_pushbullet=() +declare -A arr_twilio=() declare -A arr_telegram=() declare -A arr_email=() @@ -285,6 +294,14 @@ do [ "${r}" != "disabled" ] && filter_recipient_by_criticality pushbullet "${r}" && arr_pushbullet[${r/|*/}]="1" done + # twilio + a="${role_recipients_twilio[${x}]}" + [ -z "${a}" ] && a="${DEFAULT_RECIPIENT_TWILIO}" + for r in ${a//,/ } + do + [ "${r}" != "disabled" ] && filter_recipient_by_criticality twilio "${r}" && arr_twilio[${r/|*/}]="1" + done + # telegram a="${role_recipients_telegram[${x}]}" [ -z "${a}" ] && a="${DEFAULT_RECIPIENT_TELEGRAM}" @@ -314,6 +331,10 @@ to_pushover="${!arr_pushover[*]}" to_pushbullet="${!arr_pushbullet[*]}" [ -z "${to_pushbullet}" ] && SEND_PUSHBULLET="NO" +# build the list of twilio recipients (phone numbers) +to_twilio="${!arr_twilio[*]}" +[ -z "${to_twilio}" ] && SEND_TWILIO="NO" + # check array of telegram recipients (chat ids) to_telegram="${!arr_telegram[*]}" [ -z "${to_telegram}" ] && SEND_TELEGRAM="NO" @@ -340,10 +361,13 @@ done # check pushbullet [ -z "${DEFAULT_RECIPIENT_PUSHBULLET}" ] && SEND_PUSHBULLET="NO" +# check twilio +[ -z "${DEFAULT_RECIPIENT_TWILIO}" ] && SEND_TWILIO="NO" + # check telegram [ -z "${TELEGRAM_BOT_TOKEN}" ] && SEND_TELEGRAM="NO" -if [ \( "${SEND_PUSHOVER}" = "YES" -o "${SEND_SLACK}" = "YES" -o "${SEND_TELEGRAM}" = "YES" -o "${SEND_PUSHBULLET}" = "YES" \) -a -z "${curl}" ] +if [ \( "${SEND_PUSHOVER}" = "YES" -o "${SEND_SLACK}" = "YES" -o "${SEND_TWILIO}" = "YES" -o "${SEND_TELEGRAM}" = "YES" -o "${SEND_PUSHBULLET}" = "YES" \) -a -z "${curl}" ] then curl="$(which curl 2>/dev/null || command -v curl 2>/dev/null)" if [ -z "${curl}" ] @@ -352,6 +376,7 @@ if [ \( "${SEND_PUSHOVER}" = "YES" -o "${SEND_SLACK}" = "YES" -o "${SEND_TELEGRA SEND_PUSHBULLET="NO" SEND_TELEGRAM="NO" SEND_SLACK="NO" + SEND_TWILIO="NO" fi fi @@ -362,7 +387,7 @@ if [ "${SEND_EMAIL}" = "YES" -a -z "${sendmail}" ] 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_PUSHBULLET}" != "YES" ] +if [ "${SEND_EMAIL}" != "YES" -a "${SEND_PUSHOVER}" != "YES" -a "${SEND_TELEGRAM}" != "YES" -a "${SEND_SLACK}" != "YES" -a "${SEND_TWILIO}" != "YES" -a "${SEND_PUSHBULLET}" != "YES" ] then fatal "All notification methods are disabled. Not sending notification to '${role}' for '${name}' = '${value}' of chart '${chart}' for status '${status}'." fi @@ -567,6 +592,38 @@ EOF return 1 } +# ----------------------------------------------------------------------------- +# twilio sender + +send_twilio() { + local accountsid="${1}" accounttoken="${2}" twilionumber="${3}" recipients="${4}" title="${5}" message="${6}" httpcode sent=0 user + if [ "${SEND_TWILIO}" = "YES" -a ! -z "${accountsid}" -a ! -z "${accounttoken}" -a ! -z "${twilionumber}" -a ! -z "${recipients}" -a ! -z "${message}" -a ! -z "${title}" ] + then + #https://www.twilio.com/packages/labs/code/bash/twilio-sms + for user in ${recipients} + do + httpcode=$(${curl} -X POST --write-out %{http_code} --silent --output /dev/null \ + --data-urlencode "From=${twilionumber}" \ + --data-urlencode "To=${user}" \ + --data-urlencode "Body=${title} ${message}" \ + -u "${accountsid}:${accounttoken}" \ + "https://api.twilio.com/2010-04-01/Accounts/${accountsid}/Messages.json") + + if [ "${httpcode}" == "201" ] + then + info "sent Twilio SMS for: ${host} ${chart}.${name} is ${status} to '${user}'" + sent=$((sent + 1)) + else + error "failed to send Twilio 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 @@ -795,6 +852,17 @@ The source of this alarm is line ${src}" SENT_PUSHBULLET=$? +# ----------------------------------------------------------------------------- +# send the twilio SMS + +send_twilio "${TWILIO_ACCOUNT_SID}" "${TWILIO_ACCOUNT_TOKEN}" "${TWILIO_NUMBER}" "${to_twilio}" "${host} ${status_message} - ${name//_/ } - ${chart}" "${alarm} +Severity: ${severity} +Chart: ${chart} +Family: ${family} +${info}" + +SENT_TWILIO=$? + # ----------------------------------------------------------------------------- # send the telegram.org message @@ -905,7 +973,7 @@ SENT_EMAIL=$? # let netdata know # we did send something -[ ${SENT_EMAIL} -eq 0 -o ${SENT_PUSHOVER} -eq 0 -o ${SENT_TELEGRAM} -eq 0 -o ${SENT_SLACK} -eq 0 -o ${SENT_PUSHBULLET} -eq 0 ] && exit 0 +[ ${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 ] && exit 0 # we did not send anything exit 1 diff --git a/plugins.d/fping.plugin b/plugins.d/fping.plugin index 32e1b711..3a61ab33 100755 --- a/plugins.d/fping.plugin +++ b/plugins.d/fping.plugin @@ -5,26 +5,66 @@ # (C) 2016 Costa Tsaousis # GPL v3+ # -# This plugin requires a special version of fping. -# Get it from https://github.com/ktsaou/fping -# and build it, like this: -# -# cd /usr/src -# git clone https://github.com/ktsaou/fping.git fping-netdata.git -# cd fping-netdata.git -# ./autogen.sh -# ./configure --prefix=/usr/local -# make -# cp src/fping /usr/local/bin/ -# chown root:root /usr/local/bin/fping -# chmod 4755 /usr/local/bin/fping -# -# Then, create /etc/netdata/fping.conf -# and set the configuration options given below +# This plugin requires a latest version of fping. +# You can compile it from source, by running me with option: install export PATH="${PATH}:/sbin:/usr/sbin:/usr/local/sbin" export LC_ALL=C +if [ "${1}" = "install" ] + then + [ "${UID}" != 0 ] && echo >&2 "Please run me as root. This will install a single binary file: /usr/local/bin/fping." && exit 1 + + run() { + printf >&2 " > " + printf >&2 "%q " "${@}" + printf >&2 "\n" + "${@}" || exit 1 + } + + [ ! -d /usr/src ] && run mkdir -p /usr/src + [ ! -d /usr/local/bin ] && run mkdir -p /usr/local/bin + + run cd /usr/src + + if [ -d fping-ktsaou.git ] + then + run cd fping-ktsaou.git + run git pull + else + run git clone https://github.com/ktsaou/fping.git fping-ktsaou.git + run cd fping-ktsaou.git + fi + + run ./autogen.sh + run ./configure --prefix=/usr/local + run make clean + run make + if [ -f /usr/local/bin/fping ] + then + run mv -f /usr/local/bin/fping /usr/local/bin/fping.old + fi + run mv src/fping /usr/local/bin/fping + run chown root:root /usr/local/bin/fping + run chmod 4755 /usr/local/bin/fping + echo >&2 + echo >&2 "All done, you have a compatible fping now at /usr/local/bin/fping." + echo >&2 + + fping="$(which fping 2>/dev/null || command -v fping 2>/dev/null)" + if [ "${fping}" != "/usr/local/bin/fping" ] + then + echo >&2 "You have another fping installed at: ${fping}." + echo >&2 "Please set:" + echo >&2 + echo >&2 " fping=\"/usr/local/bin/fping\"" + echo >&2 + echo >&2 "at /etc/netdata/fping.conf" + echo >&2 + fi + exit 0 +fi + # ----------------------------------------------------------------------------- PROGRAM_NAME="$(basename "${0}")" @@ -79,18 +119,20 @@ NETDATA_CONFIG_DIR="${NETDATA_CONFIG_DIR-/etc/netdata}" # can be overwritten at /etc/netdata/fping.conf # the fping binary to use -# we need one that can output netdata friendly info -fping="$(which fping || command -v fping)" +# we need one that can output netdata friendly info (supporting: -N) +# if you have multiple versions, put here the full filename of the right one +fping="$( which fping 2>/dev/null || command -v fping 2>/dev/null )" # a space separated list of hosts to fping +# we suggest to put names here and the IPs of these names in /etc/hosts hosts="" # the time in milliseconds (1 sec = 1000 ms) -# to ping the hosts - by default 2 pings per iteration -ping_every="$((update_every * 1000 / 2))" +# to ping the hosts - by default 5 pings per host per iteration +ping_every="$((update_every * 1000 / 5))" -# how many retries to make if a host does not respond -retries=1 +# fping options +fping_opts="-R -b 56 -i 1 -r 0 -t 5000" # ----------------------------------------------------------------------------- # load the configuration file @@ -112,8 +154,14 @@ then fatal "command '${fping}' is not executable - cannot proceed." fi +if [ ${ping_every} -lt 20 ] + then + warning "ping every was set to ${ping_every} but 20 is the minimum for non-root users. Setting it to 20 ms." + ping_every=20 +fi + # the fping options we will use -options=( -N -l -R -Q ${update_every} -p ${ping_every} -r ${retries} ${hosts} ) +options=( -N -l -Q ${update_every} -p ${ping_every} ${fping_opts} ${hosts} ) # execute fping exec "${fping}" "${options[@]}" diff --git a/plugins.d/loopsleepms.sh.inc b/plugins.d/loopsleepms.sh.inc index 6de93043..4f2e0235 100644 --- a/plugins.d/loopsleepms.sh.inc +++ b/plugins.d/loopsleepms.sh.inc @@ -1,6 +1,6 @@ # no need for shebang - this file is included from other scripts -LOOPSLEEP_DATE="$(which date)" +LOOPSLEEP_DATE="$(which date 2>/dev/null || command -v date 2>/dev/null)" if [ -z "$LOOPSLEEP_DATE" ] then echo >&2 "$0: ERROR: Cannot find the command 'date' in the system path." diff --git a/plugins.d/python.d.plugin b/plugins.d/python.d.plugin index 5e81fb26..05d23b9a 100755 --- a/plugins.d/python.d.plugin +++ b/plugins.d/python.d.plugin @@ -28,6 +28,7 @@ sys.path.append(MODULES_DIR + "python_modules") PROGRAM = os.path.basename(__file__).replace(".plugin", "") DEBUG_FLAG = False +TRACE_FLAG = False OVERRIDE_UPDATE_EVERY = False # ----------------------------------------------------------------------------- @@ -292,8 +293,8 @@ class PythonCharts(object): if job.name is not None and len(job.name) != 0: prefix += "/" + job.name try: + msg.error("DISABLED:", prefix) self.jobs.remove(job) - msg.info("Disabled", prefix) except Exception as e: msg.debug("This shouldn't happen. NO " + prefix + " IN LIST:" + str(self.jobs) + " ERROR: " + str(e)) @@ -332,21 +333,21 @@ class PythonCharts(object): job = self.jobs[i] try: if not job.check(): - msg.error(job.chart_name, "check function failed.") + msg.error(job.chart_name, "check() failed - disabling job") self._stop(job) else: - msg.debug(job.chart_name, "check succeeded") + msg.info("CHECKED OK:", job.chart_name) i += 1 try: if job.override_name is not None: new_name = job.__module__ + '_' + job.override_name if new_name in overridden: - msg.error(job.override_name + " already exists. Stopping '" + job.name + "'") + msg.info("DROPPED:", job.name, ", job '" + job.override_name + "' is already served by another job.") self._stop(job) i -= 1 else: job.name = job.override_name - msg.debug(job.chart_name + " changing chart name to: '" + new_name + "'") + msg.info("RENAMED:", new_name, ", from " + job.chart_name) job.chart_name = new_name overridden.append(job.chart_name) except Exception: @@ -435,7 +436,7 @@ def parse_cmdline(directory, *commands): :param commands: list of str :return: dict """ - global DEBUG_FLAG + global DEBUG_FLAG, TRACE_FLAG global OVERRIDE_UPDATE_EVERY global BASE_CONFIG @@ -447,6 +448,8 @@ def parse_cmdline(directory, *commands): elif cmd == "debug" or cmd == "all": DEBUG_FLAG = True # redirect stderr to stdout? + elif cmd == "trace" or cmd == "all": + TRACE_FLAG = True elif os.path.isfile(directory + cmd + ".chart.py") or os.path.isfile(directory + cmd): #DEBUG_FLAG = True mods.append(cmd.replace(".chart.py", "")) @@ -470,14 +473,14 @@ def run(): """ Main program. """ - global DEBUG_FLAG, BASE_CONFIG + global DEBUG_FLAG, TRACE_FLAG, BASE_CONFIG # read configuration file disabled = [] configfile = CONFIG_DIR + "python.d.conf" msg.PROGRAM = PROGRAM msg.info("reading configuration file:", configfile) - log_counter = 200 + log_throttle = 200 log_interval = 3600 conf = read_config(configfile) @@ -488,23 +491,33 @@ def run(): msg.fatal('disabled in configuration file.\n') except (KeyError, TypeError): pass + try: for param in BASE_CONFIG: BASE_CONFIG[param] = conf[param] except (KeyError, TypeError): pass # use default update_every from NETDATA_UPDATE_EVERY + try: DEBUG_FLAG = conf['debug'] except (KeyError, TypeError): pass + try: - log_counter = conf['logs_per_interval'] + TRACE_FLAG = conf['trace'] except (KeyError, TypeError): pass + + try: + log_throttle = conf['logs_per_interval'] + except (KeyError, TypeError): + pass + try: log_interval = conf['log_interval'] except (KeyError, TypeError): pass + for k, v in conf.items(): if k in ("update_every", "debug", "enabled"): continue @@ -514,8 +527,11 @@ def run(): # parse passed command line arguments modules = parse_cmdline(MODULES_DIR, *sys.argv) msg.DEBUG_FLAG = DEBUG_FLAG - msg.LOG_COUNTER = log_counter + msg.TRACE_FLAG = TRACE_FLAG + msg.LOG_THROTTLE = log_throttle msg.LOG_INTERVAL = log_interval + msg.LOG_COUNTER = 0 + msg.LOG_NEXT_CHECK = 0 msg.info("MODULES_DIR='" + MODULES_DIR + "', CONFIG_DIR='" + CONFIG_DIR + "', UPDATE_EVERY=" + str(BASE_CONFIG['update_every']) + diff --git a/plugins.d/tc-qos-helper.sh b/plugins.d/tc-qos-helper.sh index ffe995f7..7e1e92cf 100755 --- a/plugins.d/tc-qos-helper.sh +++ b/plugins.d/tc-qos-helper.sh @@ -58,7 +58,7 @@ plugins_dir="${NETDATA_PLUGINS_DIR}" [ -z "$plugins_dir" ] && plugins_dir="$( dirname $PROGRAM_FILE )" config_dir=${NETDATA_CONFIG_DIR-/etc/netdata} -tc="$(which tc 2>/dev/null)" +tc="$(which tc 2>/dev/null || command -v tc 2>/dev/null)" fireqos_run_dir="/var/run/fireqos" qos_get_class_names_every=120 qos_exit_every=3600 diff --git a/python.d/Makefile.am b/python.d/Makefile.am index d769e313..cc4a37bc 100644 --- a/python.d/Makefile.am +++ b/python.d/Makefile.am @@ -1,46 +1,47 @@ MAINTAINERCLEANFILES= $(srcdir)/Makefile.in CLEANFILES = \ - python-modules-installer.sh \ - $(NULL) + python-modules-installer.sh \ + $(NULL) include $(top_srcdir)/build/subst.inc SUFFIXES = .in dist_python_SCRIPTS = \ - apache.chart.py \ - apache_cache.chart.py \ - cpufreq.chart.py \ - dovecot.chart.py \ - example.chart.py \ - exim.chart.py \ - hddtemp.chart.py \ - ipfs.chart.py \ - memcached.chart.py \ - mysql.chart.py \ - nginx.chart.py \ - nginx_log.chart.py \ - phpfpm.chart.py \ - postfix.chart.py \ - redis.chart.py \ - retroshare.chart.py \ - sensors.chart.py \ - squid.chart.py \ - tomcat.chart.py \ - python-modules-installer.sh \ - $(NULL) + apache.chart.py \ + apache_cache.chart.py \ + cpufreq.chart.py \ + dovecot.chart.py \ + example.chart.py \ + exim.chart.py \ + hddtemp.chart.py \ + ipfs.chart.py \ + memcached.chart.py \ + mysql.chart.py \ + nginx.chart.py \ + nginx_log.chart.py \ + phpfpm.chart.py \ + postfix.chart.py \ + postgres.chart.py \ + redis.chart.py \ + retroshare.chart.py \ + sensors.chart.py \ + squid.chart.py \ + tomcat.chart.py \ + python-modules-installer.sh \ + $(NULL) dist_python_DATA = \ - README.md \ - $(NULL) + README.md \ + $(NULL) pythonmodulesdir=$(pythondir)/python_modules dist_pythonmodules_DATA = \ - python_modules/__init__.py \ - python_modules/base.py \ - python_modules/msg.py \ - python_modules/lm_sensors.py \ - $(NULL) + python_modules/__init__.py \ + python_modules/base.py \ + python_modules/msg.py \ + python_modules/lm_sensors.py \ + $(NULL) pythonyaml2dir=$(pythonmodulesdir)/pyyaml2 dist_pythonyaml2_DATA = \ diff --git a/python.d/dovecot.chart.py b/python.d/dovecot.chart.py index c05cb0c2..60e8bf6e 100644 --- a/python.d/dovecot.chart.py +++ b/python.d/dovecot.chart.py @@ -13,75 +13,75 @@ retries = 60 ORDER = ['sessions', 'logins', 'commands', 'faults', 'context_switches', - 'disk', 'bytes', 'syscalls', + 'io', 'net', 'syscalls', 'lookup', 'cache', 'auth', 'auth_cache'] CHARTS = { 'sessions': { - 'options': [None, "active sessions", 'number', 'IMAP', 'dovecot.sessions', 'line'], + 'options': [None, "Dovecot Active Sessions", 'number', 'sessions', 'dovecot.sessions', 'line'], 'lines': [ ['num_connected_sessions', 'active sessions', 'absolute'] ]}, 'logins': { - 'options': [None, "logins", 'number', 'IMAP', 'dovecot.logins', 'line'], + 'options': [None, "Dovecot Logins", 'number', 'logins', 'dovecot.logins', 'line'], 'lines': [ ['num_logins', 'logins', 'absolute'] ]}, 'commands': { - 'options': [None, "commands", "commands", 'IMAP', 'dovecot.commands', 'line'], + 'options': [None, "Dovecot Commands", "commands", 'commands', 'dovecot.commands', 'line'], 'lines': [ ['num_cmds', 'commands', 'absolute'] ]}, 'faults': { - 'options': [None, "faults", "faults", 'Faults', 'dovecot.faults', 'line'], + 'options': [None, "Dovecot Page Faults", "faults", 'page faults', 'dovecot.faults', 'line'], 'lines': [ ['min_faults', 'minor', 'absolute'], ['maj_faults', 'major', 'absolute'] ]}, 'context_switches': { - 'options': [None, "context switches", '', 'Context Switches', 'dovecot.context_switches', 'line'], + 'options': [None, "Dovecot Context Switches", '', 'context switches', 'dovecot.context_switches', 'line'], 'lines': [ ['vol_cs', 'volountary', 'absolute'], ['invol_cs', 'involountary', 'absolute'] ]}, - 'disk': { - 'options': [None, "disk", 'bytes/s', 'Reads and Writes', 'dovecot.disk', 'line'], + 'io': { + 'options': [None, "Dovecot Disk I/O", 'kilobytes/s', 'disk', 'dovecot.io', 'area'], 'lines': [ - ['disk_input', 'read', 'incremental'], - ['disk_output', 'write', 'incremental'] + ['disk_input', 'read', 'incremental', 1, 1024], + ['disk_output', 'write', 'incremental', -1, 1024] ]}, - 'bytes': { - 'options': [None, "bytes", 'bytes/s', 'Reads and Writes', 'dovecot.bytes', 'line'], + 'net': { + 'options': [None, "Dovecot Network Bandwidth", 'kilobits/s', 'network', 'dovecot.net', 'area'], 'lines': [ - ['read_bytes', 'read', 'incremental'], - ['write_bytes', 'write', 'incremental'] + ['read_bytes', 'read', 'incremental', 8, 1024], + ['write_bytes', 'write', 'incremental', -8, 1024] ]}, 'syscalls': { - 'options': [None, "number of syscalls", 'syscalls/s', 'Reads and Writes', 'dovecot.syscalls', 'line'], + 'options': [None, "Dovecot Number of SysCalls", 'syscalls/s', 'system', 'dovecot.syscalls', 'line'], 'lines': [ ['read_count', 'read', 'incremental'], ['write_count', 'write', 'incremental'] ]}, 'lookup': { - 'options': [None, "lookups", 'number/s', 'Mail', 'dovecot.lookup', 'line'], + 'options': [None, "Dovecot Lookups", 'number/s', 'lookups', 'dovecot.lookup', 'stacked'], 'lines': [ ['mail_lookup_path', 'path', 'incremental'], ['mail_lookup_attr', 'attr', 'incremental'] ]}, 'cache': { - 'options': [None, "hits", 'hits/s', 'Mail', 'dovecot.cache', 'line'], + 'options': [None, "Dovecot Cache Hits", 'hits/s', 'cache', 'dovecot.cache', 'line'], 'lines': [ ['mail_cache_hits', 'hits', 'incremental'] ]}, 'auth': { - 'options': [None, "attempts", 'attempts', 'Authentication', 'dovecot.auth', 'stacked'], + 'options': [None, "Dovecot Authentications", 'attempts', 'logins', 'dovecot.auth', 'stacked'], 'lines': [ - ['auth_successes', 'success', 'absolute'], - ['auth_failures', 'failure', 'absolute'] + ['auth_successes', 'ok', 'absolute'], + ['auth_failures', 'failed', 'absolute'] ]}, 'auth_cache': { - 'options': [None, "cache", 'number', 'Authentication', 'dovecot.auth_cache', 'stacked'], + 'options': [None, "Dovecot Authentication Cache", 'number', 'cache', 'dovecot.auth_cache', 'stacked'], 'lines': [ ['auth_cache_hits', 'hit', 'absolute'], ['auth_cache_misses', 'miss', 'absolute'] @@ -110,6 +110,10 @@ class Service(SocketService): except (ValueError, AttributeError): return None + if raw is None: + self.debug("dovecot returned no data") + return None + data = raw.split('\n')[:2] desc = data[0].split('\t') vals = data[1].split('\t') diff --git a/python.d/hddtemp.chart.py b/python.d/hddtemp.chart.py index 465bfdfa..2e7695db 100644 --- a/python.d/hddtemp.chart.py +++ b/python.d/hddtemp.chart.py @@ -23,7 +23,7 @@ ORDER = ['temperatures'] CHARTS = { 'temperatures': { - 'options': ['disks_temp', 'temperature', 'Celsius', 'Disks temperature', 'hddtemp.temperatures', 'line'], + 'options': ['disks_temp', 'Disks Temperatures', 'Celsius', 'temperatures', 'hddtemp.temperatures', 'line'], 'lines': [ # lines are created dynamically in `check()` method ]} diff --git a/python.d/memcached.chart.py b/python.d/memcached.chart.py index 5a1400c9..0d6807ba 100644 --- a/python.d/memcached.chart.py +++ b/python.d/memcached.chart.py @@ -20,89 +20,89 @@ retries = 60 # }} ORDER = ['cache', 'net', 'connections', 'items', 'evicted_reclaimed', - 'get', 'get_rate', 'set_rate', 'delete', 'cas', 'increment', 'decrement', 'touch', 'touch_rate'] + 'get', 'get_rate', 'set_rate', 'cas', 'delete', 'increment', 'decrement', 'touch', 'touch_rate'] CHARTS = { 'cache': { - 'options': [None, 'Cache Size', 'megabytes', 'Cache', 'memcached.cache', 'stacked'], + 'options': [None, 'Cache Size', 'megabytes', 'cache', 'memcached.cache', 'stacked'], 'lines': [ - ['used', 'used', 'absolute', 1, 1048576], - ['avail', 'available', 'absolute', 1, 1048576] + ['avail', 'available', 'absolute', 1, 1048576], + ['used', 'used', 'absolute', 1, 1048576] ]}, 'net': { - 'options': [None, 'Network', 'kilobytes/s', 'Network', 'memcached.net', 'line'], + 'options': [None, 'Network', 'kilobits/s', 'network', 'memcached.net', 'area'], 'lines': [ - ['bytes_read', 'read', 'incremental', 1, 1024], - ['bytes_written', 'written', 'incremental', 1, 1024] + ['bytes_read', 'in', 'incremental', 8, 1024], + ['bytes_written', 'out', 'incremental', -8, 1024] ]}, 'connections': { - 'options': [None, 'Connections', 'connections/s', 'Cluster', 'memcached.connections', 'line'], + 'options': [None, 'Connections', 'connections/s', 'connections', 'memcached.connections', 'line'], 'lines': [ ['curr_connections', 'current', 'incremental'], ['rejected_connections', 'rejected', 'incremental'], ['total_connections', 'total', 'incremental'] ]}, 'items': { - 'options': [None, 'Items', 'items', 'Cluster', 'memcached.items', 'line'], + 'options': [None, 'Items', 'items', 'items', 'memcached.items', 'line'], 'lines': [ ['curr_items', 'current', 'absolute'], ['total_items', 'total', 'absolute'] ]}, 'evicted_reclaimed': { - 'options': [None, 'Items', 'items', 'Evicted and Reclaimed', 'memcached.evicted_reclaimed', 'line'], + 'options': [None, 'Items', 'items', 'items', 'memcached.evicted_reclaimed', 'line'], 'lines': [ - ['evictions', 'evicted', 'absolute'], - ['reclaimed', 'reclaimed', 'absolute'] + ['reclaimed', 'reclaimed', 'absolute'], + ['evictions', 'evicted', 'absolute'] ]}, 'get': { - 'options': [None, 'Requests', 'requests', 'GET', 'memcached.get', 'stacked'], + 'options': [None, 'Requests', 'requests', 'get ops', 'memcached.get', 'stacked'], 'lines': [ ['get_hits', 'hits', 'percent-of-absolute-row'], ['get_misses', 'misses', 'percent-of-absolute-row'] ]}, 'get_rate': { - 'options': [None, 'Rate', 'requests/s', 'GET', 'memcached.get_rate', 'line'], + 'options': [None, 'Rate', 'requests/s', 'get ops', 'memcached.get_rate', 'line'], 'lines': [ ['cmd_get', 'rate', 'incremental'] ]}, 'set_rate': { - 'options': [None, 'Rate', 'requests/s', 'SET', 'memcached.set_rate', 'line'], + 'options': [None, 'Rate', 'requests/s', 'set ops', 'memcached.set_rate', 'line'], 'lines': [ ['cmd_set', 'rate', 'incremental'] ]}, 'delete': { - 'options': [None, 'Requests', 'requests', 'DELETE', 'memcached.delete', 'stacked'], + 'options': [None, 'Requests', 'requests', 'delete ops', 'memcached.delete', 'stacked'], 'lines': [ ['delete_hits', 'hits', 'percent-of-absolute-row'], ['delete_misses', 'misses', 'percent-of-absolute-row'], ]}, 'cas': { - 'options': [None, 'Requests', 'requests', 'CAS', 'memcached.cas', 'stacked'], + 'options': [None, 'Requests', 'requests', 'check and set ops', 'memcached.cas', 'stacked'], 'lines': [ ['cas_hits', 'hits', 'percent-of-absolute-row'], ['cas_misses', 'misses', 'percent-of-absolute-row'], ['cas_badval', 'bad value', 'percent-of-absolute-row'] ]}, 'increment': { - 'options': [None, 'Requests', 'requests', 'Increment', 'memcached.increment', 'stacked'], + 'options': [None, 'Requests', 'requests', 'increment ops', 'memcached.increment', 'stacked'], 'lines': [ ['incr_hits', 'hits', 'percent-of-absolute-row'], ['incr_misses', 'misses', 'percent-of-absolute-row'] ]}, 'decrement': { - 'options': [None, 'Requests', 'requests', 'Decrement', 'memcached.decrement', 'stacked'], + 'options': [None, 'Requests', 'requests', 'decrement ops', 'memcached.decrement', 'stacked'], 'lines': [ ['decr_hits', 'hits', 'percent-of-absolute-row'], ['decr_misses', 'misses', 'percent-of-absolute-row'] ]}, 'touch': { - 'options': [None, 'Requests', 'requests', 'Touch', 'memcached.touch', 'stacked'], + 'options': [None, 'Requests', 'requests', 'touch ops', 'memcached.touch', 'stacked'], 'lines': [ ['touch_hits', 'hits', 'percent-of-absolute-row'], ['touch_misses', 'misses', 'percent-of-absolute-row'] ]}, 'touch_rate': { - 'options': [None, 'Rate', 'requests/s', 'Touch', 'memcached.touch_rate', 'line'], + 'options': [None, 'Rate', 'requests/s', 'touch ops', 'memcached.touch_rate', 'line'], 'lines': [ ['cmd_touch', 'rate', 'incremental'] ]} @@ -125,44 +125,52 @@ class Service(SocketService): Get data from socket :return: dict """ + response = self._get_raw_data() + if response is None: + # error has already been logged + return None + + if response.startswith('ERROR'): + self.error("received ERROR") + return None + try: - raw = self._get_raw_data().split("\n") + parsed = response.split("\n") except AttributeError: - self.error("no data received") - return None - if raw[0].startswith('ERROR'): - self.error("Memcached returned ERROR") + self.error("response is invalid/empty") return None + + # split the response data = {} - for line in raw: + for line in parsed: if line.startswith('STAT'): try: t = line[5:].split(' ') - data[t[0]] = int(t[1]) + data[t[0]] = t[1] except (IndexError, ValueError): + self.debug("invalid line received: " + str(line)) pass - try: - data['hit_rate'] = int((data['keyspace_hits'] / float(data['keyspace_hits'] + data['keyspace_misses'])) * 100) - except: - data['hit_rate'] = 0 + if len(data) == 0: + self.error("received data doesn't have any records") + return None + + # custom calculations try: data['avail'] = int(data['limit_maxbytes']) - int(data['bytes']) - data['used'] = data['bytes'] + data['used'] = int(data['bytes']) except: pass - if len(data) == 0: - self.error("received data doesn't have needed records") - return None - else: - return data + return data def _check_raw_data(self, data): if data.endswith('END\r\n'): + self.debug("received full response from memcached") return True - else: - return False + + self.debug("waiting more data from memcached") + return False def check(self): """ diff --git a/python.d/nginx_log.chart.py b/python.d/nginx_log.chart.py index 95fb123d..16a9d957 100644 --- a/python.d/nginx_log.chart.py +++ b/python.d/nginx_log.chart.py @@ -54,7 +54,10 @@ class Service(LogService): regex = self.regex for line in raw: code = regex.search(line) - beginning = code.group(1)[0] + try: + beginning = code.group(1)[0] + except AttributeError: + continue if beginning == '2': data["2xx"] += 1 diff --git a/python.d/postgres.chart.py b/python.d/postgres.chart.py index bb1e268c..cd99bdfc 100644 --- a/python.d/postgres.chart.py +++ b/python.d/postgres.chart.py @@ -7,6 +7,7 @@ from copy import deepcopy import psycopg2 from psycopg2 import extensions +from psycopg2._psycopg import DatabaseError from psycopg2.extras import DictCursor from base import SimpleService @@ -113,74 +114,74 @@ ORDER = ['db_stat_transactions', 'db_stat_tuple_read', 'db_stat_tuple_returned', CHARTS = { 'db_stat_transactions': { - 'options': [None, ' Transactions', 'Count', ' database statistics', '.db_stat_transactions', 'line'], + 'options': [None, 'Transactions on db', 'transactions/s', 'db statistics', 'postgres.db_stat_transactions', 'line'], 'lines': [ - ['db_stat_xact_commit', 'Committed', 'absolute'], - ['db_stat_xact_rollback', 'Rolled Back', 'absolute'] + ['db_stat_xact_commit', 'committed', 'incremental'], + ['db_stat_xact_rollback', 'rolled back', 'incremental'] ]}, 'db_stat_connections': { - 'options': [None, ' Connections', 'Count', ' database statistics', '.db_stat_connections', 'line'], + 'options': [None, 'Current connections to db', 'count', 'db statistics', 'postgres.db_stat_connections', 'line'], 'lines': [ - ['db_stat_connections', 'Connections', 'absolute'] + ['db_stat_connections', 'connections', 'absolute'] ]}, 'db_stat_tuple_read': { - 'options': [None, ' Tuple read', 'Count', ' database statistics', '.db_stat_tuple_read', 'line'], + 'options': [None, 'Tuple reads from db', 'reads/s', 'db statistics', 'postgres.db_stat_tuple_read', 'line'], 'lines': [ - ['db_stat_blks_read', 'Disk', 'absolute'], - ['db_stat_blks_hit', 'Cache', 'absolute'] + ['db_stat_blks_read', 'disk', 'incremental'], + ['db_stat_blks_hit', 'cache', 'incremental'] ]}, 'db_stat_tuple_returned': { - 'options': [None, ' Tuple returned', 'Count', ' database statistics', '.db_stat_tuple_returned', 'line'], + 'options': [None, 'Tuples returned from db', 'tuples/s', 'db statistics', 'postgres.db_stat_tuple_returned', 'line'], 'lines': [ - ['db_stat_tup_returned', 'Sequential', 'absolute'], - ['db_stat_tup_fetched', 'Bitmap', 'absolute'] + ['db_stat_tup_returned', 'sequential', 'incremental'], + ['db_stat_tup_fetched', 'bitmap', 'incremental'] ]}, 'db_stat_tuple_write': { - 'options': [None, ' Tuple write', 'Count', ' database statistics', '.db_stat_tuple_write', 'line'], + 'options': [None, 'Tuples written to db', 'writes/s', 'db statistics', 'postgres.db_stat_tuple_write', 'line'], 'lines': [ - ['db_stat_tup_inserted', 'Inserted', 'absolute'], - ['db_stat_tup_updated', 'Updated', 'absolute'], - ['db_stat_tup_deleted', 'Deleted', 'absolute'], - ['db_stat_conflicts', 'Conflicts', 'absolute'] + ['db_stat_tup_inserted', 'inserted', 'incremental'], + ['db_stat_tup_updated', 'updated', 'incremental'], + ['db_stat_tup_deleted', 'deleted', 'incremental'], + ['db_stat_conflicts', 'conflicts', 'incremental'] ]}, 'backend_process': { - 'options': [None, 'Backend processes', 'Count', 'Backend processes', 'postgres.backend_process', 'line'], + 'options': [None, 'Current Backend Processes', 'processes', 'backend processes', 'postgres.backend_process', 'line'], 'lines': [ - ['backend_process_active', 'Active', 'absolute'], - ['backend_process_idle', 'Idle', 'absolute'] + ['backend_process_active', 'active', 'absolute'], + ['backend_process_idle', 'idle', 'absolute'] ]}, 'index_count': { - 'options': [None, 'Total index', 'Count', 'Index', 'postgres.index_count', 'line'], + 'options': [None, 'Total indexes', 'index', 'indexes', 'postgres.index_count', 'line'], 'lines': [ - ['index_count', 'Total index', 'absolute'] + ['index_count', 'total', 'absolute'] ]}, 'index_size': { - 'options': [None, 'Index size', 'MB', 'Index', 'postgres.index_size', 'line'], + 'options': [None, 'Indexes size', 'MB', 'indexes', 'postgres.index_size', 'line'], 'lines': [ - ['index_size', 'Size', 'absolute', 1, 1024 * 1024] + ['index_size', 'size', 'absolute', 1, 1024 * 1024] ]}, 'table_count': { - 'options': [None, 'Total table', 'Count', 'Table', 'postgres.table_count', 'line'], + 'options': [None, 'Total Tables', 'tables', 'tables', 'postgres.table_count', 'line'], 'lines': [ - ['table_count', 'Total table', 'absolute'] + ['table_count', 'total', 'absolute'] ]}, 'table_size': { - 'options': [None, 'Table size', 'MB', 'Table', 'postgres.table_size', 'line'], + 'options': [None, 'Tables size', 'MB', 'tables', 'postgres.table_size', 'line'], 'lines': [ - ['table_size', 'Size', 'absolute', 1, 1024 * 1024] + ['table_size', 'size', 'absolute', 1, 1024 * 1024] ]}, 'wal': { - 'options': [None, 'WAL stats', 'Files', 'WAL', 'postgres.wal', 'line'], + 'options': [None, 'Write-Ahead Logging Statistics', 'files/s', 'write ahead log', 'postgres.wal', 'line'], 'lines': [ - ['wal_total', 'Total', 'absolute'], - ['wal_ready', 'Ready', 'absolute'], - ['wal_done', 'Done', 'absolute'] + ['wal_total', 'total', 'incremental'], + ['wal_ready', 'ready', 'incremental'], + ['wal_done', 'done', 'incremental'] ]}, 'background_writer': { - 'options': [None, 'Checkpoints', 'Count', 'Background Writer', 'postgres.background_writer', 'line'], + 'options': [None, 'Checkpoints', 'writes/s', 'background writer', 'postgres.background_writer', 'line'], 'lines': [ - ['background_writer_scheduled', 'Scheduled', 'absolute'], - ['background_writer_requested', 'Requested', 'absolute'] + ['background_writer_scheduled', 'scheduled', 'incremental'], + ['background_writer_requested', 'requested', 'incremental'] ]} } @@ -196,7 +197,6 @@ class Service(SimpleService): self.connection = None self.is_superuser = False self.data = {} - self.old_data = {} self.databases = set() def _connect(self): @@ -222,6 +222,8 @@ class Service(SimpleService): self._create_definitions() return True + except DatabaseError: + return False except Exception as e: self.error(e) return False @@ -256,10 +258,10 @@ class Service(SimpleService): self.definitions[chart_name] = { 'options': [ name, - database_name + title, + title + ': ' + database_name, units, - database_name + family, - database_name + context, + 'db ' + database_name, + context, chart_type ] } @@ -272,22 +274,22 @@ class Service(SimpleService): def _add_database_lock_chart(self, database_name): chart_name = "{}_locks".format(database_name) if chart_name not in self.order: - self.order.insert(0, chart_name) + self.order.insert(-1, chart_name) self.definitions[chart_name] = dict( options= [ None, - database_name + ' locks', - 'Count', - database_name + ' database statistics', - database_name + '.locks', + 'Locks on db: ' + database_name, + 'locks', + 'db ' + database_name, + 'postgres.db_locks', 'line' ], lines=[] ) for lock_type in LOCK_TYPES: - lock_id = "{}_{}".format(database_name, lock_type.lower()) + lock_id = "{}_{}".format(database_name, lock_type) label = re.sub("([a-z])([A-Z])", "\g<1> \g<2>", lock_type) self.definitions[chart_name]['lines'].append([lock_id, label, 'absolute']) @@ -319,76 +321,62 @@ class Service(SimpleService): cursor.execute(DATABASE) for row in cursor: database_name = row.get('database_name') - self.add_derive_value('db_stat_xact_commit', prefix=database_name, value=int(row.get('xact_commit', 0))) - self.add_derive_value('db_stat_xact_rollback', prefix=database_name, value=int(row.get('xact_rollback', 0))) - self.add_derive_value('db_stat_blks_read', prefix=database_name, value=int(row.get('blks_read', 0))) - self.add_derive_value('db_stat_blks_hit', prefix=database_name, value=int(row.get('blks_hit', 0))) - self.add_derive_value('db_stat_tup_returned', prefix=database_name, value=int(row.get('tup_returned', 0))) - self.add_derive_value('db_stat_tup_fetched', prefix=database_name, value=int(row.get('tup_fetched', 0))) - self.add_derive_value('db_stat_tup_inserted', prefix=database_name, value=int(row.get('tup_inserted', 0))) - self.add_derive_value('db_stat_tup_updated', prefix=database_name, value=int(row.get('tup_updated', 0))) - self.add_derive_value('db_stat_tup_deleted', prefix=database_name, value=int(row.get('tup_deleted', 0))) - self.add_derive_value('db_stat_conflicts', prefix=database_name, value=int(row.get('conflicts', 0))) - conn_key = "{}_{}".format(database_name, 'db_stat_connections') - self.data[conn_key] = int(row.get('connections', 0)) + self.data["{}_{}".format(database_name, 'db_stat_xact_commit')] = int(row.get('xact_commit', 0)) + self.data["{}_{}".format(database_name, 'db_stat_xact_rollback')] = int(row.get('xact_rollback', 0)) + self.data["{}_{}".format(database_name, 'db_stat_blks_read')] = int(row.get('blks_read', 0)) + self.data["{}_{}".format(database_name, 'db_stat_blks_hit')] = int(row.get('blks_hit', 0)) + self.data["{}_{}".format(database_name, 'db_stat_tup_returned')] = int(row.get('tup_returned', 0)) + self.data["{}_{}".format(database_name, 'db_stat_tup_fetched')] = int(row.get('tup_fetched', 0)) + self.data["{}_{}".format(database_name, 'db_stat_tup_inserted')] = int(row.get('tup_inserted', 0)) + self.data["{}_{}".format(database_name, 'db_stat_tup_updated')] = int(row.get('tup_updated', 0)) + self.data["{}_{}".format(database_name, 'db_stat_tup_deleted')] = int(row.get('tup_deleted', 0)) + self.data["{}_{}".format(database_name, 'db_stat_conflicts')] = int(row.get('conflicts', 0)) + self.data["{}_{}".format(database_name, 'db_stat_connections')] = int(row.get('connections', 0)) def add_backend_stats(self, cursor): cursor.execute(BACKENDS) temp = cursor.fetchone() self.data['backend_process_active'] = int(temp.get('backends_active', 0)) - self.data['backend_process_idle'] = int(temp.get('backends_idle', 0)) + self.data['backend_process_idle'] = int(temp.get('backends_idle', 0)) def add_index_stats(self, cursor): cursor.execute(INDEX_STATS) temp = cursor.fetchone() - self.data['index_count'] = int(temp.get('indexes', 0)) - self.data['index_size'] = int(temp.get('size_indexes', 0)) + self.data['index_count'] = int(temp.get('indexes', 0)) + self.data['index_size'] = int(temp.get('size_indexes', 0)) def add_table_stats(self, cursor): cursor.execute(TABLE_STATS) temp = cursor.fetchone() - self.data['table_count'] = int(temp.get('relations', 0)) - self.data['table_size'] = int(temp.get('size_relations', 0)) + self.data['table_count'] = int(temp.get('relations', 0)) + self.data['table_size'] = int(temp.get('size_relations', 0)) def add_lock_stats(self, cursor): cursor.execute(DATABASE_LOCKS) - # First zero out all current lock values. + + # zero out all current lock values for database_name in self.databases: for lock_type in LOCK_TYPES: - lock_id = "{}_{}".format(database_name, lock_type.lower()) - self.data[lock_id] = 0 + self.data["{}_{}".format(database_name, lock_type)] = 0 - # Now populate those that have current locks + # populate those that have current locks for row in cursor: database_name, lock_type, lock_count = row - lock_id = "{}_{}".format(database_name, lock_type.lower()) - self.data[lock_id] = lock_count + self.data["{}_{}".format(database_name, lock_type)] = lock_count def add_wal_stats(self, cursor): cursor.execute(ARCHIVE) temp = cursor.fetchone() - self.add_derive_value('wal_total', int(temp.get('file_count', 0))) - self.add_derive_value('wal_ready', int(temp.get('ready_count', 0))) - self.add_derive_value('wal_done', int(temp.get('done_count', 0))) + self.data['wal_total'] = int(temp.get('file_count', 0)) + self.data['wal_ready'] = int(temp.get('ready_count', 0)) + self.data['wal_done'] = int(temp.get('done_count', 0)) def add_bgwriter_stats(self, cursor): cursor.execute(BGWRITER) temp = cursor.fetchone() - - self.add_derive_value('background_writer_scheduled', temp.get('checkpoints_timed', 0)) - self.add_derive_value('background_writer_requested', temp.get('checkpoints_requests', 0)) - - def add_derive_value(self, key, value, prefix=None): - if prefix: - key = "{}_{}".format(prefix, key) - if key not in self.old_data.keys(): - self.data[key] = 0 - else: - self.data[key] = value - self.old_data[key] - - self.old_data[key] = value - + self.data['background_writer_scheduled'] = temp.get('checkpoints_timed', 0) + self.data['background_writer_requested'] = temp.get('checkpoints_requests', 0) ''' def add_replication_stats(self, cursor): diff --git a/python.d/python_modules/base.py b/python.d/python_modules/base.py index cb04274b..201128f8 100644 --- a/python.d/python_modules/base.py +++ b/python.d/python_modules/base.py @@ -119,6 +119,7 @@ class SimpleService(threading.Thread): t_start = time.time() timetable = self.timetable chart_name = self.chart_name + # check if it is time to execute job update() function if timetable['next'] > t_start: self.debug(chart_name, "will be run in", str(int((timetable['next'] - t_start) * 1000)), "ms") @@ -129,20 +130,22 @@ class SimpleService(threading.Thread): "ready to run, after", str(int((t_start - timetable['last']) * 1000)), "ms (update_every:", str(timetable['freq'] * 1000), "ms, latency:", str(int((t_start - timetable['next']) * 1000)), "ms") + if self.__first_run: since_last = 0 + if not self.update(since_last): self.error("update function failed.") return False + t_end = time.time() self.timetable['next'] = t_end - (t_end % timetable['freq']) + timetable['freq'] + # draw performance graph run_time = str(int((t_end - t_start) * 1000)) # noinspection SqlNoDataSourceInspection print("BEGIN netdata.plugin_pythond_%s %s\nSET run_time = %s\nEND\n" % (self.chart_name, str(since_last), run_time)) - # sys.stdout.write("BEGIN netdata.plugin_pythond_%s %s\nSET run_time = %s\nEND\n" % - # (self.chart_name, str(since_last), run_time)) self.debug(chart_name, "updated in", str(run_time), "ms") self.timetable['last'] = t_start @@ -156,21 +159,24 @@ class SimpleService(threading.Thread): :return: None """ self.timetable['last'] = time.time() + self.debug("starting data collection - update frequency: " + str(self.update_every) + ", retries allowed: " + str(self.retries)) while True: # run forever, unless something is wrong try: status = self._run_once() except Exception as e: - self.error("Something wrong: ", str(e)) + self.alert("internal error - aborting data collection: " + str(e)) return + if status: # handle retries if update failed time.sleep(max (0, self.timetable['next'] - time.time())) self.retries_left = self.retries else: self.retries_left -= 1 if self.retries_left <= 0: - self.error("no more retries. Exiting") + self.alert("failed to collect data - no more retries allowed - aborting data collection") return else: + self.error("failed to collect data. " + str(self.retries_left) + " retries left.") time.sleep(self.timetable['freq']) # --- CHART --- @@ -318,6 +324,12 @@ class SimpleService(threading.Thread): """ msg.error(self.chart_name, *params) + def alert(self, *params): + """ + Show error message on stderr + """ + msg.alert(self.chart_name, *params) + def debug(self, *params): """ Show debug message on stderr @@ -345,10 +357,18 @@ class SimpleService(threading.Thread): :return: boolean """ self.debug("Module", str(self.__module__), "doesn't implement check() function. Using default.") - if self._get_data() is None or len(self._get_data()) == 0: + data = self._get_data() + + if data is None: + self.debug("failed to receive data during check().") return False - else: - return True + + if len(data) == 0: + self.debug("empty data during check().") + return False + + self.debug("successfully received data during check(): '" + str(data) + "'") + return True def create(self): """ @@ -357,6 +377,7 @@ class SimpleService(threading.Thread): """ data = self._get_data() if data is None: + self.debug("failed to receive data during create().") return False idx = 0 @@ -380,7 +401,7 @@ class SimpleService(threading.Thread): """ data = self._get_data() if data is None: - self.debug("_get_data() returned no data") + self.debug("failed to receive data during update().") return False updated = False @@ -506,8 +527,83 @@ class SocketService(SimpleService): self.unix_socket = None self.request = "" self.__socket_config = None + self.__empty_request = "".encode() SimpleService.__init__(self, configuration=configuration, name=name) + def _socketerror(self, message=None): + if self.unix_socket is not None: + self.error("unix socket '" + self.unix_socket + "':", message) + else: + if self.__socket_config is not None: + af, socktype, proto, canonname, sa = self.__socket_config + self.error("socket to '" + str(sa[0]) + "' port " + str(sa[1]) + ":", message) + else: + self.error("unknown socket:", message) + + def _connect2socket(self, res=None): + """ + Connect to a socket, passing the result of getaddrinfo() + :return: boolean + """ + if res is None: + res = self.__socket_config + if res is None: + self.error("Cannot create socket to 'None':") + return False + + af, socktype, proto, canonname, sa = res + try: + self.debug("creating socket to '" + str(sa[0]) + "', port " + str(sa[1])) + self._sock = socket.socket(af, socktype, proto) + except socket.error as e: + self.error("Failed to create socket to '" + str(sa[0]) + "', port " + str(sa[1]) + ":", str(e)) + self._sock = None + self.__socket_config = None + return False + + try: + self.debug("connecting socket to '" + str(sa[0]) + "', port " + str(sa[1])) + self._sock.connect(sa) + except socket.error as e: + self.error("Failed to connect to '" + str(sa[0]) + "', port " + str(sa[1]) + ":", str(e)) + self._disconnect() + self.__socket_config = None + return False + + self.debug("connected to '" + str(sa[0]) + "', port " + str(sa[1])) + self.__socket_config = res + return True + + def _connect2unixsocket(self): + """ + Connect to a unix socket, given its filename + :return: boolean + """ + if self.unix_socket is None: + self.error("cannot connect to unix socket 'None'") + return False + + try: + self.debug("attempting DGRAM unix socket '" + str(self.unix_socket) + "'") + self._sock = socket.socket(socket.AF_UNIX, socket.SOCK_DGRAM) + self._sock.connect(self.unix_socket) + self.debug("connected DGRAM unix socket '" + str(self.unix_socket) + "'") + return True + except socket.error as e: + self.debug("Failed to connect DGRAM unix socket '" + str(self.unix_socket) + "':", str(e)) + + try: + self.debug("attempting STREAM unix socket '" + str(self.unix_socket) + "'") + self._sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM) + self._sock.connect(self.unix_socket) + self.debug("connected STREAM unix socket '" + str(self.unix_socket) + "'") + return True + except socket.error as e: + self.debug("Failed to connect STREAM unix socket '" + str(self.unix_socket) + "':", str(e)) + self.error("Failed to connect to unix socket '" + str(self.unix_socket) + "':", str(e)) + self._sock = None + return False + def _connect(self): """ Recreate socket and connect to it since sockets cannot be reused after closing @@ -515,63 +611,38 @@ class SocketService(SimpleService): :return: """ try: - if self.unix_socket is None: - if self.__socket_config is None: - # establish ipv6 or ipv4 connection. - for res in socket.getaddrinfo(self.host, self.port, socket.AF_UNSPEC, socket.SOCK_STREAM): - try: - # noinspection SpellCheckingInspection - af, socktype, proto, canonname, sa = res - self._sock = socket.socket(af, socktype, proto) - except socket.error as e: - self.debug("Cannot create socket:", str(e)) - self._sock = None - continue - try: - self._sock.connect(sa) - except socket.error as e: - self.debug("Cannot connect to socket:", str(e)) - self._disconnect() - continue - self.__socket_config = res - break - else: - # connect to socket with previously established configuration - try: - af, socktype, proto, canonname, sa = self.__socket_config - self._sock = socket.socket(af, socktype, proto) - self._sock.connect(sa) - except socket.error as e: - self.debug("Cannot create or connect to socket:", str(e)) - self._disconnect() + if self.unix_socket is not None: + self._connect2unixsocket() + else: - # connect to unix socket - try: - self._sock = socket.socket(socket.AF_UNIX, socket.SOCK_DGRAM) - self._sock.connect(self.unix_socket) - except socket.error: - self._sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM) - self._sock.connect(self.unix_socket) + if self.__socket_config is not None: + self._connect2socket() + else: + for res in socket.getaddrinfo(self.host, self.port, socket.AF_UNSPEC, socket.SOCK_STREAM): + if self._connect2socket(res): break except Exception as e: - self.error(str(e), - "Cannot create socket with following configuration: host:", str(self.host), - "port:", str(self.port), - "socket:", str(self.unix_socket)) self._sock = None - self._sock.setblocking(0) + self.__socket_config = None + + if self._sock is not None: + self._sock.setblocking(0) + self._sock.settimeout(5) + self.debug("set socket timeout to: " + str(self._sock.gettimeout())) def _disconnect(self): """ Close socket connection :return: """ - try: - self._sock.shutdown(2) # 0 - read, 1 - write, 2 - all - self._sock.close() - except Exception: - pass - self._sock = None + if self._sock is not None: + try: + self.debug("closing socket") + self._sock.shutdown(2) # 0 - read, 1 - write, 2 - all + self._sock.close() + except Exception: + pass + self._sock = None def _send(self): """ @@ -579,15 +650,13 @@ class SocketService(SimpleService): :return: boolean """ # Send request if it is needed - if self.request != "".encode(): + if self.request != self.__empty_request: try: + self.debug("sending request:", str(self.request)) self._sock.send(self.request) except Exception as e: + self._socketerror("error sending request:" + str(e)) self._disconnect() - self.error(str(e), - "used configuration: host:", str(self.host), - "port:", str(self.port), - "socket:", str(self.unix_socket)) return False return True @@ -598,24 +667,28 @@ class SocketService(SimpleService): """ data = "" while True: + self.debug("receiving response") try: - ready_to_read, _, in_error = select.select([self._sock], [], [], 5) + buf = self._sock.recv(4096) except Exception as e: - self.debug("SELECT", str(e)) + self._socketerror("failed to receive response:" + str(e)) self._disconnect() break - if len(ready_to_read) > 0: - buf = self._sock.recv(4096) - if len(buf) == 0 or buf is None: # handle server disconnect - break - data += buf.decode(errors='ignore') - if self._check_raw_data(data): - break - else: - self.error("Socket timed out.") + + if buf is None or len(buf) == 0: # handle server disconnect + if data == "": + self._socketerror("unexpectedly disconnected") + else: + self.debug("server closed the connection") self._disconnect() break + self.debug("received data:", str(buf)) + data += buf.decode(errors='ignore') + if self._check_raw_data(data): + break + + self.debug("final response:", str(data)) return data def _get_raw_data(self): @@ -625,6 +698,8 @@ class SocketService(SimpleService): """ if self._sock is None: self._connect() + if self._sock is None: + return None # Send request if it is needed if not self._send(): @@ -654,6 +729,7 @@ class SocketService(SimpleService): self.name = "" else: self.name = str(self.name) + try: self.unix_socket = str(self.configuration['socket']) except (KeyError, TypeError): @@ -667,10 +743,12 @@ class SocketService(SimpleService): self.port = int(self.configuration['port']) except (KeyError, TypeError): self.debug("No port specified. Using: '" + str(self.port) + "'") + try: self.request = str(self.configuration['request']) except (KeyError, TypeError): self.debug("No request specified. Using: '" + str(self.request) + "'") + self.request = self.request.encode() def check(self): @@ -724,7 +802,7 @@ class LogService(SimpleService): try: self.log_path = str(self.configuration['path']) except (KeyError, TypeError): - self.error("No path to log specified. Using: '" + self.log_path + "'") + self.info("No path to log specified. Using: '" + self.log_path + "'") if os.access(self.log_path, os.R_OK): return True @@ -779,13 +857,14 @@ class ExecutableService(SimpleService): try: self.command = str(self.configuration['command']) except (KeyError, TypeError): - self.error("No command specified. Using: '" + self.command + "'") + self.info("No command specified. Using: '" + self.command + "'") command = self.command.split(' ') for arg in command[1:]: if any(st in arg for st in self.bad_substrings): self.error("Bad command argument:" + " ".join(self.command[1:])) return False + # test command and search for it in /usr/sbin or /sbin when failed base = command[0].split('/')[-1] if self._get_raw_data() is None: @@ -793,8 +872,10 @@ class ExecutableService(SimpleService): command[0] = prefix + base if os.path.isfile(command[0]): break + self.command = command if self._get_data() is None or len(self._get_data()) == 0: self.error("Command", self.command, "returned no data") return False + return True diff --git a/python.d/python_modules/msg.py b/python.d/python_modules/msg.py index 203751af..b835c940 100644 --- a/python.d/python_modules/msg.py +++ b/python.d/python_modules/msg.py @@ -1,14 +1,17 @@ # -*- coding: utf-8 -*- # Description: logging for netdata python.d modules +import traceback import sys from time import time, strftime DEBUG_FLAG = False +TRACE_FLAG = False PROGRAM = "" -LOG_COUNTER = 2 -LOG_INTERVAL = 5 -NEXT_CHECK = 0 +LOG_COUNTER = 0 +LOG_THROTTLE = 10000 # has to be too big during init +LOG_INTERVAL = 1 # has to be too low during init +LOG_NEXT_CHECK = 0 WRITE = sys.stderr.write FLUSH = sys.stderr.flush @@ -20,23 +23,39 @@ def log_msg(msg_type, *args): :param msg_type: str """ global LOG_COUNTER - if not DEBUG_FLAG: - LOG_COUNTER -= 1 + global LOG_THROTTLE + global LOG_INTERVAL + global LOG_NEXT_CHECK now = time() - if LOG_COUNTER >= 0: + + if not DEBUG_FLAG: + LOG_COUNTER += 1 + + # WRITE("COUNTER " + str(LOG_COUNTER) + " THROTTLE " + str(LOG_THROTTLE) + " INTERVAL " + str(LOG_INTERVAL) + " NOW " + str(now) + " NEXT " + str(LOG_NEXT_CHECK) + "\n") + + if LOG_COUNTER <= LOG_THROTTLE or msg_type == "FATAL" or msg_type == "ALERT": timestamp = strftime('%Y-%m-%d %X') msg = "%s: %s %s: %s" % (timestamp, PROGRAM, str(msg_type), " ".join(args)) WRITE(msg + "\n") FLUSH() + elif LOG_COUNTER == LOG_THROTTLE + 1: + timestamp = strftime('%Y-%m-%d %X') + msg = "%s: python.d.plugin: throttling further log messages for %s seconds" % (timestamp, str(int(LOG_NEXT_CHECK + 0.5) - int(now))) + WRITE(msg + "\n") + FLUSH() - global NEXT_CHECK - if NEXT_CHECK <= now: - NEXT_CHECK = now - (now % LOG_INTERVAL) + LOG_INTERVAL - if LOG_COUNTER < 0: + if LOG_NEXT_CHECK <= now: + if LOG_COUNTER >= LOG_THROTTLE: timestamp = strftime('%Y-%m-%d %X') - msg = "%s: Prevented %s log messages from displaying" % (timestamp, str(0 - LOG_COUNTER)) + msg = "%s: python.d.plugin: Prevented %s log messages from displaying" % (timestamp, str(LOG_COUNTER - LOG_THROTTLE)) WRITE(msg + "\n") FLUSH() + LOG_NEXT_CHECK = now - (now % LOG_INTERVAL) + LOG_INTERVAL + LOG_COUNTER = 0 + + if TRACE_FLAG: + if msg_type == "FATAL" or msg_type == "ERROR" or msg_type == "ALERT": + traceback.print_exc() def debug(*args): @@ -56,6 +75,13 @@ def error(*args): log_msg("ERROR", *args) +def alert(*args): + """ + Print message on stderr. + """ + log_msg("ALERT", *args) + + def info(*args): """ Print message on stderr. @@ -71,4 +97,4 @@ def fatal(*args): # using sys.stdout causes IOError: Broken Pipe print('DISABLE') # sys.stdout.write('DISABLE\n') - sys.exit(1) \ No newline at end of file + sys.exit(1) diff --git a/python.d/redis.chart.py b/python.d/redis.chart.py index 218401e1..b23160be 100644 --- a/python.d/redis.chart.py +++ b/python.d/redis.chart.py @@ -19,40 +19,58 @@ retries = 60 # 'unix_socket': None # }} -ORDER = ['operations', 'hit_rate', 'memory', 'keys', 'clients', 'slaves'] +ORDER = ['operations', 'hit_rate', 'memory', 'keys', 'net', 'connections', 'clients', 'slaves', 'persistence'] CHARTS = { 'operations': { - 'options': [None, 'Operations', 'operations/s', 'Statistics', 'redis.operations', 'line'], + 'options': [None, 'Redis Operations', 'operations/s', 'operations', 'redis.operations', 'line'], 'lines': [ + ['total_commands_processed', 'commands', 'incremental'], ['instantaneous_ops_per_sec', 'operations', 'absolute'] ]}, 'hit_rate': { - 'options': [None, 'Hit rate', 'percent', 'Statistics', 'redis.hit_rate', 'line'], + 'options': [None, 'Redis Hit rate', 'percent', 'hits', 'redis.hit_rate', 'line'], 'lines': [ ['hit_rate', 'rate', 'absolute'] ]}, 'memory': { - 'options': [None, 'Memory utilization', 'kilobytes', 'Memory', 'redis.memory', 'line'], + 'options': [None, 'Redis Memory utilization', 'kilobytes', 'memory', 'redis.memory', 'line'], 'lines': [ ['used_memory', 'total', 'absolute', 1, 1024], ['used_memory_lua', 'lua', 'absolute', 1, 1024] ]}, + 'net': { + 'options': [None, 'Redis Bandwidth', 'kilobits/s', 'network', 'redis.net', 'area'], + 'lines': [ + ['total_net_input_bytes', 'in', 'incremental', 8, 1024], + ['total_net_output_bytes', 'out', 'incremental', -8, 1024] + ]}, 'keys': { - 'options': [None, 'Database keys', 'keys', 'Keys', 'redis.keys', 'line'], + 'options': [None, 'Redis Keys per Database', 'keys', 'keys', 'redis.keys', 'line'], 'lines': [ # lines are created dynamically in `check()` method ]}, + 'connections': { + 'options': [None, 'Redis Connections', 'connections/s', 'connections', 'redis.connections', 'line'], + 'lines': [ + ['total_connections_received', 'received', 'incremental', 1], + ['rejected_connections', 'rejected', 'incremental', -1] + ]}, 'clients': { - 'options': [None, 'Clients', 'clients', 'Clients', 'redis.clients', 'line'], + 'options': [None, 'Redis Clients', 'clients', 'connections', 'redis.clients', 'line'], 'lines': [ - ['connected_clients', 'connected', 'absolute'], - ['blocked_clients', 'blocked', 'absolute'] + ['connected_clients', 'connected', 'absolute', 1], + ['blocked_clients', 'blocked', 'absolute', -1] ]}, 'slaves': { - 'options': [None, 'Slaves', 'slaves', 'Replication', 'redis.slaves', 'line'], + 'options': [None, 'Redis Slaves', 'slaves', 'replication', 'redis.slaves', 'line'], 'lines': [ ['connected_slaves', 'connected', 'absolute'] + ]}, + 'persistence': { + 'options': [None, 'Redis Persistence Changes Since Last Save', 'changes', 'persistence', 'redis.rdb_changes', 'line'], + 'lines': [ + ['rdb_changes_since_last_save', 'changes', 'absolute'] ]} } @@ -74,33 +92,45 @@ class Service(SocketService): Get data from socket :return: dict """ + response = self._get_raw_data() + if response is None: + # error has already been logged + return None + try: - raw = self._get_raw_data().split("\n") + parsed = response.split("\n") except AttributeError: - self.error("no data received") + self.error("response is invalid/empty") return None + data = {} - for line in raw: - if line.startswith(('instantaneous', 'keyspace', 'used_memory', 'connected', 'blocked')): - try: - t = line.split(':') - data[t[0]] = int(t[1]) - except (IndexError, ValueError): - pass - elif line.startswith('db'): + for line in parsed: + if len(line) < 5 or line[0] == '$' or line[0] == '#': + continue + + if line.startswith('db'): tmp = line.split(',')[0].replace('keys=', '') record = tmp.split(':') - data[record[0]] = int(record[1]) + data[record[0]] = record[1] + continue + + try: + t = line.split(':') + data[t[0]] = t[1] + except (IndexError, ValueError): + self.debug("invalid line received: " + str(line)) + pass + + if len(data) == 0: + self.error("received data doesn't have any records") + return None + try: - data['hit_rate'] = int((data['keyspace_hits'] / float(data['keyspace_hits'] + data['keyspace_misses'])) * 100) + data['hit_rate'] = (int(data['keyspace_hits']) * 100) / (int(data['keyspace_hits']) + int(data['keyspace_misses'])) except: data['hit_rate'] = 0 - if len(data) == 0: - self.error("received data doesn't have needed records") - return None - else: - return data + return data def _check_raw_data(self, data): """ @@ -113,11 +143,12 @@ class Service(SocketService): supposed = data.split('\n')[0][1:] offset = len(supposed) + 4 # 1 dollar sing, 1 new line character + 1 ending sequence '\r\n' supposed = int(supposed) + if length - offset >= supposed: + self.debug("received full response from redis") return True - else: - return False + self.debug("waiting more data from redis") return False def check(self): diff --git a/python.d/squid.chart.py b/python.d/squid.chart.py index 8300d9ba..e9e8f1d0 100644 --- a/python.d/squid.chart.py +++ b/python.d/squid.chart.py @@ -58,20 +58,25 @@ class Service(SocketService): Get data via http request :return: dict """ + response = self._get_raw_data() + data = {} try: raw = "" - for tmp in self._get_raw_data().split('\r\n'): + for tmp in response.split('\r\n'): if tmp.startswith("sample_time"): raw = tmp break + if raw.startswith('<'): self.error("invalid data received") return None + for row in raw.split('\n'): if row.startswith(("client", "server.all")): tmp = row.split("=") data[tmp[0].replace('.', '_').strip(' ')] = int(tmp[1]) + except (ValueError, AttributeError, TypeError): self.error("invalid data received") return None @@ -83,15 +88,19 @@ class Service(SocketService): return data def _check_raw_data(self, data): - if "Connection: keep-alive" in data[:1024]: + header = data[:1024].lower() + + if "connection: keep-alive" in header: self._keep_alive = True else: self._keep_alive = False - if data[-7:] == "\r\n0\r\n\r\n" and "Transfer-Encoding: chunked" in data[:1024]: # HTTP/1.1 response + if data[-7:] == "\r\n0\r\n\r\n" and "transfer-encoding: chunked" in header: # HTTP/1.1 response + self.debug("received full response from squid") return True - else: - return False + + self.debug("waiting more data from squid") + return False def check(self): """ diff --git a/src/Makefile.am b/src/Makefile.am index 86b9a9fe..32623f43 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -35,6 +35,7 @@ netdata_SOURCES = \ eval.c eval.h \ global_statistics.c global_statistics.h \ health.c health.h \ + ipc.c ipc.h \ log.c log.h \ main.c main.h \ plugin_checks.c plugin_checks.h \ diff --git a/src/apps_plugin.c b/src/apps_plugin.c index f22a575b..10987917 100644 --- a/src/apps_plugin.c +++ b/src/apps_plugin.c @@ -2787,7 +2787,6 @@ int main(int argc, char **argv) procfile_adaptive_initial_allocation = 1; time_t started_t = time(NULL); - time_t current_t; get_system_HZ(); get_system_pid_max(); get_system_cpus(); @@ -2829,22 +2828,16 @@ int main(int argc, char **argv) , RATES_DETAIL ); -#ifndef PROFILING_MODE - unsigned long long sunext = (time(NULL) - (time(NULL) % update_every) + update_every) * 1000000ULL; - unsigned long long sunow; -#endif /* PROFILING_MODE */ - + unsigned long long step = update_every * 1000000ULL; global_iterations_counter = 1; for(;1; global_iterations_counter++) { -#ifndef PROFILING_MODE - // delay until it is our time to run - while((sunow = time_usec()) < sunext) - sleep_usec(sunext - sunow); + unsigned long long now = time_usec(); + unsigned long long next = now - (now % step) + step; - // find the next time we need to run - while(time_usec() > sunext) - sunext += update_every * 1000000ULL; -#endif /* PROFILING_MODE */ + while(now < next) { + sleep_usec(next - now); + now = time_usec(); + } if(!collect_data_for_all_processes_from_proc()) { error("Cannot collect /proc data for running processes. Disabling apps.plugin..."); @@ -2878,13 +2871,9 @@ int main(int argc, char **argv) if(unlikely(debug)) fprintf(stderr, "apps.plugin: done Loop No %llu\n", global_iterations_counter); - current_t = time(NULL); + time_t current_t = time(NULL); -#ifndef PROFILING_MODE // restart check (14400 seconds) if(current_t - started_t > 14400) exit(0); -#else - if(current_t - started_t > 10) exit(0); -#endif /* PROFILING_MODE */ } } diff --git a/src/avl.c b/src/avl.c index 324afeeb..7efbf6da 100644 --- a/src/avl.c +++ b/src/avl.c @@ -283,18 +283,18 @@ avl *avl_remove(avl_tree *tree, avl *item) { // --------------------------- // traversing -void avl_walker(avl *node, void (*callback)(void *)) { +void avl_walker(avl *node, void (*callback)(void *entry, void *data), void *data) { if(node->avl_link[0]) - avl_walker(node->avl_link[0], callback); + avl_walker(node->avl_link[0], callback, data); - callback(node); + callback(node, data); if(node->avl_link[1]) - avl_walker(node->avl_link[1], callback); + avl_walker(node->avl_link[1], callback, data); } -void avl_traverse(avl_tree *t, void (*callback)(void *)) { - avl_walker(t->root, callback); +void avl_traverse(avl_tree *t, void (*callback)(void *entry, void *data), void *data) { + avl_walker(t->root, callback, data); } // --------------------------- @@ -372,9 +372,9 @@ avl *avl_insert_lock(avl_tree_lock *t, avl *a) { return ret; } -void avl_traverse_lock(avl_tree_lock *t, void (*callback)(void *)) { +void avl_traverse_lock(avl_tree_lock *t, void (*callback)(void *entry, void *data), void *data) { avl_read_lock(t); - avl_traverse(&t->avl_tree, callback); + avl_traverse(&t->avl_tree, callback, data); avl_unlock(t); } diff --git a/src/avl.h b/src/avl.h index 973d68fb..1ca687be 100644 --- a/src/avl.h +++ b/src/avl.h @@ -80,7 +80,7 @@ void avl_init_lock(avl_tree_lock *t, int (*compar)(void *a, void *b)); void avl_init(avl_tree *t, int (*compar)(void *a, void *b)); -void avl_traverse_lock(avl_tree_lock *t, void (*callback)(void *)); -void avl_traverse(avl_tree *t, void (*callback)(void *)); +void avl_traverse_lock(avl_tree_lock *t, void (*callback)(void *entry, void *data), void *data); +void avl_traverse(avl_tree *t, void (*callback)(void *entry, void *data), void *data); #endif /* avl.h */ diff --git a/src/common.c b/src/common.c index ce348d79..fa69bff8 100644 --- a/src/common.c +++ b/src/common.c @@ -864,11 +864,9 @@ uint32_t simple_hash(const char *name) { */ void strreverse(char *begin, char *end) { - char aux; - while (end > begin) { // clearer code. - aux = *end; + char aux = *end; *end-- = *begin; *begin++ = aux; } @@ -905,11 +903,10 @@ void *mymmap(const char *filename, size_t size, int flags, int ksm) { #ifdef MADV_MERGEABLE static int log_madvise_2 = 1, log_madvise_3 = 1; #endif - int fd; void *mem = NULL; errno = 0; - fd = open(filename, O_RDWR | O_CREAT | O_NOATIME, 0664); + int fd = open(filename, O_RDWR | O_CREAT | O_NOATIME, 0664); if (fd != -1) { if (lseek(fd, size, SEEK_SET) == (off_t) size) { if (write(fd, "", 1) == 1) { @@ -1090,14 +1087,12 @@ int snprintfz(char *dst, size_t n, const char *fmt, ...) { int processors = 1; long get_system_cpus(void) { - procfile *ff = NULL; - processors = 1; char filename[FILENAME_MAX + 1]; snprintfz(filename, FILENAME_MAX, "%s/proc/stat", global_host_prefix); - ff = procfile_open(filename, NULL, PROCFILE_FLAG_DEFAULT); + procfile *ff = procfile_open(filename, NULL, PROCFILE_FLAG_DEFAULT); if(!ff) { error("Cannot open file '%s'. Assuming system has %d processors.", filename, processors); return processors; @@ -1127,11 +1122,9 @@ long get_system_cpus(void) { pid_t pid_max = 32768; pid_t get_system_pid_max(void) { - procfile *ff = NULL; - char filename[FILENAME_MAX + 1]; snprintfz(filename, FILENAME_MAX, "%s/proc/sys/kernel/pid_max", global_host_prefix); - ff = procfile_open(filename, NULL, PROCFILE_FLAG_DEFAULT); + procfile *ff = procfile_open(filename, NULL, PROCFILE_FLAG_DEFAULT); if(!ff) { error("Cannot open file '%s'. Assuming system supports %d pids.", filename, pid_max); return pid_max; diff --git a/src/common.h b/src/common.h index dfb3c608..58a6dbb8 100644 --- a/src/common.h +++ b/src/common.h @@ -129,6 +129,8 @@ #include "main.h" #include "unit_test.h" +#include "ipc.h" + #ifdef abs #undef abs #endif diff --git a/src/daemon.c b/src/daemon.c index 5bf6a1e0..2453012e 100644 --- a/src/daemon.c +++ b/src/daemon.c @@ -58,6 +58,21 @@ static void chown_open_file(int fd, uid_t uid, gid_t gid) { } } +void create_needed_dir(const char *dir, uid_t uid, gid_t gid) +{ + // attempt to create the directory + if(mkdir(dir, 0755) == 0) { + // we created it + + // chown it to match the required user + if(chown(dir, uid, gid) == -1) + error("Cannot chown directory '%s' to %u:%u", dir, (unsigned int)uid, (unsigned int)gid); + } + else if(errno != EEXIST) + // log an error only if the directory does not exist + error("Cannot create directory '%s'", dir); +} + int become_user(const char *username, int pid_fd) { struct passwd *pw = getpwnam(username); @@ -69,6 +84,14 @@ int become_user(const char *username, int pid_fd) uid_t uid = pw->pw_uid; gid_t gid = pw->pw_gid; + create_needed_dir(CACHE_DIR, uid, gid); + create_needed_dir(VARLIB_DIR, uid, gid); + + if(pidfile[0]) { + if(chown(pidfile, uid, gid) == -1) + error("Cannot chown '%s' to %u:%u", pidfile, (unsigned int)uid, (unsigned int)gid); + } + int ngroups = (int)sysconf(_SC_NGROUPS_MAX); gid_t *supplementary_groups = NULL; if(ngroups) { @@ -91,7 +114,6 @@ int become_user(const char *username, int pid_fd) error("Cannot set supplementary groups for user '%s'", username); freez(supplementary_groups); - supplementary_groups = NULL; ngroups = 0; } @@ -223,11 +245,13 @@ int become_daemon(int dont_fork, const char *user) } else debug(D_SYSTEM, "Successfully became user '%s'.", user); } + else { + create_needed_dir(CACHE_DIR, getuid(), getgid()); + create_needed_dir(VARLIB_DIR, getuid(), getgid()); + } - if(pidfd != -1) { + if(pidfd != -1) close(pidfd); - pidfd = -1; - } return(0); } diff --git a/src/eval.c b/src/eval.c index 397b43bd..a4450f92 100644 --- a/src/eval.c +++ b/src/eval.c @@ -59,20 +59,6 @@ static inline void print_parsed_as_constant(BUFFER *out, calculated_number n); // ---------------------------------------------------------------------------- // evaluation of expressions -static inline calculated_number eval_check_number(calculated_number n, int *error) { - if(unlikely(isnan(n))) { - *error = EVAL_ERROR_VALUE_IS_NAN; - return 0; - } - - if(unlikely(isinf(n))) { - *error = EVAL_ERROR_VALUE_IS_INFINITE; - return 0; - } - - return n; -} - static inline calculated_number eval_variable(EVAL_EXPRESSION *exp, EVAL_VARIABLE *v, int *error) { static uint32_t this_hash = 0, now_hash = 0, after_hash = 0, before_hash = 0, status_hash = 0, removed_hash = 0, uninitialized_hash = 0, undefined_hash = 0, clear_hash = 0, warning_hash = 0, critical_hash = 0; calculated_number n; @@ -187,7 +173,7 @@ static inline calculated_number eval_variable(EVAL_EXPRESSION *exp, EVAL_VARIABL } *error = EVAL_ERROR_UNKNOWN_VARIABLE; - buffer_sprintf(exp->error_msg, "unknown variable '%s'", v->name); + buffer_sprintf(exp->error_msg, "[ undefined variable '%s' ] ", v->name); return 0; } @@ -213,7 +199,6 @@ static inline calculated_number eval_value(EVAL_EXPRESSION *exp, EVAL_VALUE *v, break; } - // return eval_check_number(n, error); return n; } @@ -362,7 +347,6 @@ static inline calculated_number eval_node(EVAL_EXPRESSION *exp, EVAL_NODE *op, i calculated_number n = operators[op->operator].eval(exp, op, error); - // return eval_check_number(n, error); return n; } @@ -1047,9 +1031,7 @@ static inline EVAL_NODE *parse_rest_of_expression(const char **string, int *erro // high level function to parse an expression or a sub-expression static inline EVAL_NODE *parse_full_expression(const char **string, int *error) { - EVAL_NODE *op1 = NULL; - - op1 = parse_one_full_operand(string, error); + EVAL_NODE *op1 = parse_one_full_operand(string, error); if(!op1) { *error = EVAL_ERROR_MISSING_OPERAND; return NULL; @@ -1067,8 +1049,19 @@ int expression_evaluate(EVAL_EXPRESSION *exp) { buffer_reset(exp->error_msg); exp->result = eval_node(exp, (EVAL_NODE *)exp->nodes, &exp->error); - if(exp->error == EVAL_ERROR_OK) - exp->result = eval_check_number(exp->result, &exp->error); + if(unlikely(isnan(exp->result))) { + if(exp->error == EVAL_ERROR_OK) + exp->error = EVAL_ERROR_VALUE_IS_NAN; + } + else if(unlikely(isinf(exp->result))) { + if(exp->error == EVAL_ERROR_OK) + exp->error = EVAL_ERROR_VALUE_IS_INFINITE; + } + else if(unlikely(exp->error == EVAL_ERROR_UNKNOWN_VARIABLE)) { + // although there is an unknown variable + // the expression was evaluated successfully + exp->error = EVAL_ERROR_OK; + } if(exp->error != EVAL_ERROR_OK) { exp->result = NAN; @@ -1086,7 +1079,6 @@ int expression_evaluate(EVAL_EXPRESSION *exp) { EVAL_EXPRESSION *expression_parse(const char *string, const char **failed_at, int *error) { const char *s = string; int err = EVAL_ERROR_OK; - unsigned long pos = 0; EVAL_NODE *op = parse_full_expression(&s, &err); @@ -1102,7 +1094,7 @@ EVAL_EXPRESSION *expression_parse(const char *string, const char **failed_at, in if (error) *error = err; if(!op) { - pos = s - string + 1; + unsigned long pos = s - string + 1; error("failed to parse expression '%s': %s at character %lu (i.e.: '%s').", string, expression_strerror(err), pos, s); return NULL; } diff --git a/src/health.c b/src/health.c index 53fbcdca..6441a14b 100644 --- a/src/health.c +++ b/src/health.c @@ -141,13 +141,12 @@ static inline void health_alarm_log_save(RRDHOST *host, ALARM_ENTRY *ae) { static inline ssize_t health_alarm_log_read(RRDHOST *host, FILE *fp, const char *filename) { static uint32_t max_unique_id = 0, max_alarm_id = 0; - ssize_t loaded = -1, updated = -1, errored = -1, duplicate = -1; errno = 0; char *s, *buf = mallocz(65536 + 1); size_t line = 0, len = 0; - loaded = updated = errored = duplicate = 0; + ssize_t loaded = 0, updated = 0, errored = 0, duplicate = 0; pthread_rwlock_rdlock(&host->health_log.alarm_log_rwlock); @@ -486,14 +485,17 @@ static inline void rrdvar_free(RRDHOST *host, avl_tree_lock *tree, RRDVAR *rv) { if(!rv) return; - if(tree) - rrdvar_index_del(tree, rv); + if(tree) { + debug(D_VARIABLES, "Deleting variable '%s'", rv->name); + if(unlikely(!rrdvar_index_del(tree, rv))) + error("Attempted to delete variable '%s' from host '%s', but it is not found.", rv->name, host->hostname); + } freez(rv->name); freez(rv); } -static inline RRDVAR *rrdvar_create_and_index(const char *scope, avl_tree_lock *tree, const char *name, int type, calculated_number *value) { +static inline RRDVAR *rrdvar_create_and_index(const char *scope, avl_tree_lock *tree, const char *name, int type, void *value) { char *variable = strdupz(name); rrdvar_fix_name(variable); uint32_t hash = simple_hash(variable); @@ -518,19 +520,83 @@ static inline RRDVAR *rrdvar_create_and_index(const char *scope, avl_tree_lock * debug(D_VARIABLES, "Variable '%s' created in scope '%s'", variable, scope); } else { + debug(D_VARIABLES, "Variable '%s' is already found in scope '%s'.", variable, scope); + // already exists freez(variable); + + // this is important + // it must return NULL - not the existing variable - or double-free will happen rv = NULL; } return rv; } +// ---------------------------------------------------------------------------- +// CUSTOM VARIABLES + +RRDVAR *rrdvar_custom_host_variable_create(RRDHOST *host, const char *name) { + calculated_number *v = callocz(1, sizeof(calculated_number)); + *v = NAN; + RRDVAR *rv = rrdvar_create_and_index("host", &host->variables_root_index, name, RRDVAR_TYPE_CALCULATED_ALLOCATED, v); + if(unlikely(!rv)) { + free(v); + error("Requested variable '%s' already exists - possibly 2 plugins will be updating it at the same time", name); + + char *variable = strdupz(name); + rrdvar_fix_name(variable); + uint32_t hash = simple_hash(variable); + + rv = rrdvar_index_find(&host->variables_root_index, variable, hash); + } + + return rv; +} + +void rrdvar_custom_host_variable_destroy(RRDHOST *host, const char *name) { + char *variable = strdupz(name); + rrdvar_fix_name(variable); + uint32_t hash = simple_hash(variable); + + RRDVAR *rv = rrdvar_index_find(&host->variables_root_index, variable, hash); + freez(variable); + + if(!rv) { + error("Attempted to remove variable '%s' from host '%s', but it does not exist.", name, host->hostname); + return; + } + + if(rv->type != RRDVAR_TYPE_CALCULATED_ALLOCATED) { + error("Attempted to remove variable '%s' from host '%s', but it does not a custom allocated variable.", name, host->hostname); + return; + } + + if(!rrdvar_index_del(&host->variables_root_index, rv)) { + error("Attempted to remove variable '%s' from host '%s', but it cannot be found.", name, host->hostname); + return; + } + + freez(rv->name); + freez(rv->value); + freez(rv); +} + +void rrdvar_custom_host_variable_set(RRDVAR *rv, calculated_number value) { + if(rv->type != RRDVAR_TYPE_CALCULATED_ALLOCATED) + error("requested to set variable '%s' to value " CALCULATED_NUMBER_FORMAT " but the variable is not a custom one.", rv->name, value); + else { + calculated_number *v = rv->value; + *v = value; + } +} + // ---------------------------------------------------------------------------- // RRDVAR lookup -calculated_number rrdvar2number(RRDVAR *rv) { +static calculated_number rrdvar2number(RRDVAR *rv) { switch(rv->type) { + case RRDVAR_TYPE_CALCULATED_ALLOCATED: case RRDVAR_TYPE_CALCULATED: { calculated_number *n = (calculated_number *)rv->value; return *n; @@ -562,11 +628,6 @@ calculated_number rrdvar2number(RRDVAR *rv) { } } -void dump_variable(void *data) { - RRDVAR *rv = (RRDVAR *)data; - debug(D_HEALTH, "%50s : %20.5Lf", rv->name, rrdvar2number(rv)); -} - int health_variable_lookup(const char *variable, uint32_t hash, RRDCALC *rc, calculated_number *result) { RRDSET *st = rc->rrdset; RRDVAR *rv; @@ -591,162 +652,217 @@ int health_variable_lookup(const char *variable, uint32_t hash, RRDCALC *rc, cal return 1; } - debug(D_HEALTH, "Available local chart '%s' variables:", st->id); - avl_traverse_lock(&st->variables_root_index, dump_variable); + return 0; +} - debug(D_HEALTH, "Available family '%s' variables:", st->rrdfamily->family); - avl_traverse_lock(&st->rrdfamily->variables_root_index, dump_variable); +// ---------------------------------------------------------------------------- +// RRDVAR to JSON - debug(D_HEALTH, "Available host '%s' variables:", st->rrdhost->hostname); - avl_traverse_lock(&st->rrdhost->variables_root_index, dump_variable); +struct variable2json_helper { + BUFFER *buf; + size_t counter; +}; - return 0; +static void single_variable2json(void *entry, void *data) { + struct variable2json_helper *helper = (struct variable2json_helper *)data; + RRDVAR *rv = (RRDVAR *)entry; + calculated_number value = rrdvar2number(rv); + + if(unlikely(isnan(value) || isinf(value))) + buffer_sprintf(helper->buf, "%s\n\t\t\"%s\": null", helper->counter?",":"", rv->name); + else + buffer_sprintf(helper->buf, "%s\n\t\t\"%s\": %0.5Lf", helper->counter?",":"", rv->name, (long double)value); + + helper->counter++; +} + +void health_api_v1_chart_variables2json(RRDSET *st, BUFFER *buf) { + struct variable2json_helper helper = { + .buf = buf, + .counter = 0 + }; + + buffer_sprintf(buf, "{\n\t\"chart\": \"%s\",\n\t\"chart_name\": \"%s\",\n\t\"chart_variables\": {", st->id, st->name); + avl_traverse_lock(&st->variables_root_index, single_variable2json, (void *)&helper); + buffer_sprintf(buf, "\n\t},\n\t\"family\": \"%s\",\n\t\"family_variables\": {", st->family); + helper.counter = 0; + avl_traverse_lock(&st->rrdfamily->variables_root_index, single_variable2json, (void *)&helper); + buffer_sprintf(buf, "\n\t},\n\t\"host\": \"%s\",\n\t\"host_variables\": {", st->rrdhost->hostname); + helper.counter = 0; + avl_traverse_lock(&st->rrdhost->variables_root_index, single_variable2json, (void *)&helper); + buffer_strcat(buf, "\n\t}\n}\n"); } + // ---------------------------------------------------------------------------- -// RRDSETVAR management +// RRDDIMVAR management +// DIMENSION VARIABLES -RRDSETVAR *rrdsetvar_create(RRDSET *st, const char *variable, int type, void *value, uint32_t options) { - debug(D_VARIABLES, "RRDVARSET create for chart id '%s' name '%s' with variable name '%s'", st->id, st->name, variable); - RRDSETVAR *rs = (RRDSETVAR *)callocz(1, sizeof(RRDSETVAR)); +#define RRDDIMVAR_ID_MAX 1024 - char buffer[RRDVAR_MAX_LENGTH + 1]; - snprintfz(buffer, RRDVAR_MAX_LENGTH, "%s.%s", st->id, variable); - rs->fullid = strdupz(buffer); +static inline void rrddimvar_free_variables(RRDDIMVAR *rs) { + RRDDIM *rd = rs->rrddim; + RRDSET *st = rd->rrdset; - snprintfz(buffer, RRDVAR_MAX_LENGTH, "%s.%s", st->name, variable); - rs->fullname = strdupz(buffer); + // CHART VARIABLES FOR THIS DIMENSION - rs->variable = strdupz(variable); + rrdvar_free(st->rrdhost, &st->variables_root_index, rs->var_local_id); + rs->var_local_id = NULL; - rs->type = type; - rs->value = value; - rs->options = options; - rs->rrdset = st; + rrdvar_free(st->rrdhost, &st->variables_root_index, rs->var_local_name); + rs->var_local_name = NULL; - rs->local = rrdvar_create_and_index("local", &st->variables_root_index, rs->variable, rs->type, rs->value); - rs->family = rrdvar_create_and_index("family", &st->rrdfamily->variables_root_index, rs->fullid, rs->type, rs->value); - rs->host = rrdvar_create_and_index("host", &st->rrdhost->variables_root_index, rs->fullid, rs->type, rs->value); - rs->family_name = rrdvar_create_and_index("family", &st->rrdfamily->variables_root_index, rs->fullname, rs->type, rs->value); - rs->host_name = rrdvar_create_and_index("host", &st->rrdhost->variables_root_index, rs->fullname, rs->type, rs->value); + // FAMILY VARIABLES FOR THIS DIMENSION - rs->next = st->variables; - st->variables = rs; + rrdvar_free(st->rrdhost, &st->rrdfamily->variables_root_index, rs->var_family_id); + rs->var_family_id = NULL; - return rs; -} + rrdvar_free(st->rrdhost, &st->rrdfamily->variables_root_index, rs->var_family_name); + rs->var_family_name = NULL; -void rrdsetvar_rename_all(RRDSET *st) { - debug(D_VARIABLES, "RRDSETVAR rename for chart id '%s' name '%s'", st->id, st->name); + rrdvar_free(st->rrdhost, &st->rrdfamily->variables_root_index, rs->var_family_contextid); + rs->var_family_contextid = NULL; - // only these 2 can change name - // rs->family_name - // rs->host_name + rrdvar_free(st->rrdhost, &st->rrdfamily->variables_root_index, rs->var_family_contextname); + rs->var_family_contextname = NULL; - char buffer[RRDVAR_MAX_LENGTH + 1]; - RRDSETVAR *rs, *next = st->variables; - while((rs = next)) { - next = rs->next; + // HOST VARIABLES FOR THIS DIMENSION - snprintfz(buffer, RRDVAR_MAX_LENGTH, "%s.%s", st->name, rs->variable); + rrdvar_free(st->rrdhost, &st->rrdhost->variables_root_index, rs->var_host_chartidid); + rs->var_host_chartidid = NULL; - if (strcmp(buffer, rs->fullname)) { - // name changed - rrdvar_free(st->rrdhost, &st->rrdfamily->variables_root_index, rs->family_name); - rrdvar_free(st->rrdhost, &st->rrdhost->variables_root_index, rs->host_name); + rrdvar_free(st->rrdhost, &st->rrdhost->variables_root_index, rs->var_host_chartidname); + rs->var_host_chartidname = NULL; - freez(rs->fullname); - rs->fullname = strdupz(st->name); - rs->family_name = rrdvar_create_and_index("family", &st->rrdfamily->variables_root_index, rs->fullname, rs->type, rs->value); - rs->host_name = rrdvar_create_and_index("host", &st->rrdhost->variables_root_index, rs->fullname, rs->type, rs->value); - } - } + rrdvar_free(st->rrdhost, &st->rrdhost->variables_root_index, rs->var_host_chartnameid); + rs->var_host_chartnameid = NULL; - rrdsetcalc_link_matching(st); -} + rrdvar_free(st->rrdhost, &st->rrdhost->variables_root_index, rs->var_host_chartnamename); + rs->var_host_chartnamename = NULL; -void rrdsetvar_free(RRDSETVAR *rs) { - RRDSET *st = rs->rrdset; - debug(D_VARIABLES, "RRDSETVAR free for chart id '%s' name '%s', variable '%s'", st->id, st->name, rs->variable); + // KEYS - rrdvar_free(st->rrdhost, &st->variables_root_index, rs->local); - rrdvar_free(st->rrdhost, &st->rrdfamily->variables_root_index, rs->family); - rrdvar_free(st->rrdhost, &st->rrdhost->variables_root_index, rs->host); - rrdvar_free(st->rrdhost, &st->rrdfamily->variables_root_index, rs->family_name); - rrdvar_free(st->rrdhost, &st->rrdhost->variables_root_index, rs->host_name); + freez(rs->key_id); + rs->key_id = NULL; - if(st->variables == rs) { - st->variables = rs->next; - } - else { - RRDSETVAR *t; - for (t = st->variables; t && t->next != rs; t = t->next); - if(!t) error("RRDSETVAR '%s' not found in chart '%s' variables linked list", rs->fullname, st->id); - else t->next = rs->next; - } + freez(rs->key_name); + rs->key_name = NULL; - freez(rs->fullid); - freez(rs->fullname); - freez(rs->variable); - freez(rs); -} + freez(rs->key_fullidid); + rs->key_fullidid = NULL; -// ---------------------------------------------------------------------------- -// RRDDIMVAR management + freez(rs->key_fullidname); + rs->key_fullidname = NULL; -#define RRDDIMVAR_ID_MAX 1024 + freez(rs->key_contextid); + rs->key_contextid = NULL; -RRDDIMVAR *rrddimvar_create(RRDDIM *rd, int type, const char *prefix, const char *suffix, void *value, uint32_t options) { - RRDSET *st = rd->rrdset; + freez(rs->key_contextname); + rs->key_contextname = NULL; - debug(D_VARIABLES, "RRDDIMSET create for chart id '%s' name '%s', dimension id '%s', name '%s%s%s'", st->id, st->name, rd->id, (prefix)?prefix:"", rd->name, (suffix)?suffix:""); + freez(rs->key_fullnameid); + rs->key_fullnameid = NULL; - if(!prefix) prefix = ""; - if(!suffix) suffix = ""; + freez(rs->key_fullnamename); + rs->key_fullnamename = NULL; +} + +static inline void rrddimvar_create_variables(RRDDIMVAR *rs) { + rrddimvar_free_variables(rs); + + RRDDIM *rd = rs->rrddim; + RRDSET *st = rd->rrdset; char buffer[RRDDIMVAR_ID_MAX + 1]; - RRDDIMVAR *rs = (RRDDIMVAR *)callocz(1, sizeof(RRDDIMVAR)); - rs->prefix = strdupz(prefix); - rs->suffix = strdupz(suffix); + // KEYS snprintfz(buffer, RRDDIMVAR_ID_MAX, "%s%s%s", rs->prefix, rd->id, rs->suffix); - rs->id = strdupz(buffer); + rs->key_id = strdupz(buffer); snprintfz(buffer, RRDDIMVAR_ID_MAX, "%s%s%s", rs->prefix, rd->name, rs->suffix); - rs->name = strdupz(buffer); + rs->key_name = strdupz(buffer); + + snprintfz(buffer, RRDDIMVAR_ID_MAX, "%s.%s", st->id, rs->key_id); + rs->key_fullidid = strdupz(buffer); + + snprintfz(buffer, RRDDIMVAR_ID_MAX, "%s.%s", st->id, rs->key_name); + rs->key_fullidname = strdupz(buffer); + + snprintfz(buffer, RRDDIMVAR_ID_MAX, "%s.%s", st->context, rs->key_id); + rs->key_contextid = strdupz(buffer); + + snprintfz(buffer, RRDDIMVAR_ID_MAX, "%s.%s", st->context, rs->key_name); + rs->key_contextname = strdupz(buffer); + + snprintfz(buffer, RRDDIMVAR_ID_MAX, "%s.%s", st->name, rs->key_id); + rs->key_fullnameid = strdupz(buffer); + + snprintfz(buffer, RRDDIMVAR_ID_MAX, "%s.%s", st->name, rs->key_name); + rs->key_fullnamename = strdupz(buffer); + + // CHART VARIABLES FOR THIS DIMENSION + // ----------------------------------- + // + // dimensions are available as: + // - $id + // - $name + + rs->var_local_id = rrdvar_create_and_index("local", &st->variables_root_index, rs->key_id, rs->type, rs->value); + rs->var_local_name = rrdvar_create_and_index("local", &st->variables_root_index, rs->key_name, rs->type, rs->value); + + // FAMILY VARIABLES FOR THIS DIMENSION + // ----------------------------------- + // + // dimensions are available as: + // - $id (only the first, when multiple overlap) + // - $name (only the first, when multiple overlap) + // - $chart-context.id + // - $chart-context.name + + rs->var_family_id = rrdvar_create_and_index("family", &st->rrdfamily->variables_root_index, rs->key_id, rs->type, rs->value); + rs->var_family_name = rrdvar_create_and_index("family", &st->rrdfamily->variables_root_index, rs->key_name, rs->type, rs->value); + rs->var_family_contextid = rrdvar_create_and_index("family", &st->rrdfamily->variables_root_index, rs->key_contextid, rs->type, rs->value); + rs->var_family_contextname = rrdvar_create_and_index("family", &st->rrdfamily->variables_root_index, rs->key_contextname, rs->type, rs->value); + + // HOST VARIABLES FOR THIS DIMENSION + // ----------------------------------- + // + // dimensions are available as: + // - $chart-id.id + // - $chart-id.name + // - $chart-name.id + // - $chart-name.name + + rs->var_host_chartidid = rrdvar_create_and_index("host", &st->rrdhost->variables_root_index, rs->key_fullidid, rs->type, rs->value); + rs->var_host_chartidname = rrdvar_create_and_index("host", &st->rrdhost->variables_root_index, rs->key_fullidname, rs->type, rs->value); + rs->var_host_chartnameid = rrdvar_create_and_index("host", &st->rrdhost->variables_root_index, rs->key_fullnameid, rs->type, rs->value); + rs->var_host_chartnamename = rrdvar_create_and_index("host", &st->rrdhost->variables_root_index, rs->key_fullnamename, rs->type, rs->value); +} + +RRDDIMVAR *rrddimvar_create(RRDDIM *rd, int type, const char *prefix, const char *suffix, void *value, uint32_t options) { + RRDSET *st = rd->rrdset; - snprintfz(buffer, RRDDIMVAR_ID_MAX, "%s.%s", rd->rrdset->id, rs->id); - rs->fullidid = strdupz(buffer); + debug(D_VARIABLES, "RRDDIMSET create for chart id '%s' name '%s', dimension id '%s', name '%s%s%s'", st->id, st->name, rd->id, (prefix)?prefix:"", rd->name, (suffix)?suffix:""); - snprintfz(buffer, RRDDIMVAR_ID_MAX, "%s.%s", rd->rrdset->id, rs->name); - rs->fullidname = strdupz(buffer); + if(!prefix) prefix = ""; + if(!suffix) suffix = ""; - snprintfz(buffer, RRDDIMVAR_ID_MAX, "%s.%s", rd->rrdset->name, rs->id); - rs->fullnameid = strdupz(buffer); + RRDDIMVAR *rs = (RRDDIMVAR *)callocz(1, sizeof(RRDDIMVAR)); - snprintfz(buffer, RRDDIMVAR_ID_MAX, "%s.%s", rd->rrdset->name, rs->name); - rs->fullnamename = strdupz(buffer); + rs->prefix = strdupz(prefix); + rs->suffix = strdupz(suffix); rs->type = type; rs->value = value; rs->options = options; rs->rrddim = rd; - rs->local_id = rrdvar_create_and_index("local", &st->variables_root_index, rs->id, rs->type, rs->value); - rs->local_name = rrdvar_create_and_index("local", &st->variables_root_index, rs->name, rs->type, rs->value); - - rs->family_id = rrdvar_create_and_index("family", &st->rrdfamily->variables_root_index, rs->id, rs->type, rs->value); - rs->family_name = rrdvar_create_and_index("family", &st->rrdfamily->variables_root_index, rs->name, rs->type, rs->value); - - rs->host_fullidid = rrdvar_create_and_index("host", &st->rrdhost->variables_root_index, rs->fullidid, rs->type, rs->value); - rs->host_fullidname = rrdvar_create_and_index("host", &st->rrdhost->variables_root_index, rs->fullidname, rs->type, rs->value); - rs->host_fullnameid = rrdvar_create_and_index("host", &st->rrdhost->variables_root_index, rs->fullnameid, rs->type, rs->value); - rs->host_fullnamename = rrdvar_create_and_index("host", &st->rrdhost->variables_root_index, rs->fullnamename, rs->type, rs->value); - rs->next = rd->variables; rd->variables = rs; + rrddimvar_create_variables(rs); + return rs; } @@ -757,41 +873,7 @@ void rrddimvar_rename_all(RRDDIM *rd) { RRDDIMVAR *rs, *next = rd->variables; while((rs = next)) { next = rs->next; - - if (strcmp(rd->name, rs->name)) { - char buffer[RRDDIMVAR_ID_MAX + 1]; - // name changed - - // name - rrdvar_free(st->rrdhost, &st->variables_root_index, rs->local_name); - freez(rs->name); - snprintfz(buffer, RRDDIMVAR_ID_MAX, "%s%s%s", rs->prefix, rd->name, rs->suffix); - rs->name = strdupz(buffer); - rs->local_name = rrdvar_create_and_index("local", &st->variables_root_index, rs->name, rs->type, rs->value); - - rrdvar_free(st->rrdhost, &st->rrdhost->variables_root_index, rs->host_fullidname); - freez(rs->fullidname); - snprintfz(buffer, RRDDIMVAR_ID_MAX, "%s.%s", st->id, rs->name); - rs->fullidname = strdupz(buffer); - rs->host_fullidname = rrdvar_create_and_index("host", &st->rrdhost->variables_root_index, - rs->fullidname, rs->type, rs->value); - - // fullnameid - rrdvar_free(st->rrdhost, &st->rrdhost->variables_root_index, rs->host_fullnameid); - freez(rs->fullnameid); - snprintfz(buffer, RRDDIMVAR_ID_MAX, "%s.%s", st->name, rs->id); - rs->fullnameid = strdupz(buffer); - rs->host_fullnameid = rrdvar_create_and_index("host", &st->rrdhost->variables_root_index, - rs->fullnameid, rs->type, rs->value); - - // fullnamename - rrdvar_free(st->rrdhost, &st->rrdhost->variables_root_index, rs->host_fullnamename); - freez(rs->fullnamename); - snprintfz(buffer, RRDDIMVAR_ID_MAX, "%s.%s", st->name, rs->name); - rs->fullnamename = strdupz(buffer); - rs->host_fullnamename = rrdvar_create_and_index("host", &st->rrdhost->variables_root_index, - rs->fullnamename, rs->type, rs->value); - } + rrddimvar_create_variables(rs); } } @@ -800,16 +882,7 @@ void rrddimvar_free(RRDDIMVAR *rs) { RRDSET *st = rd->rrdset; debug(D_VARIABLES, "RRDDIMSET free for chart id '%s' name '%s', dimension id '%s', name '%s', prefix='%s', suffix='%s'", st->id, st->name, rd->id, rd->name, rs->prefix, rs->suffix); - rrdvar_free(st->rrdhost, &st->variables_root_index, rs->local_id); - rrdvar_free(st->rrdhost, &st->variables_root_index, rs->local_name); - - rrdvar_free(st->rrdhost, &st->rrdfamily->variables_root_index, rs->family_id); - rrdvar_free(st->rrdhost, &st->rrdfamily->variables_root_index, rs->family_name); - - rrdvar_free(st->rrdhost, &st->rrdhost->variables_root_index, rs->host_fullidid); - rrdvar_free(st->rrdhost, &st->rrdhost->variables_root_index, rs->host_fullidname); - rrdvar_free(st->rrdhost, &st->rrdhost->variables_root_index, rs->host_fullnameid); - rrdvar_free(st->rrdhost, &st->rrdhost->variables_root_index, rs->host_fullnamename); + rrddimvar_free_variables(rs); if(rd->variables == rs) { debug(D_VARIABLES, "RRDDIMSET removing first entry for chart id '%s' name '%s', dimension id '%s', name '%s'", st->id, st->name, rd->id, rd->name); @@ -819,18 +892,129 @@ void rrddimvar_free(RRDDIMVAR *rs) { debug(D_VARIABLES, "RRDDIMSET removing non-first entry for chart id '%s' name '%s', dimension id '%s', name '%s'", st->id, st->name, rd->id, rd->name); RRDDIMVAR *t; for (t = rd->variables; t && t->next != rs; t = t->next) ; - if(!t) error("RRDDIMVAR '%s' not found in dimension '%s/%s' variables linked list", rs->name, st->id, rd->id); + if(!t) error("RRDDIMVAR '%s' not found in dimension '%s/%s' variables linked list", rs->key_name, st->id, rd->id); else t->next = rs->next; } freez(rs->prefix); freez(rs->suffix); - freez(rs->id); - freez(rs->name); - freez(rs->fullidid); - freez(rs->fullidname); - freez(rs->fullnameid); - freez(rs->fullnamename); + freez(rs); +} + +// ---------------------------------------------------------------------------- +// RRDSETVAR management +// CHART VARIABLES + +static inline void rrdsetvar_free_variables(RRDSETVAR *rs) { + RRDSET *st = rs->rrdset; + + // CHART + + rrdvar_free(st->rrdhost, &st->variables_root_index, rs->var_local); + rs->var_local = NULL; + + // FAMILY + + rrdvar_free(st->rrdhost, &st->rrdfamily->variables_root_index, rs->var_family); + rs->var_family = NULL; + + rrdvar_free(st->rrdhost, &st->rrdhost->variables_root_index, rs->var_host); + rs->var_host = NULL; + + // HOST + + rrdvar_free(st->rrdhost, &st->rrdfamily->variables_root_index, rs->var_family_name); + rs->var_family_name = NULL; + + rrdvar_free(st->rrdhost, &st->rrdhost->variables_root_index, rs->var_host_name); + rs->var_host_name = NULL; + + // KEYS + + freez(rs->key_fullid); + rs->key_fullid = NULL; + + freez(rs->key_fullname); + rs->key_fullname = NULL; +} + +static inline void rrdsetvar_create_variables(RRDSETVAR *rs) { + rrdsetvar_free_variables(rs); + + RRDSET *st = rs->rrdset; + + // KEYS + + char buffer[RRDVAR_MAX_LENGTH + 1]; + snprintfz(buffer, RRDVAR_MAX_LENGTH, "%s.%s", st->id, rs->variable); + rs->key_fullid = strdupz(buffer); + + snprintfz(buffer, RRDVAR_MAX_LENGTH, "%s.%s", st->name, rs->variable); + rs->key_fullname = strdupz(buffer); + + // CHART + + rs->var_local = rrdvar_create_and_index("local", &st->variables_root_index, rs->variable, rs->type, rs->value); + + // FAMILY + + rs->var_family = rrdvar_create_and_index("family", &st->rrdfamily->variables_root_index, rs->key_fullid, rs->type, rs->value); + rs->var_family_name = rrdvar_create_and_index("family", &st->rrdfamily->variables_root_index, rs->key_fullname, rs->type, rs->value); + + // HOST + + rs->var_host = rrdvar_create_and_index("host", &st->rrdhost->variables_root_index, rs->key_fullid, rs->type, rs->value); + rs->var_host_name = rrdvar_create_and_index("host", &st->rrdhost->variables_root_index, rs->key_fullname, rs->type, rs->value); + +} + +RRDSETVAR *rrdsetvar_create(RRDSET *st, const char *variable, int type, void *value, uint32_t options) { + debug(D_VARIABLES, "RRDVARSET create for chart id '%s' name '%s' with variable name '%s'", st->id, st->name, variable); + RRDSETVAR *rs = (RRDSETVAR *)callocz(1, sizeof(RRDSETVAR)); + + rs->variable = strdupz(variable); + rs->type = type; + rs->value = value; + rs->options = options; + rs->rrdset = st; + + rs->next = st->variables; + st->variables = rs; + + rrdsetvar_create_variables(rs); + + return rs; +} + +void rrdsetvar_rename_all(RRDSET *st) { + debug(D_VARIABLES, "RRDSETVAR rename for chart id '%s' name '%s'", st->id, st->name); + + RRDSETVAR *rs, *next = st->variables; + while((rs = next)) { + next = rs->next; + rrdsetvar_create_variables(rs); + } + + rrdsetcalc_link_matching(st); +} + +void rrdsetvar_free(RRDSETVAR *rs) { + RRDSET *st = rs->rrdset; + debug(D_VARIABLES, "RRDSETVAR free for chart id '%s' name '%s', variable '%s'", st->id, st->name, rs->variable); + + if(st->variables == rs) { + st->variables = rs->next; + } + else { + RRDSETVAR *t; + for (t = st->variables; t && t->next != rs; t = t->next); + if(!t) error("RRDSETVAR '%s' not found in chart '%s' variables linked list", rs->key_fullname, st->id); + else t->next = rs->next; + } + + rrdsetvar_free_variables(rs); + + freez(rs->variable); freez(rs); } @@ -2391,11 +2575,13 @@ void health_reload(void) { // health main thread and friends static inline int rrdcalc_value2status(calculated_number n) { - if(isnan(n)) return RRDCALC_STATUS_UNDEFINED; + if(isnan(n) || isinf(n)) return RRDCALC_STATUS_UNDEFINED; if(n) return RRDCALC_STATUS_RAISED; return RRDCALC_STATUS_CLEAR; } +#define ALARM_EXEC_COMMAND_LENGTH 8192 + static inline void health_alarm_execute(RRDHOST *host, ALARM_ENTRY *ae) { ae->flags |= HEALTH_ENTRY_FLAG_PROCESSED; @@ -2406,30 +2592,35 @@ static inline void health_alarm_execute(RRDHOST *host, ALARM_ENTRY *ae) { // find the previous notification for the same alarm // which we have run the exec script - ALARM_ENTRY *t; - for(t = ae->next; t ;t = t->next) { - if(t->alarm_id == ae->alarm_id && t->flags & HEALTH_ENTRY_FLAG_EXEC_RUN) - break; - } + { + uint32_t id = ae->alarm_id; + ALARM_ENTRY *t; + for(t = ae->next; t ; t = t->next) { + if(t->alarm_id == id && t->flags & HEALTH_ENTRY_FLAG_EXEC_RUN) + break; + } - if(likely(t)) { - // we have executed this alarm notification in the past - if (t && t->new_status == ae->new_status) { - // don't send the same notification again - debug(D_HEALTH, "Health not sending again notification for alarm '%s.%s' status %s", ae->chart, ae->name, - rrdcalc_status2string(ae->new_status)); - goto done; + if(likely(t)) { + // we have executed this alarm notification in the past + if(t && t->new_status == ae->new_status) { + // don't send the notification for the same status again + debug(D_HEALTH, "Health not sending again notification for alarm '%s.%s' status %s", ae->chart, ae->name + , rrdcalc_status2string(ae->new_status)); + goto done; + } } - } - else { - // we have not executed this alarm notification in the past - if(unlikely(ae->old_status == RRDCALC_STATUS_UNINITIALIZED && ae->new_status == RRDCALC_STATUS_CLEAR)) { - debug(D_HEALTH, "Health not sending notification for first initialization of alarm '%s.%s' status %s", ae->chart, ae->name, rrdcalc_status2string(ae->new_status)); - goto done; + else { + // we have not executed this alarm notification in the past + // so, don't send CLEAR notifications + if(unlikely(ae->new_status == RRDCALC_STATUS_CLEAR)) { + debug(D_HEALTH, "Health not sending notification for first initialization of alarm '%s.%s' status %s" + , ae->chart, ae->name, rrdcalc_status2string(ae->new_status)); + goto done; + } } } - char buffer[FILENAME_MAX + 1]; + static char command_to_run[ALARM_EXEC_COMMAND_LENGTH + 1]; pid_t command_pid; const char *exec = ae->exec; @@ -2438,7 +2629,7 @@ static inline void health_alarm_execute(RRDHOST *host, ALARM_ENTRY *ae) { const char *recipient = ae->recipient; if(!recipient) recipient = health.health_default_recipient; - snprintfz(buffer, FILENAME_MAX, "exec %s '%s' '%s' '%u' '%u' '%u' '%lu' '%s' '%s' '%s' '%s' '%s' '%0.0Lf' '%0.0Lf' '%s' '%u' '%u' '%s' '%s'", + snprintfz(command_to_run, ALARM_EXEC_COMMAND_LENGTH, "exec %s '%s' '%s' '%u' '%u' '%u' '%lu' '%s' '%s' '%s' '%s' '%s' '%0.0Lf' '%0.0Lf' '%s' '%u' '%u' '%s' '%s'", exec, recipient, host->hostname, @@ -2463,14 +2654,14 @@ static inline void health_alarm_execute(RRDHOST *host, ALARM_ENTRY *ae) { ae->flags |= HEALTH_ENTRY_FLAG_EXEC_RUN; ae->exec_run_timestamp = time(NULL); - debug(D_HEALTH, "executing command '%s'", buffer); - FILE *fp = mypopen(buffer, &command_pid); + debug(D_HEALTH, "executing command '%s'", command_to_run); + FILE *fp = mypopen(command_to_run, &command_pid); if(!fp) { - error("HEALTH: Cannot popen(\"%s\", \"r\").", buffer); + error("HEALTH: Cannot popen(\"%s\", \"r\").", command_to_run); goto done; } debug(D_HEALTH, "HEALTH reading from command"); - char *s = fgets(buffer, FILENAME_MAX, fp); + char *s = fgets(command_to_run, FILENAME_MAX, fp); (void)s; ae->exec_code = mypclose(fp, command_pid); debug(D_HEALTH, "done executing command - returned with code %d", ae->exec_code); @@ -2559,34 +2750,55 @@ static inline void health_alarm_log_process(RRDHOST *host) { } static inline int rrdcalc_isrunnable(RRDCALC *rc, time_t now, time_t *next_run) { - if (unlikely(!rc->rrdset)) { + if(unlikely(!rc->rrdset)) { debug(D_HEALTH, "Health not running alarm '%s.%s'. It is not linked to a chart.", rc->chart?rc->chart:"NOCHART", rc->name); return 0; } - if (unlikely(!rc->rrdset->last_collected_time.tv_sec)) { - debug(D_HEALTH, "Health not running alarm '%s.%s'. Chart is not yet collected.", rc->chart?rc->chart:"NOCHART", rc->name); + if(unlikely(rc->next_update > now)) { + if (unlikely(*next_run > rc->next_update)) { + // update the next_run time of the main loop + // to run this alarm precisely the time required + *next_run = rc->next_update; + } + + debug(D_HEALTH, "Health not examining alarm '%s.%s' yet (will do in %d secs).", rc->chart?rc->chart:"NOCHART", rc->name, (int) (rc->next_update - now)); return 0; } - if (unlikely(!rc->update_every)) { + if(unlikely(!rc->update_every)) { debug(D_HEALTH, "Health not running alarm '%s.%s'. It does not have an update frequency", rc->chart?rc->chart:"NOCHART", rc->name); return 0; } - if (unlikely(rc->next_update > now)) { - if (unlikely(*next_run > rc->next_update)) - *next_run = rc->next_update; + if(unlikely(!rc->rrdset->last_collected_time.tv_sec || rc->rrdset->counter_done < 2)) { + debug(D_HEALTH, "Health not running alarm '%s.%s'. Chart is not fully collected yet.", rc->chart?rc->chart:"NOCHART", rc->name); + return 0; + } - debug(D_HEALTH, "Health not examining alarm '%s.%s' yet (will do in %d secs).", rc->chart?rc->chart:"NOCHART", rc->name, (int) (rc->next_update - now)); + int update_every = rc->rrdset->update_every; + time_t first = rrdset_first_entry_t(rc->rrdset); + time_t last = rrdset_last_entry_t(rc->rrdset); + + if(unlikely(now + update_every < first /* || now - update_every > last */)) { + debug(D_HEALTH + , "Health not examining alarm '%s.%s' yet (wanted time is out of bounds - we need %lu but got %lu - %lu)." + , rc->chart ? rc->chart : "NOCHART", rc->name, (unsigned long) now, (unsigned long) first + , (unsigned long) last); return 0; } - // FIXME - // we should check that the DB lookup is possible - // i.e. - // - the duration of the chart includes the required timeframe - // we SHOULD NOT check the dimensions - there might be alarms that refer non-existing dimensions (e.g. cpu steal) + if(RRDCALC_HAS_DB_LOOKUP(rc)) { + time_t needed = now + rc->before + rc->after; + + if(needed + update_every < first || needed - update_every > last) { + debug(D_HEALTH + , "Health not examining alarm '%s.%s' yet (not enough data yet - we need %lu but got %lu - %lu)." + , rc->chart ? rc->chart : "NOCHART", rc->name, (unsigned long) needed, (unsigned long) first + , (unsigned long) last); + return 0; + } + } return 1; } @@ -2617,24 +2829,28 @@ void *health_main(void *ptr) { time_t next_run = now + min_run_every; RRDCALC *rc; - if (unlikely(pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &oldstate) != 0)) + if(unlikely(pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &oldstate) != 0)) error("Cannot set pthread cancel state to DISABLE."); rrdhost_rdlock(&localhost); // the first loop is to lookup values from the db - for (rc = localhost.alarms; rc; rc = rc->next) { - if (unlikely(!rrdcalc_isrunnable(rc, now, &next_run))) + for(rc = localhost.alarms; rc; rc = rc->next) { + if(unlikely(!rrdcalc_isrunnable(rc, now, &next_run))) { + if(unlikely(rc->rrdcalc_flags & RRDCALC_FLAG_RUNNABLE)) + rc->rrdcalc_flags &= ~RRDCALC_FLAG_RUNNABLE; continue; + } runnable++; rc->old_value = rc->value; + rc->rrdcalc_flags |= RRDCALC_FLAG_RUNNABLE; // 1. if there is database lookup, do it // 2. if there is calculation expression, run it if (unlikely(RRDCALC_HAS_DB_LOOKUP(rc))) { - time_t old_db_timestamp = rc->db_before; + /* time_t old_db_timestamp = rc->db_before; */ int value_is_null = 0; int ret = rrd2value(rc->rrdset, wb, &rc->value, @@ -2655,6 +2871,7 @@ void *health_main(void *ptr) { else if (unlikely(rc->rrdcalc_flags & RRDCALC_FLAG_DB_ERROR)) rc->rrdcalc_flags &= ~RRDCALC_FLAG_DB_ERROR; + /* - RRDCALC_FLAG_DB_STALE not currently used if (unlikely(old_db_timestamp == rc->db_before)) { // database is stale @@ -2667,6 +2884,7 @@ void *health_main(void *ptr) { } else if (unlikely(rc->rrdcalc_flags & RRDCALC_FLAG_DB_STALE)) rc->rrdcalc_flags &= ~RRDCALC_FLAG_DB_STALE; + */ if (unlikely(value_is_null)) { // collected value is null @@ -2695,23 +2913,24 @@ void *health_main(void *ptr) { rc->value = NAN; - debug(D_HEALTH, "Health alarm '%s.%s': failed to evaluate calculation with error: %s", - rc->chart?rc->chart:"NOCHART", rc->name, buffer_tostring(rc->calculation->error_msg)); + debug(D_HEALTH, "Health alarm '%s.%s': expression '%s' failed: %s", + rc->chart?rc->chart:"NOCHART", rc->name, rc->calculation->parsed_as, buffer_tostring(rc->calculation->error_msg)); if (unlikely(!(rc->rrdcalc_flags & RRDCALC_FLAG_CALC_ERROR))) { rc->rrdcalc_flags |= RRDCALC_FLAG_CALC_ERROR; - error("Health alarm '%s.%s': failed to evaluate calculation with error: %s", - rc->chart?rc->chart:"NOCHART", rc->name, buffer_tostring(rc->calculation->error_msg)); + error("Health alarm '%s.%s': expression '%s' failed: %s", + rc->chart?rc->chart:"NOCHART", rc->name, rc->calculation->parsed_as, buffer_tostring(rc->calculation->error_msg)); } } else { if (unlikely(rc->rrdcalc_flags & RRDCALC_FLAG_CALC_ERROR)) rc->rrdcalc_flags &= ~RRDCALC_FLAG_CALC_ERROR; - debug(D_HEALTH, "Health alarm '%s.%s': calculation expression gave value " + debug(D_HEALTH, "Health alarm '%s.%s': expression '%s' gave value " CALCULATED_NUMBER_FORMAT ": %s (source: %s)", rc->chart?rc->chart:"NOCHART", rc->name, + rc->calculation->parsed_as, rc->calculation->result, buffer_tostring(rc->calculation->error_msg), rc->source @@ -2723,11 +2942,11 @@ void *health_main(void *ptr) { } rrdhost_unlock(&localhost); - if (unlikely(runnable && !netdata_exit)) { + if(unlikely(runnable && !netdata_exit)) { rrdhost_rdlock(&localhost); - for (rc = localhost.alarms; rc; rc = rc->next) { - if (unlikely(!rrdcalc_isrunnable(rc, now, &next_run))) + for(rc = localhost.alarms; rc; rc = rc->next) { + if(unlikely(!(rc->rrdcalc_flags & RRDCALC_FLAG_RUNNABLE))) continue; int warning_status = RRDCALC_STATUS_UNDEFINED; diff --git a/src/health.h b/src/health.h index cebea49b..10885c62 100644 --- a/src/health.h +++ b/src/health.h @@ -5,11 +5,13 @@ extern int health_enabled; extern int rrdvar_compare(void *a, void *b); -#define RRDVAR_TYPE_CALCULATED 1 -#define RRDVAR_TYPE_TIME_T 2 -#define RRDVAR_TYPE_COLLECTED 3 -#define RRDVAR_TYPE_TOTAL 4 -#define RRDVAR_TYPE_INT 5 +#define RRDVAR_TYPE_CALCULATED 1 +#define RRDVAR_TYPE_TIME_T 2 +#define RRDVAR_TYPE_COLLECTED 3 +#define RRDVAR_TYPE_TOTAL 4 +#define RRDVAR_TYPE_INT 5 +#define RRDVAR_TYPE_CALCULATED_ALLOCATED 6 + // the variables as stored in the variables indexes // there are 3 indexes: @@ -34,8 +36,8 @@ typedef struct rrdvar { // This means, there will be no speed penalty for using // these variables typedef struct rrdsetvar { - char *fullid; // chart type.chart id.variable - char *fullname; // chart type.chart name.variable + char *key_fullid; // chart type.chart id.variable + char *key_fullname; // chart type.chart name.variable char *variable; // variable int type; @@ -43,11 +45,11 @@ typedef struct rrdsetvar { uint32_t options; - RRDVAR *local; - RRDVAR *family; - RRDVAR *host; - RRDVAR *family_name; - RRDVAR *host_name; + RRDVAR *var_local; + RRDVAR *var_family; + RRDVAR *var_host; + RRDVAR *var_family_name; + RRDVAR *var_host_name; struct rrdset *rrdset; @@ -64,28 +66,32 @@ typedef struct rrddimvar { char *prefix; char *suffix; - char *id; // dimension id - char *name; // dimension name - char *fullidid; // chart type.chart id.dimension id - char *fullidname; // chart type.chart id.dimension name - char *fullnameid; // chart type.chart name.dimension id - char *fullnamename; // chart type.chart name.dimension name + char *key_id; // dimension id + char *key_name; // dimension name + char *key_contextid; // context + dimension id + char *key_contextname; // context + dimension name + char *key_fullidid; // chart type.chart id + dimension id + char *key_fullidname; // chart type.chart id + dimension name + char *key_fullnameid; // chart type.chart name + dimension id + char *key_fullnamename; // chart type.chart name + dimension name int type; void *value; uint32_t options; - RRDVAR *local_id; - RRDVAR *local_name; + RRDVAR *var_local_id; + RRDVAR *var_local_name; - RRDVAR *family_id; - RRDVAR *family_name; + RRDVAR *var_family_id; + RRDVAR *var_family_name; + RRDVAR *var_family_contextid; + RRDVAR *var_family_contextname; - RRDVAR *host_fullidid; - RRDVAR *host_fullidname; - RRDVAR *host_fullnameid; - RRDVAR *host_fullnamename; + RRDVAR *var_host_chartidid; + RRDVAR *var_host_chartidname; + RRDVAR *var_host_chartnameid; + RRDVAR *var_host_chartnamename; struct rrddim *rrddim; @@ -115,10 +121,11 @@ typedef struct rrddimvar { #define RRDCALC_FLAG_DB_ERROR 0x00000001 #define RRDCALC_FLAG_DB_NAN 0x00000002 -#define RRDCALC_FLAG_DB_STALE 0x00000004 +/* #define RRDCALC_FLAG_DB_STALE 0x00000004 */ #define RRDCALC_FLAG_CALC_ERROR 0x00000008 #define RRDCALC_FLAG_WARN_ERROR 0x00000010 #define RRDCALC_FLAG_CRIT_ERROR 0x00000020 +#define RRDCALC_FLAG_RUNNABLE 0x00000040 typedef struct rrdcalc { uint32_t id; // the unique id of this alarm @@ -345,4 +352,10 @@ extern int health_variable_lookup(const char *variable, uint32_t hash, RRDCALC * extern void health_alarms2json(RRDHOST *host, BUFFER *wb, int all); extern void health_alarm_log2json(RRDHOST *host, BUFFER *wb, uint32_t after); +void health_api_v1_chart_variables2json(RRDSET *st, BUFFER *buf); + +extern RRDVAR *rrdvar_custom_host_variable_create(RRDHOST *host, const char *name); +extern void rrdvar_custom_host_variable_destroy(RRDHOST *host, const char *name); +extern void rrdvar_custom_host_variable_set(RRDVAR *rv, calculated_number value); + #endif //NETDATA_HEALTH_H diff --git a/src/ipc.c b/src/ipc.c new file mode 100644 index 00000000..3cf76513 --- /dev/null +++ b/src/ipc.c @@ -0,0 +1,238 @@ +#include "common.h" + +#include +#include +#include + + +#ifndef SEMVMX +#define SEMVMX 32767 /* <= 32767 semaphore maximum value */ +#endif + +/* Some versions of libc only define IPC_INFO when __USE_GNU is defined. */ +#ifndef IPC_INFO +#define IPC_INFO 3 +#endif + +struct ipc_limits { + uint64_t shmmni; /* max number of segments */ + uint64_t shmmax; /* max segment size */ + uint64_t shmall; /* max total shared memory */ + uint64_t shmmin; /* min segment size */ + + int semmni; /* max number of arrays */ + int semmsl; /* max semaphores per array */ + int semmns; /* max semaphores system wide */ + int semopm; /* max ops per semop call */ + unsigned int semvmx; /* semaphore max value (constant) */ + + int msgmni; /* max queues system wide */ + size_t msgmax; /* max size of message */ + int msgmnb; /* default max size of queue */ +}; + +struct ipc_status { + int semusz; /* current number of arrays */ + int semaem; /* current semaphores system wide */ +}; + +/* + * The last arg of semctl is a union semun, but where is it defined? X/OPEN + * tells us to define it ourselves, but until recently Linux include files + * would also define it. + */ +#ifndef HAVE_UNION_SEMUN +/* according to X/OPEN we have to define it ourselves */ +union semun { + int val; + struct semid_ds *buf; + unsigned short int *array; + struct seminfo *__buf; +}; +#endif + +static inline int ipc_sem_get_limits(struct ipc_limits *lim) { + static procfile *ff = NULL; + static int error_shown = 0; + static char filename[FILENAME_MAX + 1] = ""; + + if(unlikely(!filename[0])) + snprintfz(filename, FILENAME_MAX, "%s/proc/sys/kernel/sem", global_host_prefix); + + if(unlikely(!ff)) { + ff = procfile_open(filename, NULL, PROCFILE_FLAG_DEFAULT); + if(unlikely(!ff)) { + if(unlikely(!error_shown)) { + error("IPC: Cannot open file '%s'.", filename); + error_shown = 1; + } + goto ipc; + } + } + + ff = procfile_readall(ff); + if(unlikely(!ff)) { + if(unlikely(!error_shown)) { + error("IPC: Cannot read file '%s'.", filename); + error_shown = 1; + } + goto ipc; + } + + if(procfile_lines(ff) >= 1 && procfile_linewords(ff, 0) >= 4) { + lim->semvmx = SEMVMX; + lim->semmsl = atoi(procfile_lineword(ff, 0, 0)); + lim->semmns = atoi(procfile_lineword(ff, 0, 1)); + lim->semopm = atoi(procfile_lineword(ff, 0, 2)); + lim->semmni = atoi(procfile_lineword(ff, 0, 3)); + return 0; + } + else { + if(unlikely(!error_shown)) { + error("IPC: Invalid content in file '%s'.", filename); + error_shown = 1; + } + goto ipc; + } + +ipc: + // cannot do it from the file + // query IPC + { + struct seminfo seminfo = {.semmni = 0}; + union semun arg = {.array = (ushort *) &seminfo}; + + if(unlikely(semctl(0, 0, IPC_INFO, arg) < 0)) { + error("IPC: Failed to read '%s' and request IPC_INFO with semctl().", filename); + goto error; + } + + lim->semvmx = SEMVMX; + lim->semmni = seminfo.semmni; + lim->semmsl = seminfo.semmsl; + lim->semmns = seminfo.semmns; + lim->semopm = seminfo.semopm; + return 0; + } + +error: + lim->semvmx = 0; + lim->semmni = 0; + lim->semmsl = 0; + lim->semmns = 0; + lim->semopm = 0; + return -1; +} + +/* +printf ("------ Semaphore Limits --------\n"); +printf ("max number of arrays = %d\n", limits.semmni); +printf ("max semaphores per array = %d\n", limits.semmsl); +printf ("max semaphores system wide = %d\n", limits.semmns); +printf ("max ops per semop call = %d\n", limits.semopm); +printf ("semaphore max value = %u\n", limits.semvmx); + +printf ("------ Semaphore Status --------\n"); +printf ("used arrays = %d\n", status.semusz); +printf ("allocated semaphores = %d\n", status.semaem); +*/ + +static inline int ipc_sem_get_status(struct ipc_status *st) { + struct seminfo seminfo; + union semun arg; + + arg.array = (ushort *) (void *) &seminfo; + + if(unlikely(semctl (0, 0, SEM_INFO, arg) < 0)) { + /* kernel not configured for semaphores */ + static int error_shown = 0; + if(unlikely(!error_shown)) { + error("IPC: kernel is not configured for semaphores"); + error_shown = 1; + } + st->semusz = 0; + st->semaem = 0; + return -1; + } + + st->semusz = seminfo.semusz; + st->semaem = seminfo.semaem; + return 0; +} + +int do_ipc(int update_every, unsigned long long dt) { + (void)dt; + + static int initialized = 0, read_limits_next = 0; + static struct ipc_limits limits; + static struct ipc_status status; + static RRDVAR *arrays_max = NULL, *semaphores_max = NULL; + static RRDSET *semaphores = NULL, *arrays = NULL; + + if(unlikely(!initialized)) { + initialized = 1; + + // make sure it works + if(ipc_sem_get_limits(&limits) == -1) { + error("unable to fetch semaphore limits"); + return 1; + } + + // make sure it works + if(ipc_sem_get_status(&status) == -1) { + error("unable to fetch semaphore statistics"); + return 1; + } + + arrays_max = rrdvar_custom_host_variable_create(&localhost, "ipc.semaphores.arrays.max"); + semaphores_max = rrdvar_custom_host_variable_create(&localhost, "ipc.semaphores.max"); + + if(arrays_max) rrdvar_custom_host_variable_set(arrays_max, limits.semmni); + if(semaphores_max) rrdvar_custom_host_variable_set(semaphores_max, limits.semmns); + + // create the charts + semaphores = rrdset_find("system.ipc_semaphores"); + if(!semaphores) { + semaphores = rrdset_create("system", "ipc_semaphores", NULL, "ipc semaphores", NULL, "IPC Semaphores", "semaphores", 1000, rrd_update_every, RRDSET_TYPE_AREA); + rrddim_add(semaphores, "semaphores", NULL, 1, 1, RRDDIM_ABSOLUTE); + } + + arrays = rrdset_find("system.ipc_semaphore_arrays"); + if(!arrays) { + arrays = rrdset_create("system", "ipc_semaphore_arrays", NULL, "ipc semaphores", NULL, "IPC Semaphore Arrays", "arrays", 1000, rrd_update_every, RRDSET_TYPE_AREA); + rrddim_add(arrays, "arrays", NULL, 1, 1, RRDDIM_ABSOLUTE); + } + } + + if(unlikely(read_limits_next < 0)) { + if(unlikely(ipc_sem_get_limits(&limits) == -1)) { + error("Unable to fetch semaphore limits."); + } + else { + rrdvar_custom_host_variable_set(arrays_max, limits.semmni); + rrdvar_custom_host_variable_set(semaphores_max, limits.semmns); + + arrays->red = limits.semmni; + semaphores->red = limits.semmns; + + read_limits_next = 60 / update_every; + } + } + else + read_limits_next--; + + if(unlikely(ipc_sem_get_status(&status) == -1)) { + error("Unable to get semaphore statistics"); + return 0; + } + + if(semaphores->counter_done) rrdset_next(semaphores); + rrddim_set(semaphores, "semaphores", status.semaem); + rrdset_done(semaphores); + + if(arrays->counter_done) rrdset_next(arrays); + rrddim_set(arrays, "arrays", status.semusz); + rrdset_done(arrays); + + return 0; +} diff --git a/src/ipc.h b/src/ipc.h new file mode 100644 index 00000000..3762a69d --- /dev/null +++ b/src/ipc.h @@ -0,0 +1,7 @@ +#ifndef NETDATA_PLUGIN_IPC_H +#define NETDATA_PLUGIN_IPC_H 1 + +extern int do_ipc(int update_every, unsigned long long dt); + +#endif /* NETDATA_PLUGIN_IPC_H */ + diff --git a/src/log.c b/src/log.c index 86716987..bf2ad6b3 100644 --- a/src/log.c +++ b/src/log.c @@ -24,7 +24,7 @@ void syslog_init(void) { } int open_log_file(int fd, FILE **fp, const char *filename, int *enabled_syslog) { - int f, t; + int f; if(!filename || !*filename || !strcmp(filename, "none")) filename = "/dev/null"; @@ -64,7 +64,7 @@ int open_log_file(int fd, FILE **fp, const char *filename, int *enabled_syslog) if(fd != f && fd != -1) { // it automatically closes - t = dup2(f, fd); + int t = dup2(f, fd); if (t == -1) { error("Cannot dup2() new fd %d to old fd %d for '%s'", f, fd, filename); close(f); diff --git a/src/main.c b/src/main.c index 1a819938..695c98e3 100644 --- a/src/main.c +++ b/src/main.c @@ -643,7 +643,7 @@ int main(int argc, char **argv) // fork, switch user, create pid file, set process priority if(become_daemon(dont_fork, user) == -1) - fatal("Cannot demonize myself."); + fatal("Cannot daemonize myself."); info("NetData started on pid %d", getpid()); diff --git a/src/plugin_idlejitter.c b/src/plugin_idlejitter.c index 30c6d870..a9b340ab 100644 --- a/src/plugin_idlejitter.c +++ b/src/plugin_idlejitter.c @@ -34,7 +34,7 @@ void *cpuidlejitter_main(void *ptr) while(susec < (rrd_update_every * 1000000ULL)) { gettimeofday(&before, NULL); - usleep(sleep_ms * 1000); + sleep_usec(sleep_ms * 1000); gettimeofday(&after, NULL); // calculate the time it took for a full loop diff --git a/src/plugin_proc.c b/src/plugin_proc.c index a50a2251..1aa2fb58 100644 --- a/src/plugin_proc.c +++ b/src/plugin_proc.c @@ -35,6 +35,7 @@ void *proc_main(void *ptr) int vdo_proc_softirqs = !config_get_boolean("plugin:proc", "/proc/softirqs", 1); int vdo_proc_net_softnet_stat = !config_get_boolean("plugin:proc", "/proc/net/softnet_stat", 1); int vdo_proc_loadavg = !config_get_boolean("plugin:proc", "/proc/loadavg", 1); + int vdo_ipc = !config_get_boolean("plugin:proc", "ipc", 1); int vdo_sys_kernel_mm_ksm = !config_get_boolean("plugin:proc", "/sys/kernel/mm/ksm", 1); int vdo_cpu_netdata = !config_get_boolean("plugin:proc", "netdata server resources", 1); @@ -57,22 +58,18 @@ void *proc_main(void *ptr) unsigned long long sutime_proc_softirqs = 0ULL; unsigned long long sutime_proc_net_softnet_stat = 0ULL; unsigned long long sutime_proc_loadavg = 0ULL; + unsigned long long sutime_ipc = 0ULL; unsigned long long sutime_sys_kernel_mm_ksm = 0ULL; - // the next time we will run - aligned properly - unsigned long long sunext = (time(NULL) - (time(NULL) % rrd_update_every) + rrd_update_every) * 1000000ULL; - unsigned long long sunow; - + unsigned long long step = rrd_update_every * 1000000ULL; for(;;) { - if(unlikely(netdata_exit)) break; + unsigned long long now = time_usec(); + unsigned long long next = now - (now % step) + step; - // delay until it is our time to run - while((sunow = time_usec()) < sunext) - sleep_usec(sunext - sunow); - - // find the next time we need to run - while(time_usec() > sunext) - sunext += rrd_update_every * 1000000ULL; + while(now < next) { + sleep_usec(next - now); + now = time_usec(); + } if(unlikely(netdata_exit)) break; @@ -81,153 +78,161 @@ void *proc_main(void *ptr) if(!vdo_sys_kernel_mm_ksm) { debug(D_PROCNETDEV_LOOP, "PROCNETDEV: calling do_sys_kernel_mm_ksm()."); - sunow = time_usec(); - vdo_sys_kernel_mm_ksm = do_sys_kernel_mm_ksm(rrd_update_every, (sutime_sys_kernel_mm_ksm > 0)?sunow - sutime_sys_kernel_mm_ksm:0ULL); - sutime_sys_kernel_mm_ksm = sunow; + now = time_usec(); + vdo_sys_kernel_mm_ksm = do_sys_kernel_mm_ksm(rrd_update_every, (sutime_sys_kernel_mm_ksm > 0)?now - sutime_sys_kernel_mm_ksm:0ULL); + sutime_sys_kernel_mm_ksm = now; } if(unlikely(netdata_exit)) break; if(!vdo_proc_loadavg) { debug(D_PROCNETDEV_LOOP, "PROCNETDEV: calling do_proc_loadavg()."); - sunow = time_usec(); - vdo_proc_loadavg = do_proc_loadavg(rrd_update_every, (sutime_proc_loadavg > 0)?sunow - sutime_proc_loadavg:0ULL); - sutime_proc_loadavg = sunow; + now = time_usec(); + vdo_proc_loadavg = do_proc_loadavg(rrd_update_every, (sutime_proc_loadavg > 0)?now - sutime_proc_loadavg:0ULL); + sutime_proc_loadavg = now; + } + if(unlikely(netdata_exit)) break; + + if(!vdo_ipc) { + debug(D_PROCNETDEV_LOOP, "PROCNETDEV: calling do_ipc()."); + now = time_usec(); + vdo_ipc = do_ipc(rrd_update_every, (sutime_ipc > 0)?now - sutime_ipc:0ULL); + sutime_ipc = now; } if(unlikely(netdata_exit)) break; if(!vdo_proc_interrupts) { debug(D_PROCNETDEV_LOOP, "PROCNETDEV: calling do_proc_interrupts()."); - sunow = time_usec(); - vdo_proc_interrupts = do_proc_interrupts(rrd_update_every, (sutime_proc_interrupts > 0)?sunow - sutime_proc_interrupts:0ULL); - sutime_proc_interrupts = sunow; + now = time_usec(); + vdo_proc_interrupts = do_proc_interrupts(rrd_update_every, (sutime_proc_interrupts > 0)?now - sutime_proc_interrupts:0ULL); + sutime_proc_interrupts = now; } if(unlikely(netdata_exit)) break; if(!vdo_proc_softirqs) { debug(D_PROCNETDEV_LOOP, "PROCNETDEV: calling do_proc_softirqs()."); - sunow = time_usec(); - vdo_proc_softirqs = do_proc_softirqs(rrd_update_every, (sutime_proc_softirqs > 0)?sunow - sutime_proc_softirqs:0ULL); - sutime_proc_softirqs = sunow; + now = time_usec(); + vdo_proc_softirqs = do_proc_softirqs(rrd_update_every, (sutime_proc_softirqs > 0)?now - sutime_proc_softirqs:0ULL); + sutime_proc_softirqs = now; } if(unlikely(netdata_exit)) break; if(!vdo_proc_net_softnet_stat) { debug(D_PROCNETDEV_LOOP, "PROCNETDEV: calling do_proc_net_softnet_stat()."); - sunow = time_usec(); - vdo_proc_net_softnet_stat = do_proc_net_softnet_stat(rrd_update_every, (sutime_proc_net_softnet_stat > 0)?sunow - sutime_proc_net_softnet_stat:0ULL); - sutime_proc_net_softnet_stat = sunow; + now = time_usec(); + vdo_proc_net_softnet_stat = do_proc_net_softnet_stat(rrd_update_every, (sutime_proc_net_softnet_stat > 0)?now - sutime_proc_net_softnet_stat:0ULL); + sutime_proc_net_softnet_stat = now; } if(unlikely(netdata_exit)) break; if(!vdo_proc_sys_kernel_random_entropy_avail) { debug(D_PROCNETDEV_LOOP, "PROCNETDEV: calling do_proc_sys_kernel_random_entropy_avail()."); - sunow = time_usec(); - vdo_proc_sys_kernel_random_entropy_avail = do_proc_sys_kernel_random_entropy_avail(rrd_update_every, (sutime_proc_sys_kernel_random_entropy_avail > 0)?sunow - sutime_proc_sys_kernel_random_entropy_avail:0ULL); - sutime_proc_sys_kernel_random_entropy_avail = sunow; + now = time_usec(); + vdo_proc_sys_kernel_random_entropy_avail = do_proc_sys_kernel_random_entropy_avail(rrd_update_every, (sutime_proc_sys_kernel_random_entropy_avail > 0)?now - sutime_proc_sys_kernel_random_entropy_avail:0ULL); + sutime_proc_sys_kernel_random_entropy_avail = now; } if(unlikely(netdata_exit)) break; if(!vdo_proc_net_dev) { debug(D_PROCNETDEV_LOOP, "PROCNETDEV: calling do_proc_net_dev()."); - sunow = time_usec(); - vdo_proc_net_dev = do_proc_net_dev(rrd_update_every, (sutime_proc_net_dev > 0)?sunow - sutime_proc_net_dev:0ULL); - sutime_proc_net_dev = sunow; + now = time_usec(); + vdo_proc_net_dev = do_proc_net_dev(rrd_update_every, (sutime_proc_net_dev > 0)?now - sutime_proc_net_dev:0ULL); + sutime_proc_net_dev = now; } if(unlikely(netdata_exit)) break; if(!vdo_proc_diskstats) { debug(D_PROCNETDEV_LOOP, "PROCNETDEV: calling do_proc_diskstats()."); - sunow = time_usec(); - vdo_proc_diskstats = do_proc_diskstats(rrd_update_every, (sutime_proc_diskstats > 0)?sunow - sutime_proc_diskstats:0ULL); - sutime_proc_diskstats = sunow; + now = time_usec(); + vdo_proc_diskstats = do_proc_diskstats(rrd_update_every, (sutime_proc_diskstats > 0)?now - sutime_proc_diskstats:0ULL); + sutime_proc_diskstats = now; } if(unlikely(netdata_exit)) break; if(!vdo_proc_net_snmp) { debug(D_PROCNETDEV_LOOP, "PROCNETDEV: calling do_proc_net_snmp()."); - sunow = time_usec(); - vdo_proc_net_snmp = do_proc_net_snmp(rrd_update_every, (sutime_proc_net_snmp > 0)?sunow - sutime_proc_net_snmp:0ULL); - sutime_proc_net_snmp = sunow; + now = time_usec(); + vdo_proc_net_snmp = do_proc_net_snmp(rrd_update_every, (sutime_proc_net_snmp > 0)?now - sutime_proc_net_snmp:0ULL); + sutime_proc_net_snmp = now; } if(unlikely(netdata_exit)) break; if(!vdo_proc_net_snmp6) { debug(D_PROCNETDEV_LOOP, "PROCNETDEV: calling do_proc_net_snmp6()."); - sunow = time_usec(); - vdo_proc_net_snmp6 = do_proc_net_snmp6(rrd_update_every, (sutime_proc_net_snmp6 > 0)?sunow - sutime_proc_net_snmp6:0ULL); - sutime_proc_net_snmp6 = sunow; + now = time_usec(); + vdo_proc_net_snmp6 = do_proc_net_snmp6(rrd_update_every, (sutime_proc_net_snmp6 > 0)?now - sutime_proc_net_snmp6:0ULL); + sutime_proc_net_snmp6 = now; } if(unlikely(netdata_exit)) break; if(!vdo_proc_net_netstat) { debug(D_PROCNETDEV_LOOP, "PROCNETDEV: calling do_proc_net_netstat()."); - sunow = time_usec(); - vdo_proc_net_netstat = do_proc_net_netstat(rrd_update_every, (sutime_proc_net_netstat > 0)?sunow - sutime_proc_net_netstat:0ULL); - sutime_proc_net_netstat = sunow; + now = time_usec(); + vdo_proc_net_netstat = do_proc_net_netstat(rrd_update_every, (sutime_proc_net_netstat > 0)?now - sutime_proc_net_netstat:0ULL); + sutime_proc_net_netstat = now; } if(unlikely(netdata_exit)) break; if(!vdo_proc_net_stat_conntrack) { debug(D_PROCNETDEV_LOOP, "PROCNETDEV: calling do_proc_net_stat_conntrack()."); - sunow = time_usec(); - vdo_proc_net_stat_conntrack = do_proc_net_stat_conntrack(rrd_update_every, (sutime_proc_net_stat_conntrack > 0)?sunow - sutime_proc_net_stat_conntrack:0ULL); - sutime_proc_net_stat_conntrack = sunow; + now = time_usec(); + vdo_proc_net_stat_conntrack = do_proc_net_stat_conntrack(rrd_update_every, (sutime_proc_net_stat_conntrack > 0)?now - sutime_proc_net_stat_conntrack:0ULL); + sutime_proc_net_stat_conntrack = now; } if(unlikely(netdata_exit)) break; if(!vdo_proc_net_ip_vs_stats) { debug(D_PROCNETDEV_LOOP, "PROCNETDEV: calling vdo_proc_net_ip_vs_stats()."); - sunow = time_usec(); - vdo_proc_net_ip_vs_stats = do_proc_net_ip_vs_stats(rrd_update_every, (sutime_proc_net_ip_vs_stats > 0)?sunow - sutime_proc_net_ip_vs_stats:0ULL); - sutime_proc_net_ip_vs_stats = sunow; + now = time_usec(); + vdo_proc_net_ip_vs_stats = do_proc_net_ip_vs_stats(rrd_update_every, (sutime_proc_net_ip_vs_stats > 0)?now - sutime_proc_net_ip_vs_stats:0ULL); + sutime_proc_net_ip_vs_stats = now; } if(unlikely(netdata_exit)) break; if(!vdo_proc_net_stat_synproxy) { debug(D_PROCNETDEV_LOOP, "PROCNETDEV: calling vdo_proc_net_stat_synproxy()."); - sunow = time_usec(); - vdo_proc_net_stat_synproxy = do_proc_net_stat_synproxy(rrd_update_every, (sutime_proc_net_stat_synproxy > 0)?sunow - sutime_proc_net_stat_synproxy:0ULL); - sutime_proc_net_stat_synproxy = sunow; + now = time_usec(); + vdo_proc_net_stat_synproxy = do_proc_net_stat_synproxy(rrd_update_every, (sutime_proc_net_stat_synproxy > 0)?now - sutime_proc_net_stat_synproxy:0ULL); + sutime_proc_net_stat_synproxy = now; } if(unlikely(netdata_exit)) break; if(!vdo_proc_stat) { debug(D_PROCNETDEV_LOOP, "PROCNETDEV: calling do_proc_stat()."); - sunow = time_usec(); - vdo_proc_stat = do_proc_stat(rrd_update_every, (sutime_proc_stat > 0)?sunow - sutime_proc_stat:0ULL); - sutime_proc_stat = sunow; + now = time_usec(); + vdo_proc_stat = do_proc_stat(rrd_update_every, (sutime_proc_stat > 0)?now - sutime_proc_stat:0ULL); + sutime_proc_stat = now; } if(unlikely(netdata_exit)) break; if(!vdo_proc_meminfo) { debug(D_PROCNETDEV_LOOP, "PROCNETDEV: calling vdo_proc_meminfo()."); - sunow = time_usec(); - vdo_proc_meminfo = do_proc_meminfo(rrd_update_every, (sutime_proc_meminfo > 0)?sunow - sutime_proc_meminfo:0ULL); - sutime_proc_meminfo = sunow; + now = time_usec(); + vdo_proc_meminfo = do_proc_meminfo(rrd_update_every, (sutime_proc_meminfo > 0)?now - sutime_proc_meminfo:0ULL); + sutime_proc_meminfo = now; } if(unlikely(netdata_exit)) break; if(!vdo_proc_vmstat) { debug(D_PROCNETDEV_LOOP, "PROCNETDEV: calling vdo_proc_vmstat()."); - sunow = time_usec(); - vdo_proc_vmstat = do_proc_vmstat(rrd_update_every, (sutime_proc_vmstat > 0)?sunow - sutime_proc_vmstat:0ULL); - sutime_proc_vmstat = sunow; + now = time_usec(); + vdo_proc_vmstat = do_proc_vmstat(rrd_update_every, (sutime_proc_vmstat > 0)?now - sutime_proc_vmstat:0ULL); + sutime_proc_vmstat = now; } if(unlikely(netdata_exit)) break; if(!vdo_proc_net_rpc_nfsd) { debug(D_PROCNETDEV_LOOP, "PROCNETDEV: calling do_proc_net_rpc_nfsd()."); - sunow = time_usec(); - vdo_proc_net_rpc_nfsd = do_proc_net_rpc_nfsd(rrd_update_every, (sutime_proc_net_rpc_nfsd > 0)?sunow - sutime_proc_net_rpc_nfsd:0ULL); - sutime_proc_net_rpc_nfsd = sunow; + now = time_usec(); + vdo_proc_net_rpc_nfsd = do_proc_net_rpc_nfsd(rrd_update_every, (sutime_proc_net_rpc_nfsd > 0)?now - sutime_proc_net_rpc_nfsd:0ULL); + sutime_proc_net_rpc_nfsd = now; } if(unlikely(netdata_exit)) break; if(!vdo_proc_net_rpc_nfs) { debug(D_PROCNETDEV_LOOP, "PROCNETDEV: calling do_proc_net_rpc_nfs()."); - sunow = time_usec(); - vdo_proc_net_rpc_nfs = do_proc_net_rpc_nfs(rrd_update_every, (sutime_proc_net_rpc_nfs > 0)?sunow - sutime_proc_net_rpc_nfs:0ULL); - sutime_proc_net_rpc_nfs = sunow; + now = time_usec(); + vdo_proc_net_rpc_nfs = do_proc_net_rpc_nfs(rrd_update_every, (sutime_proc_net_rpc_nfs > 0)?now - sutime_proc_net_rpc_nfs:0ULL); + sutime_proc_net_rpc_nfs = now; } if(unlikely(netdata_exit)) break; diff --git a/src/plugin_tc.c b/src/plugin_tc.c index 399fcd6d..cecadf36 100644 --- a/src/plugin_tc.c +++ b/src/plugin_tc.c @@ -306,7 +306,7 @@ static inline void tc_device_commit(struct tc_device *d) { } else { debug(D_TC_LOOP, "TC: Updating chart for device '%s'", d->name?d->name:d->id); - rrdset_next_plugins(d->st_bytes); + rrdset_next(d->st_bytes); if(unlikely(d->name_updated && d->name && strcmp(d->id, d->name) != 0)) { rrdset_set_name(d->st_bytes, d->name); @@ -367,7 +367,7 @@ static inline void tc_device_commit(struct tc_device *d) { } else { debug(D_TC_LOOP, "TC: Updating _packets chart for device '%s'", d->name?d->name:d->id); - rrdset_next_plugins(d->st_packets); + rrdset_next(d->st_packets); // FIXME // update the family @@ -421,7 +421,7 @@ static inline void tc_device_commit(struct tc_device *d) { } else { debug(D_TC_LOOP, "TC: Updating _dropped chart for device '%s'", d->name?d->name:d->id); - rrdset_next_plugins(d->st_dropped); + rrdset_next(d->st_dropped); // FIXME // update the family @@ -475,7 +475,7 @@ static inline void tc_device_commit(struct tc_device *d) { } else { debug(D_TC_LOOP, "TC: Updating _tokens chart for device '%s'", d->name?d->name:d->id); - rrdset_next_plugins(d->st_tokens); + rrdset_next(d->st_tokens); // FIXME // update the family @@ -529,7 +529,7 @@ static inline void tc_device_commit(struct tc_device *d) { } else { debug(D_TC_LOOP, "TC: Updating _ctokens chart for device '%s'", d->name?d->name:d->id); - rrdset_next_plugins(d->st_ctokens); + rrdset_next(d->st_ctokens); // FIXME // update the family diff --git a/src/plugins_d.c b/src/plugins_d.c index 627e18a3..40536532 100644 --- a/src/plugins_d.c +++ b/src/plugins_d.c @@ -121,7 +121,6 @@ void *pluginsd_worker_thread(void *arg) info("PLUGINSD: '%s' running on pid %d", cd->fullfilename, cd->pid); RRDSET *st = NULL; - char *s; uint32_t hash; while(likely(fgets(line, PLUGINSD_LINE_MAX, fp) != NULL)) { @@ -132,7 +131,7 @@ void *pluginsd_worker_thread(void *arg) // debug(D_PLUGINSD, "PLUGINSD: %s: %s", cd->filename, line); int w = pluginsd_split_words(line, words, MAX_WORDS); - s = words[0]; + char *s = words[0]; if(unlikely(!s || !*s || !w)) { // debug(D_PLUGINSD, "PLUGINSD: empty line"); continue; @@ -189,7 +188,7 @@ void *pluginsd_worker_thread(void *arg) unsigned long long microseconds = 0; if(microseconds_txt && *microseconds_txt) microseconds = strtoull(microseconds_txt, NULL, 10); if(microseconds) rrdset_next_usec(st, microseconds); - else rrdset_next_plugins(st); + else rrdset_next(st); } } else if(likely(hash == END_HASH && !strcmp(s, "END"))) { diff --git a/src/proc_diskstats.c b/src/proc_diskstats.c index 6a5bf0a3..52712c25 100644 --- a/src/proc_diskstats.c +++ b/src/proc_diskstats.c @@ -56,19 +56,99 @@ static inline void mountinfo_reload(int force) { } } + +// linked list of mount points that are by default disabled +static struct excluded_mount_point { + const char *prefix; + size_t len; + struct excluded_mount_point *next; +} *excluded_mount_points = NULL; + +static inline int is_mount_point_excluded(const char *mount_point) { + static int initialized = 0; + + if(unlikely(!initialized)) { + initialized = 1; + + char *a = config_get("plugin:proc:/proc/diskstats", "exclude space metrics on paths", "/var/run/user/ /run/user/"); + if(a && *a) { + char *s = a; + + while(s && *s) { + // skip all spaces + while(isspace(*s)) s++; + + // empty string + if(unlikely(!*s)) break; + + // find the next space + char *c = s; + while(*c && !isspace(*c)) c++; + + char *n; + if(likely(*c)) n = c + 1; + else n = NULL; + + // terminate our string + *c = '\0'; + + // allocate the structure + struct excluded_mount_point *m = mallocz(sizeof(struct excluded_mount_point)); + m->prefix = strdup(s); + m->len = strlen(m->prefix); + m->next = excluded_mount_points; + excluded_mount_points = m; + + // prepare for next loop + s = n; + if(likely(n)) *c = ' '; + } + } + } + + size_t len = strlen(mount_point); + struct excluded_mount_point *m; + for(m = excluded_mount_points; m ; m = m->next) { + if(m->len <= len) { + // fprintf(stderr, "SPACE: comparing '%s' with '%s'\n", mount_point, m->prefix); + if(unlikely(strncmp(m->prefix, mount_point, m->len) == 0)) { + // fprintf(stderr, "SPACE: excluded '%s'\n", mount_point); + return 1; + } + } + } + + // fprintf(stderr, "SPACE: included '%s'\n", mount_point); + return 0; +} + +// Data to be stored in DICTIONARY mount_points used by do_disk_space_stats(). +// This DICTIONARY is used to lookup the settings of the mount point on each iteration. +struct mount_point_metadata { + int do_space; + int do_inodes; +}; + static inline void do_disk_space_stats(struct disk *d, const char *mount_point, const char *mount_source, const char *disk, const char *family, int update_every, unsigned long long dt) { + (void)dt; + + static DICTIONARY *mount_points = NULL; int do_space, do_inodes; - if(d) { + if(unlikely(!mount_points)) { + mount_points = dictionary_create(DICTIONARY_FLAG_SINGLE_THREADED); + } + + if(unlikely(d)) { // verify we collected the metrics for the right disk. // if not the mountpoint has changed. struct stat buff_stat; - if(stat(mount_point, &buff_stat) == -1) { + if(unlikely(stat(mount_point, &buff_stat) == -1)) { error("Failed to stat() for '%s' (disk '%s')", mount_point, disk); return; } - else if(major(buff_stat.st_dev) != d->major || minor(buff_stat.st_dev) != d->minor) { + else if(unlikely(major(buff_stat.st_dev) != d->major || minor(buff_stat.st_dev) != d->minor)) { error("Disk '%s' (disk '%s') switched major:minor", mount_point, disk); freez(d->mount_point); d->mount_point = NULL; @@ -80,25 +160,36 @@ static inline void do_disk_space_stats(struct disk *d, const char *mount_point, do_inodes = d->do_inodes; } else { - char var_name[4096 + 1]; - snprintfz(var_name, 4096, "plugin:proc:/proc/diskstats:%s", mount_point); + struct mount_point_metadata *m = dictionary_get(mount_points, mount_point); + if(unlikely(!m)) { + char var_name[4096 + 1]; + snprintfz(var_name, 4096, "plugin:proc:/proc/diskstats:%s", mount_point); - int def_space = CONFIG_ONDEMAND_ONDEMAND; + int def_space = config_get_boolean_ondemand("plugin:proc:/proc/diskstats", "space usage for all disks", CONFIG_ONDEMAND_ONDEMAND); + int def_inodes = config_get_boolean_ondemand("plugin:proc:/proc/diskstats", "inodes usage for all disks", CONFIG_ONDEMAND_ONDEMAND); - if(unlikely(strncmp(mount_point, "/run/user/", 10) == 0)) - def_space = CONFIG_ONDEMAND_NO; + if(unlikely(is_mount_point_excluded(mount_point))) { + def_space = CONFIG_ONDEMAND_NO; + def_inodes = CONFIG_ONDEMAND_NO; + } - // check the user configuration (this will also show our 'on demand' decision) - def_space = config_get_boolean_ondemand(var_name, "enable space metrics", def_space); + do_space = config_get_boolean_ondemand(var_name, "space usage", def_space); + do_inodes = config_get_boolean_ondemand(var_name, "inodes usage", def_inodes); - int ddo_space = def_space, - ddo_inodes = def_space; + struct mount_point_metadata mp = { + .do_space = do_space, + .do_inodes = do_inodes + }; - do_space = config_get_boolean_ondemand(var_name, "space usage", ddo_space); - do_inodes = config_get_boolean_ondemand(var_name, "inodes usage", ddo_inodes); + dictionary_set(mount_points, mount_point, &mp, sizeof(struct mount_point_metadata)); + } + else { + do_space = m->do_space; + do_inodes = m->do_inodes; + } } - if(do_space == CONFIG_ONDEMAND_NO && do_inodes == CONFIG_ONDEMAND_NO) + if(unlikely(do_space == CONFIG_ONDEMAND_NO && do_inodes == CONFIG_ONDEMAND_NO)) return; struct statvfs buff_statvfs; @@ -144,7 +235,7 @@ static inline void do_disk_space_stats(struct disk *d, const char *mount_point, if(do_space == CONFIG_ONDEMAND_YES || (do_space == CONFIG_ONDEMAND_ONDEMAND && (bavail || breserved_root || bused))) { st = rrdset_find_bytype("disk_space", disk); - if(!st) { + if(unlikely(!st)) { char title[4096 + 1]; snprintfz(title, 4096, "Disk Space Usage for %s [%s]", family, mount_source); st = rrdset_create("disk_space", disk, NULL, family, "disk.space", title, "GB", 2023, update_every, RRDSET_TYPE_STACKED); @@ -153,7 +244,7 @@ static inline void do_disk_space_stats(struct disk *d, const char *mount_point, rrddim_add(st, "used" , NULL, bsize, 1024*1024*1024, RRDDIM_ABSOLUTE); rrddim_add(st, "reserved_for_root", "reserved for root", bsize, 1024*1024*1024, RRDDIM_ABSOLUTE); } - else rrdset_next_usec(st, dt); + else rrdset_next(st); rrddim_set(st, "avail", bavail); rrddim_set(st, "used", bused); @@ -165,7 +256,7 @@ static inline void do_disk_space_stats(struct disk *d, const char *mount_point, if(do_inodes == CONFIG_ONDEMAND_YES || (do_inodes == CONFIG_ONDEMAND_ONDEMAND && (favail || freserved_root || fused))) { st = rrdset_find_bytype("disk_inodes", disk); - if(!st) { + if(unlikely(!st)) { char title[4096 + 1]; snprintfz(title, 4096, "Disk Files (inodes) Usage for %s [%s]", family, mount_source); st = rrdset_create("disk_inodes", disk, NULL, family, "disk.inodes", title, "Inodes", 2024, update_every, RRDSET_TYPE_STACKED); @@ -174,7 +265,7 @@ static inline void do_disk_space_stats(struct disk *d, const char *mount_point, 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_usec(st, dt); + else rrdset_next(st); rrddim_set(st, "avail", favail); rrddim_set(st, "used", fused); @@ -214,7 +305,7 @@ static struct disk *get_disk(unsigned long major, unsigned long minor, char *dis d->next = NULL; // append it to the list - if(!disk_root) + if(unlikely(!disk_root)) disk_root = d; else { struct disk *last; @@ -236,18 +327,19 @@ static struct disk *get_disk(unsigned long major, unsigned long minor, char *dis // find if it is a partition // by checking if /sys/dev/block/MAJOR:MINOR/partition is readable. snprintfz(buffer, FILENAME_MAX, path_find_block_device, major, minor, "partition"); - if(access(buffer, R_OK) == 0) { + if(likely(access(buffer, R_OK) == 0)) { d->type = DISK_TYPE_PARTITION; - } else { + } + else { // find if it is a container // by checking if /sys/dev/block/MAJOR:MINOR/slaves has entries snprintfz(buffer, FILENAME_MAX, path_find_block_device, major, minor, "slaves/"); - DIR *dirp = opendir(buffer); - if (dirp != NULL) { + DIR *dirp = opendir(buffer); + if(likely(dirp != NULL)) { struct dirent *dp; while( (dp = readdir(dirp)) ) { // . and .. are also files in empty folders. - if(strcmp(dp->d_name, ".") == 0 || strcmp(dp->d_name, "..") == 0) { + if(unlikely(strcmp(dp->d_name, ".") == 0 || strcmp(dp->d_name, "..") == 0)) { continue; } @@ -256,7 +348,7 @@ static struct disk *get_disk(unsigned long major, unsigned long minor, char *dis // Stop the loop after we found one file. break; } - if(closedir(dirp) == -1) + if(unlikely(closedir(dirp) == -1)) error("Unable to close dir %s", buffer); } } @@ -273,7 +365,7 @@ static struct disk *get_disk(unsigned long major, unsigned long minor, char *dis mi = mountinfo_find(disk_mountinfo_root, d->major, d->minor); } */ - if(mi) { + if(unlikely(mi)) { d->mount_point = strdupz(mi->mount_point); d->mount_point_hash = mi->mount_point_hash; } @@ -285,11 +377,11 @@ static struct disk *get_disk(unsigned long major, unsigned long minor, char *dis // ------------------------------------------------------------------------ // find the disk sector size - if(!path_to_get_hw_sector_size[0]) { + if(unlikely(!path_to_get_hw_sector_size[0])) { snprintfz(buffer, FILENAME_MAX, "%s%s", global_host_prefix, "/sys/block/%s/queue/hw_sector_size"); snprintfz(path_to_get_hw_sector_size, FILENAME_MAX, "%s", config_get("plugin:proc:/proc/diskstats", "path to get h/w sector size", buffer)); } - if(!path_to_get_hw_sector_size_partitions[0]) { + if(unlikely(!path_to_get_hw_sector_size_partitions[0])) { snprintfz(buffer, FILENAME_MAX, "%s%s", global_host_prefix, "/sys/dev/block/%lu:%lu/subsystem/%s/../queue/hw_sector_size"); snprintfz(path_to_get_hw_sector_size_partitions, FILENAME_MAX, "%s", config_get("plugin:proc:/proc/diskstats", "path to get h/w sector size for partitions", buffer)); } @@ -300,21 +392,21 @@ static struct disk *get_disk(unsigned long major, unsigned long minor, char *dis // replace all / with ! for(t = tf; *t ;t++) - if(*t == '/') *t = '!'; + if(unlikely(*t == '/')) *t = '!'; - if(d->type == DISK_TYPE_PARTITION) + if(likely(d->type == DISK_TYPE_PARTITION)) snprintfz(buffer, FILENAME_MAX, path_to_get_hw_sector_size_partitions, d->major, d->minor, tf); else snprintfz(buffer, FILENAME_MAX, path_to_get_hw_sector_size, tf); FILE *fpss = fopen(buffer, "r"); - if(fpss) { + if(likely(fpss)) { char buffer2[1024 + 1]; char *tmp = fgets(buffer2, 1024, fpss); - if(tmp) { + if(likely(tmp)) { d->sector_size = atoi(tmp); - if(d->sector_size <= 0) { + if(unlikely(d->sector_size <= 0)) { error("Invalid sector size %d for device %s in %s. Assuming 512.", d->sector_size, d->disk, buffer); d->sector_size = 512; } @@ -330,15 +422,17 @@ static struct disk *get_disk(unsigned long major, unsigned long minor, char *dis } static inline int select_positive_option(int option1, int option2) { - if(option1 == CONFIG_ONDEMAND_YES || option2 == CONFIG_ONDEMAND_YES) + if(unlikely(option1 == CONFIG_ONDEMAND_YES || option2 == CONFIG_ONDEMAND_YES)) return CONFIG_ONDEMAND_YES; - else if(option1 == CONFIG_ONDEMAND_ONDEMAND || option2 == CONFIG_ONDEMAND_ONDEMAND) + else if(unlikely(option1 == CONFIG_ONDEMAND_ONDEMAND || option2 == CONFIG_ONDEMAND_ONDEMAND)) return CONFIG_ONDEMAND_ONDEMAND; return CONFIG_ONDEMAND_NO; } int do_proc_diskstats(int update_every, unsigned long long dt) { + (void)dt; + static procfile *ff = NULL; static int global_enable_new_disks_detected_at_runtime = CONFIG_ONDEMAND_YES, global_enable_performance_for_physical_disks = CONFIG_ONDEMAND_ONDEMAND, @@ -346,7 +440,6 @@ int do_proc_diskstats(int update_every, unsigned long long dt) { global_enable_performance_for_partitions = CONFIG_ONDEMAND_NO, global_enable_performance_for_mountpoints = CONFIG_ONDEMAND_NO, global_enable_performance_for_virtual_mountpoints = CONFIG_ONDEMAND_ONDEMAND, - global_enable_space_for_mountpoints = CONFIG_ONDEMAND_ONDEMAND, global_do_io = CONFIG_ONDEMAND_ONDEMAND, global_do_ops = CONFIG_ONDEMAND_ONDEMAND, global_do_mops = CONFIG_ONDEMAND_ONDEMAND, @@ -354,8 +447,6 @@ int do_proc_diskstats(int update_every, unsigned long long dt) { global_do_qops = CONFIG_ONDEMAND_ONDEMAND, global_do_util = CONFIG_ONDEMAND_ONDEMAND, global_do_backlog = CONFIG_ONDEMAND_ONDEMAND, - global_do_space = CONFIG_ONDEMAND_ONDEMAND, - global_do_inodes = CONFIG_ONDEMAND_ONDEMAND, globals_initialized = 0; if(unlikely(!globals_initialized)) { @@ -366,7 +457,6 @@ int do_proc_diskstats(int update_every, unsigned long long dt) { global_enable_performance_for_partitions = config_get_boolean_ondemand("plugin:proc:/proc/diskstats", "performance metrics for partitions", global_enable_performance_for_partitions); global_enable_performance_for_mountpoints = config_get_boolean_ondemand("plugin:proc:/proc/diskstats", "performance metrics for mounted filesystems", global_enable_performance_for_mountpoints); global_enable_performance_for_virtual_mountpoints = config_get_boolean_ondemand("plugin:proc:/proc/diskstats", "performance metrics for mounted virtual disks", global_enable_performance_for_virtual_mountpoints); - global_enable_space_for_mountpoints = config_get_boolean_ondemand("plugin:proc:/proc/diskstats", "space metrics for mounted filesystems", global_enable_space_for_mountpoints); global_do_io = config_get_boolean_ondemand("plugin:proc:/proc/diskstats", "bandwidth for all disks", global_do_io); global_do_ops = config_get_boolean_ondemand("plugin:proc:/proc/diskstats", "operations for all disks", global_do_ops); @@ -375,24 +465,21 @@ int do_proc_diskstats(int update_every, unsigned long long dt) { global_do_qops = config_get_boolean_ondemand("plugin:proc:/proc/diskstats", "queued operations for all disks", global_do_qops); global_do_util = config_get_boolean_ondemand("plugin:proc:/proc/diskstats", "utilization percentage for all disks", global_do_util); global_do_backlog = config_get_boolean_ondemand("plugin:proc:/proc/diskstats", "backlog for all disks", global_do_backlog); - global_do_space = config_get_boolean_ondemand("plugin:proc:/proc/diskstats", "space usage for all disks", global_do_space); - global_do_inodes = config_get_boolean_ondemand("plugin:proc:/proc/diskstats", "inodes usage for all disks", global_do_inodes); globals_initialized = 1; } - if(!ff) { + if(unlikely(!ff)) { char filename[FILENAME_MAX + 1]; snprintfz(filename, FILENAME_MAX, "%s%s", global_host_prefix, "/proc/diskstats"); ff = procfile_open(config_get("plugin:proc:/proc/diskstats", "filename to monitor", filename), " \t", PROCFILE_FLAG_DEFAULT); } - if(!ff) return 1; + if(unlikely(!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(unlikely(!ff)) return 0; // we return 0, so that we will retry to open it next time uint32_t lines = procfile_lines(ff), l; - uint32_t words; // this is smart enough not to reload it every time mountinfo_reload(0); @@ -412,8 +499,8 @@ int do_proc_diskstats(int update_every, unsigned long long dt) { last_writes = 0, last_writesectors = 0, last_writems = 0, last_busy_ms = 0; - words = procfile_linewords(ff, l); - if(words < 14) continue; + uint32_t words = procfile_linewords(ff, l); + if(unlikely(words < 14)) continue; major = strtoul(procfile_lineword(ff, l, 0), NULL, 10); minor = strtoul(procfile_lineword(ff, l, 1), NULL, 10); @@ -487,7 +574,7 @@ int do_proc_diskstats(int update_every, unsigned long long dt) { snprintfz(var_name, 4096, "plugin:proc:/proc/diskstats:%s", disk); int def_enable = config_get_boolean_ondemand(var_name, "enable", global_enable_new_disks_detected_at_runtime); - if(def_enable == CONFIG_ONDEMAND_NO) { + if(unlikely(def_enable == CONFIG_ONDEMAND_NO)) { // the user does not want any metrics for this disk d->do_io = CONFIG_ONDEMAND_NO; d->do_ops = CONFIG_ONDEMAND_NO; @@ -546,7 +633,7 @@ int do_proc_diskstats(int update_every, unsigned long long dt) { ddo_backlog = CONFIG_ONDEMAND_NO; // we enable individual performance charts only when def_performance is not disabled - if(def_performance != CONFIG_ONDEMAND_NO) { + if(unlikely(def_performance != CONFIG_ONDEMAND_NO)) { ddo_io = global_do_io, ddo_ops = global_do_ops, ddo_mops = global_do_mops, @@ -565,7 +652,7 @@ int do_proc_diskstats(int update_every, unsigned long long dt) { d->do_backlog = config_get_boolean_ondemand(var_name, "backlog", ddo_backlog); // def_space - if(d->mount_point) { + if(unlikely(d->mount_point)) { // check the user configuration (this will also show our 'on demand' decision) def_space = config_get_boolean_ondemand(var_name, "enable space metrics", def_space); @@ -594,13 +681,13 @@ int do_proc_diskstats(int update_every, unsigned long long dt) { d->do_io = CONFIG_ONDEMAND_YES; st = rrdset_find_bytype(RRD_TYPE_DISK, disk); - if(!st) { + if(unlikely(!st)) { st = rrdset_create(RRD_TYPE_DISK, disk, NULL, family, "disk.io", "Disk I/O Bandwidth", "kilobytes/s", 2000, update_every, RRDSET_TYPE_AREA); rrddim_add(st, "reads", NULL, d->sector_size, 1024, RRDDIM_INCREMENTAL); rrddim_add(st, "writes", NULL, d->sector_size * -1, 1024, RRDDIM_INCREMENTAL); } - else rrdset_next_usec(st, dt); + else rrdset_next(st); last_readsectors = rrddim_set(st, "reads", readsectors); last_writesectors = rrddim_set(st, "writes", writesectors); @@ -613,14 +700,14 @@ int do_proc_diskstats(int update_every, unsigned long long dt) { d->do_ops = CONFIG_ONDEMAND_YES; st = rrdset_find_bytype("disk_ops", disk); - if(!st) { + if(unlikely(!st)) { st = rrdset_create("disk_ops", disk, NULL, family, "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_usec(st, dt); + else rrdset_next(st); last_reads = rrddim_set(st, "reads", reads); last_writes = rrddim_set(st, "writes", writes); @@ -633,13 +720,13 @@ int do_proc_diskstats(int update_every, unsigned long long dt) { d->do_qops = CONFIG_ONDEMAND_YES; st = rrdset_find_bytype("disk_qops", disk); - if(!st) { + if(unlikely(!st)) { st = rrdset_create("disk_qops", disk, NULL, family, "disk.qops", "Disk Current I/O Operations", "operations", 2002, update_every, RRDSET_TYPE_LINE); st->isdetail = 1; rrddim_add(st, "operations", NULL, 1, 1, RRDDIM_ABSOLUTE); } - else rrdset_next_usec(st, dt); + else rrdset_next(st); rrddim_set(st, "operations", queued_ios); rrdset_done(st); @@ -651,13 +738,13 @@ int do_proc_diskstats(int update_every, unsigned long long dt) { d->do_backlog = CONFIG_ONDEMAND_YES; st = rrdset_find_bytype("disk_backlog", disk); - if(!st) { + if(unlikely(!st)) { st = rrdset_create("disk_backlog", disk, NULL, family, "disk.backlog", "Disk Backlog", "backlog (ms)", 2003, update_every, RRDSET_TYPE_AREA); st->isdetail = 1; rrddim_add(st, "backlog", NULL, 1, 10, RRDDIM_INCREMENTAL); } - else rrdset_next_usec(st, dt); + else rrdset_next(st); rrddim_set(st, "backlog", backlog_ms); rrdset_done(st); @@ -669,13 +756,13 @@ int do_proc_diskstats(int update_every, unsigned long long dt) { d->do_util = CONFIG_ONDEMAND_YES; st = rrdset_find_bytype("disk_util", disk); - if(!st) { + if(unlikely(!st)) { st = rrdset_create("disk_util", disk, NULL, family, "disk.util", "Disk Utilization Time", "% of time working", 2004, update_every, RRDSET_TYPE_AREA); st->isdetail = 1; rrddim_add(st, "utilization", NULL, 1, 10, RRDDIM_INCREMENTAL); } - else rrdset_next_usec(st, dt); + else rrdset_next(st); last_busy_ms = rrddim_set(st, "utilization", busy_ms); rrdset_done(st); @@ -687,14 +774,14 @@ int do_proc_diskstats(int update_every, unsigned long long dt) { d->do_mops = CONFIG_ONDEMAND_YES; st = rrdset_find_bytype("disk_mops", disk); - if(!st) { + if(unlikely(!st)) { st = rrdset_create("disk_mops", disk, NULL, family, "disk.mops", "Disk Merged Operations", "merged operations/s", 2021, 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_usec(st, dt); + else rrdset_next(st); rrddim_set(st, "reads", mreads); rrddim_set(st, "writes", mwrites); @@ -707,14 +794,14 @@ int do_proc_diskstats(int update_every, unsigned long long dt) { d->do_iotime = CONFIG_ONDEMAND_YES; st = rrdset_find_bytype("disk_iotime", disk); - if(!st) { + if(unlikely(!st)) { st = rrdset_create("disk_iotime", disk, NULL, family, "disk.iotime", "Disk Total I/O Time", "milliseconds/s", 2022, 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_usec(st, dt); + else rrdset_next(st); last_readms = rrddim_set(st, "reads", readms); last_writems = rrddim_set(st, "writes", writems); @@ -725,18 +812,18 @@ int do_proc_diskstats(int update_every, unsigned long long dt) { // calculate differential charts // only if this is not the first time we run - if(dt) { + if(likely(dt)) { if( (d->do_iotime == CONFIG_ONDEMAND_YES || (d->do_iotime == CONFIG_ONDEMAND_ONDEMAND && (readms || writems))) && (d->do_ops == CONFIG_ONDEMAND_YES || (d->do_ops == CONFIG_ONDEMAND_ONDEMAND && (reads || writes)))) { st = rrdset_find_bytype("disk_await", disk); - if(!st) { + if(unlikely(!st)) { st = rrdset_create("disk_await", disk, NULL, family, "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, 1, RRDDIM_ABSOLUTE); rrddim_add(st, "writes", NULL, -1, 1, RRDDIM_ABSOLUTE); } - else rrdset_next_usec(st, dt); + else rrdset_next(st); rrddim_set(st, "reads", (reads - last_reads) ? (readms - last_readms) / (reads - last_reads) : 0); rrddim_set(st, "writes", (writes - last_writes) ? (writems - last_writems) / (writes - last_writes) : 0); @@ -746,14 +833,14 @@ int do_proc_diskstats(int update_every, unsigned long long dt) { if( (d->do_io == CONFIG_ONDEMAND_YES || (d->do_io == CONFIG_ONDEMAND_ONDEMAND && (readsectors || writesectors))) && (d->do_ops == CONFIG_ONDEMAND_YES || (d->do_ops == CONFIG_ONDEMAND_ONDEMAND && (reads || writes)))) { st = rrdset_find_bytype("disk_avgsz", disk); - if(!st) { + if(unlikely(!st)) { st = rrdset_create("disk_avgsz", disk, NULL, family, "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, d->sector_size, 1024, RRDDIM_ABSOLUTE); rrddim_add(st, "writes", NULL, d->sector_size * -1, 1024, RRDDIM_ABSOLUTE); } - else rrdset_next_usec(st, dt); + else rrdset_next(st); rrddim_set(st, "reads", (reads - last_reads) ? (readsectors - last_readsectors) / (reads - last_reads) : 0); rrddim_set(st, "writes", (writes - last_writes) ? (writesectors - last_writesectors) / (writes - last_writes) : 0); @@ -763,13 +850,13 @@ int do_proc_diskstats(int update_every, unsigned long long dt) { if( (d->do_util == CONFIG_ONDEMAND_YES || (d->do_util == CONFIG_ONDEMAND_ONDEMAND && busy_ms)) && (d->do_ops == CONFIG_ONDEMAND_YES || (d->do_ops == CONFIG_ONDEMAND_ONDEMAND && (reads || writes)))) { st = rrdset_find_bytype("disk_svctm", disk); - if(!st) { + if(unlikely(!st)) { st = rrdset_create("disk_svctm", disk, NULL, family, "disk.svctm", "Average Service Time", "ms per operation", 2007, update_every, RRDSET_TYPE_LINE); st->isdetail = 1; rrddim_add(st, "svctm", NULL, 1, 1, RRDDIM_ABSOLUTE); } - else rrdset_next_usec(st, dt); + else rrdset_next(st); rrddim_set(st, "svctm", ((reads - last_reads) + (writes - last_writes)) ? (busy_ms - last_busy_ms) / ((reads - last_reads) + (writes - last_writes)) : 0); rrdset_done(st); @@ -780,7 +867,7 @@ int do_proc_diskstats(int update_every, unsigned long long dt) { // -------------------------------------------------------------------------- // space metrics - if(d->mount_point && (d->do_space || d->do_inodes) ) { + if(unlikely( d->mount_point && (d->do_space || d->do_inodes) )) { do_disk_space_stats(d, d->mount_point, disk, disk, family, update_every, dt); } */ diff --git a/src/proc_interrupts.c b/src/proc_interrupts.c index f277a5a9..14215de6 100644 --- a/src/proc_interrupts.c +++ b/src/proc_interrupts.c @@ -21,7 +21,7 @@ static inline struct interrupt *get_interrupts_array(int lines, int cpus) { static struct interrupt *irrs = NULL; static int allocated = 0; - if(lines > allocated) { + if(unlikely(lines > allocated)) { irrs = (struct interrupt *)reallocz(irrs, lines * recordsize(cpus)); allocated = lines; } @@ -30,42 +30,46 @@ static inline struct interrupt *get_interrupts_array(int lines, int cpus) { } int do_proc_interrupts(int update_every, unsigned long long dt) { + (void)dt; + static procfile *ff = NULL; static int cpus = -1, do_per_core = -1; struct interrupt *irrs = NULL; - if(dt) {}; - - if(do_per_core == -1) do_per_core = config_get_boolean("plugin:proc:/proc/interrupts", "interrupts per core", 1); + if(unlikely(do_per_core == -1)) + do_per_core = config_get_boolean("plugin:proc:/proc/interrupts", "interrupts per core", 1); - if(!ff) { + if(unlikely(!ff)) { char filename[FILENAME_MAX + 1]; snprintfz(filename, FILENAME_MAX, "%s%s", global_host_prefix, "/proc/interrupts"); ff = procfile_open(config_get("plugin:proc:/proc/interrupts", "filename to monitor", filename), " \t", PROCFILE_FLAG_DEFAULT); } - if(!ff) return 1; + if(unlikely(!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(unlikely(!ff)) + return 0; // we return 0, so that we will retry to open it next time uint32_t lines = procfile_lines(ff), l; - uint32_t words = procfile_linewords(ff, 0), w; + uint32_t words = procfile_linewords(ff, 0); - if(!lines) { + if(unlikely(!lines)) { error("Cannot read /proc/interrupts, zero lines reported."); return 1; } // find how many CPUs are there - if(cpus == -1) { + if(unlikely(cpus == -1)) { + uint32_t w; cpus = 0; for(w = 0; w < words ; w++) { - if(strncmp(procfile_lineword(ff, 0, w), "CPU", 3) == 0) + if(unlikely(strncmp(procfile_lineword(ff, 0, w), "CPU", 3) == 0)) cpus++; } } - if(!cpus) { + if(unlikely(!cpus)) { error("PLUGIN: PROC_INTERRUPTS: Cannot find the number of CPUs in /proc/interrupts"); return 1; } @@ -81,18 +85,18 @@ int do_proc_interrupts(int update_every, unsigned long long dt) { irr->total = 0; words = procfile_linewords(ff, l); - if(!words) continue; + if(unlikely(!words)) continue; irr->id = procfile_lineword(ff, l, 0); - if(!irr->id || !irr->id[0]) continue; + if(unlikely(!irr->id || !irr->id[0])) continue; int idlen = strlen(irr->id); - if(irr->id[idlen - 1] == ':') + if(unlikely(irr->id[idlen - 1] == ':')) irr->id[idlen - 1] = '\0'; int c; for(c = 0; c < cpus ;c++) { - if((c + 1) < (int)words) + if(unlikely((c + 1) < (int)words)) irr->value[c] = strtoull(procfile_lineword(ff, l, (uint32_t)(c + 1)), NULL, 10); else irr->value[c] = 0; @@ -100,10 +104,10 @@ int do_proc_interrupts(int update_every, unsigned long long dt) { irr->total += irr->value[c]; } - if(isdigit(irr->id[0]) && (uint32_t)(cpus + 2) < words) { + if(unlikely(isdigit(irr->id[0]) && (uint32_t)(cpus + 2) < words)) { strncpyz(irr->name, procfile_lineword(ff, l, words - 1), MAX_INTERRUPT_NAME); int nlen = strlen(irr->name); - if(nlen < (MAX_INTERRUPT_NAME-1)) { + if(unlikely(nlen < (MAX_INTERRUPT_NAME-1))) { irr->name[nlen] = '_'; strncpyz(&irr->name[nlen + 1], irr->id, MAX_INTERRUPT_NAME - nlen); } @@ -120,12 +124,12 @@ int do_proc_interrupts(int update_every, unsigned long long dt) { // -------------------------------------------------------------------- st = rrdset_find_bytype("system", "interrupts"); - if(!st) { + if(unlikely(!st)) { st = rrdset_create("system", "interrupts", NULL, "interrupts", NULL, "System interrupts", "interrupts/s", 1000, update_every, RRDSET_TYPE_STACKED); for(l = 0; l < lines ;l++) { struct interrupt *irr = irrindex(irrs, l, cpus); - if(!irr->used) continue; + if(unlikely(!irr->used)) continue; rrddim_add(st, irr->id, irr->name, 1, 1, RRDDIM_INCREMENTAL); } } @@ -133,12 +137,12 @@ int do_proc_interrupts(int update_every, unsigned long long dt) { for(l = 0; l < lines ;l++) { struct interrupt *irr = irrindex(irrs, l, cpus); - if(!irr->used) continue; + if(unlikely(!irr->used)) continue; rrddim_set(st, irr->id, irr->total); } rrdset_done(st); - if(do_per_core) { + if(likely(do_per_core)) { int c; for(c = 0; c < cpus ; c++) { @@ -146,14 +150,14 @@ int do_proc_interrupts(int update_every, unsigned long long dt) { snprintfz(id, 50, "cpu%d_interrupts", c); st = rrdset_find_bytype("cpu", id); - if(!st) { + if(unlikely(!st)) { char title[100+1]; snprintfz(title, 100, "CPU%d Interrupts", c); st = rrdset_create("cpu", id, NULL, "interrupts", "cpu.interrupts", title, "interrupts/s", 1100 + c, update_every, RRDSET_TYPE_STACKED); for(l = 0; l < lines ;l++) { struct interrupt *irr = irrindex(irrs, l, cpus); - if(!irr->used) continue; + if(unlikely(!irr->used)) continue; rrddim_add(st, irr->id, irr->name, 1, 1, RRDDIM_INCREMENTAL); } } @@ -161,7 +165,7 @@ int do_proc_interrupts(int update_every, unsigned long long dt) { for(l = 0; l < lines ;l++) { struct interrupt *irr = irrindex(irrs, l, cpus); - if(!irr->used) continue; + if(unlikely(!irr->used)) continue; rrddim_set(st, irr->id, irr->value[c]); } rrdset_done(st); diff --git a/src/proc_loadavg.c b/src/proc_loadavg.c index 44ea7019..a3d75ac5 100644 --- a/src/proc_loadavg.c +++ b/src/proc_loadavg.c @@ -4,29 +4,35 @@ #define MIN_LOADAVG_UPDATE_EVERY 5 int do_proc_loadavg(int update_every, unsigned long long dt) { + (void)dt; + static procfile *ff = NULL; static int do_loadavg = -1, do_all_processes = -1; + static unsigned long long last_loadavg_usec = 0; + static RRDSET *load_chart = NULL, *processes_chart = NULL; - if(dt) {}; - - if(!ff) { + if(unlikely(!ff)) { char filename[FILENAME_MAX + 1]; snprintfz(filename, FILENAME_MAX, "%s%s", global_host_prefix, "/proc/loadavg"); ff = procfile_open(config_get("plugin:proc:/proc/loadavg", "filename to monitor", filename), " \t,:|/", PROCFILE_FLAG_DEFAULT); } - if(!ff) return 1; + if(unlikely(!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(unlikely(!ff)) + return 0; // we return 0, so that we will retry to open it next time - if(do_loadavg == -1) do_loadavg = config_get_boolean("plugin:proc:/proc/loadavg", "enable load average", 1); - if(do_all_processes == -1) do_all_processes = config_get_boolean("plugin:proc:/proc/loadavg", "enable total processes", 1); + if(unlikely(do_loadavg == -1)) { + do_loadavg = config_get_boolean("plugin:proc:/proc/loadavg", "enable load average", 1); + do_all_processes = config_get_boolean("plugin:proc:/proc/loadavg", "enable total processes", 1); + } - if(procfile_lines(ff) < 1) { + if(unlikely(procfile_lines(ff) < 1)) { error("/proc/loadavg has no lines."); return 1; } - if(procfile_linewords(ff, 0) < 6) { + if(unlikely(procfile_linewords(ff, 0) < 6)) { error("/proc/loadavg has less than 6 words in it."); return 1; } @@ -37,43 +43,49 @@ int do_proc_loadavg(int update_every, unsigned long long dt) { //unsigned long long running_processes = strtoull(procfile_lineword(ff, 0, 3), NULL, 10); unsigned long long active_processes = strtoull(procfile_lineword(ff, 0, 4), NULL, 10); - //unsigned long long next_pid = strtoull(procfile_lineword(ff, 0, 5), NULL, 10); + //unsigned long long next_pid = strtoull(procfile_lineword(ff, 0, 5), NULL, 10); - RRDSET *st; - // -------------------------------------------------------------------- - if(do_loadavg) { - st = rrdset_find_byname("system.load"); - if(!st) { - st = rrdset_create("system", "load", NULL, "load", NULL, "System Load Average", "load", 100, (update_every < MIN_LOADAVG_UPDATE_EVERY)?MIN_LOADAVG_UPDATE_EVERY:update_every, RRDSET_TYPE_LINE); - - rrddim_add(st, "load1", NULL, 1, 1000, RRDDIM_ABSOLUTE); - rrddim_add(st, "load5", NULL, 1, 1000, RRDDIM_ABSOLUTE); - rrddim_add(st, "load15", NULL, 1, 1000, RRDDIM_ABSOLUTE); + if(last_loadavg_usec <= dt) { + if(likely(do_loadavg)) { + if(unlikely(!load_chart)) { + load_chart = rrdset_find_byname("system.load"); + if(unlikely(!load_chart)) { + load_chart = rrdset_create("system", "load", NULL, "load", NULL, "System Load Average", "load", 100, (update_every < MIN_LOADAVG_UPDATE_EVERY) ? MIN_LOADAVG_UPDATE_EVERY : update_every, RRDSET_TYPE_LINE); + rrddim_add(load_chart, "load1", NULL, 1, 1000, RRDDIM_ABSOLUTE); + rrddim_add(load_chart, "load5", NULL, 1, 1000, RRDDIM_ABSOLUTE); + rrddim_add(load_chart, "load15", NULL, 1, 1000, RRDDIM_ABSOLUTE); + } + } + else + rrdset_next(load_chart); + + rrddim_set(load_chart, "load1", (collected_number) (load1 * 1000)); + rrddim_set(load_chart, "load5", (collected_number) (load5 * 1000)); + rrddim_set(load_chart, "load15", (collected_number) (load15 * 1000)); + rrdset_done(load_chart); } - else rrdset_next(st); - rrddim_set(st, "load1", load1 * 1000); - rrddim_set(st, "load5", load5 * 1000); - rrddim_set(st, "load15", load15 * 1000); - rrdset_done(st); + last_loadavg_usec = load_chart->update_every * 1000000ULL; } + else last_loadavg_usec -= dt; // -------------------------------------------------------------------- - if(do_all_processes) { - st = rrdset_find_byname("system.active_processes"); - if(!st) { - st = rrdset_create("system", "active_processes", NULL, "processes", NULL, "System Active Processes", "processes", 750, update_every, RRDSET_TYPE_LINE); - - rrddim_add(st, "active", NULL, 1, 1, RRDDIM_ABSOLUTE); + if(likely(do_all_processes)) { + if(unlikely(!processes_chart)) { + processes_chart = rrdset_find_byname("system.active_processes"); + if(unlikely(!processes_chart)) { + processes_chart = rrdset_create("system", "active_processes", NULL, "processes", NULL, "System Active Processes", "processes", 750, update_every, RRDSET_TYPE_LINE); + rrddim_add(processes_chart, "active", NULL, 1, 1, RRDDIM_ABSOLUTE); + } } - else rrdset_next(st); + else rrdset_next(processes_chart); - rrddim_set(st, "active", active_processes); - rrdset_done(st); + rrddim_set(processes_chart, "active", active_processes); + rrdset_done(processes_chart); } return 0; diff --git a/src/proc_meminfo.c b/src/proc_meminfo.c index 999c9538..11b41be7 100644 --- a/src/proc_meminfo.c +++ b/src/proc_meminfo.c @@ -1,96 +1,215 @@ #include "common.h" -#define MAX_PROC_MEMINFO_LINE 4096 -#define MAX_PROC_MEMINFO_NAME 1024 - int do_proc_meminfo(int update_every, unsigned long long dt) { - static procfile *ff = NULL; + (void)dt; + static procfile *ff = NULL; static int do_ram = -1, do_swap = -1, do_hwcorrupt = -1, do_committed = -1, do_writeback = -1, do_kernel = -1, do_slab = -1; + static uint32_t MemTotal_hash = 0, + MemFree_hash = 0, + Buffers_hash = 0, + Cached_hash = 0, + //SwapCached_hash = 0, + //Active_hash = 0, + //Inactive_hash = 0, + //ActiveAnon_hash = 0, + //InactiveAnon_hash = 0, + //ActiveFile_hash = 0, + //InactiveFile_hash = 0, + //Unevictable_hash = 0, + //Mlocked_hash = 0, + SwapTotal_hash = 0, + SwapFree_hash = 0, + Dirty_hash = 0, + Writeback_hash = 0, + //AnonPages_hash = 0, + //Mapped_hash = 0, + //Shmem_hash = 0, + Slab_hash = 0, + SReclaimable_hash = 0, + SUnreclaim_hash = 0, + KernelStack_hash = 0, + PageTables_hash = 0, + NFS_Unstable_hash = 0, + Bounce_hash = 0, + WritebackTmp_hash = 0, + //CommitLimit_hash = 0, + Committed_AS_hash = 0, + //VmallocTotal_hash = 0, + VmallocUsed_hash = 0, + //VmallocChunk_hash = 0, + //AnonHugePages_hash = 0, + //HugePages_Total_hash = 0, + //HugePages_Free_hash = 0, + //HugePages_Rsvd_hash = 0, + //HugePages_Surp_hash = 0, + //Hugepagesize_hash = 0, + //DirectMap4k_hash = 0, + //DirectMap2M_hash = 0, + HardwareCorrupted_hash = 0; + + if(unlikely(do_ram == -1)) { + do_ram = config_get_boolean("plugin:proc:/proc/meminfo", "system ram", 1); + do_swap = config_get_boolean_ondemand("plugin:proc:/proc/meminfo", "system swap", CONFIG_ONDEMAND_ONDEMAND); + do_hwcorrupt = config_get_boolean_ondemand("plugin:proc:/proc/meminfo", "hardware corrupted ECC", CONFIG_ONDEMAND_ONDEMAND); + do_committed = config_get_boolean("plugin:proc:/proc/meminfo", "committed memory", 1); + do_writeback = config_get_boolean("plugin:proc:/proc/meminfo", "writeback memory", 1); + do_kernel = config_get_boolean("plugin:proc:/proc/meminfo", "kernel memory", 1); + do_slab = config_get_boolean("plugin:proc:/proc/meminfo", "slab memory", 1); + + MemTotal_hash = simple_hash("MemTotal"); + MemFree_hash = simple_hash("MemFree"); + Buffers_hash = simple_hash("Buffers"); + Cached_hash = simple_hash("Cached"); + //SwapCached_hash = simple_hash("SwapCached"); + //Active_hash = simple_hash("Active"); + //Inactive_hash = simple_hash("Inactive"); + //ActiveAnon_hash = simple_hash("ActiveAnon"); + //InactiveAnon_hash = simple_hash("InactiveAnon"); + //ActiveFile_hash = simple_hash("ActiveFile"); + //InactiveFile_hash = simple_hash("InactiveFile"); + //Unevictable_hash = simple_hash("Unevictable"); + //Mlocked_hash = simple_hash("Mlocked"); + SwapTotal_hash = simple_hash("SwapTotal"); + SwapFree_hash = simple_hash("SwapFree"); + Dirty_hash = simple_hash("Dirty"); + Writeback_hash = simple_hash("Writeback"); + //AnonPages_hash = simple_hash("AnonPages"); + //Mapped_hash = simple_hash("Mapped"); + //Shmem_hash = simple_hash("Shmem"); + Slab_hash = simple_hash("Slab"); + SReclaimable_hash = simple_hash("SReclaimable"); + SUnreclaim_hash = simple_hash("SUnreclaim"); + KernelStack_hash = simple_hash("KernelStack"); + PageTables_hash = simple_hash("PageTables"); + NFS_Unstable_hash = simple_hash("NFS_Unstable"); + Bounce_hash = simple_hash("Bounce"); + WritebackTmp_hash = simple_hash("WritebackTmp"); + //CommitLimit_hash = simple_hash("CommitLimit"); + Committed_AS_hash = simple_hash("Committed_AS"); + //VmallocTotal_hash = simple_hash("VmallocTotal"); + VmallocUsed_hash = simple_hash("VmallocUsed"); + //VmallocChunk_hash = simple_hash("VmallocChunk"); + HardwareCorrupted_hash = simple_hash("HardwareCorrupted"); + //AnonHugePages_hash = simple_hash("AnonHugePages"); + //HugePages_Total_hash = simple_hash("HugePages_Total"); + //HugePages_Free_hash = simple_hash("HugePages_Free"); + //HugePages_Rsvd_hash = simple_hash("HugePages_Rsvd"); + //HugePages_Surp_hash = simple_hash("HugePages_Surp"); + //Hugepagesize_hash = simple_hash("Hugepagesize"); + //DirectMap4k_hash = simple_hash("DirectMap4k"); + //DirectMap2M_hash = simple_hash("DirectMap2M"); + } - if(do_ram == -1) do_ram = config_get_boolean("plugin:proc:/proc/meminfo", "system ram", 1); - if(do_swap == -1) do_swap = config_get_boolean_ondemand("plugin:proc:/proc/meminfo", "system swap", CONFIG_ONDEMAND_ONDEMAND); - if(do_hwcorrupt == -1) do_hwcorrupt = config_get_boolean_ondemand("plugin:proc:/proc/meminfo", "hardware corrupted ECC", CONFIG_ONDEMAND_ONDEMAND); - if(do_committed == -1) do_committed = config_get_boolean("plugin:proc:/proc/meminfo", "committed memory", 1); - if(do_writeback == -1) do_writeback = config_get_boolean("plugin:proc:/proc/meminfo", "writeback memory", 1); - if(do_kernel == -1) do_kernel = config_get_boolean("plugin:proc:/proc/meminfo", "kernel memory", 1); - if(do_slab == -1) do_slab = config_get_boolean("plugin:proc:/proc/meminfo", "slab memory", 1); - - (void)dt; - - if(!ff) { + if(unlikely(!ff)) { char filename[FILENAME_MAX + 1]; snprintfz(filename, FILENAME_MAX, "%s%s", global_host_prefix, "/proc/meminfo"); ff = procfile_open(config_get("plugin:proc:/proc/meminfo", "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(unlikely(!ff)) + return 0; // we return 0, so that we will retry to open it next time uint32_t lines = procfile_lines(ff), l; - uint32_t words; int hwcorrupted = 0; - unsigned long long MemTotal = 0, MemFree = 0, Buffers = 0, Cached = 0, SwapCached = 0, - Active = 0, Inactive = 0, ActiveAnon = 0, InactiveAnon = 0, ActiveFile = 0, InactiveFile = 0, - Unevictable = 0, Mlocked = 0, SwapTotal = 0, SwapFree = 0, Dirty = 0, Writeback = 0, AnonPages = 0, - Mapped = 0, Shmem = 0, Slab = 0, SReclaimable = 0, SUnreclaim = 0, KernelStack = 0, PageTables = 0, - NFS_Unstable = 0, Bounce = 0, WritebackTmp = 0, CommitLimit = 0, Committed_AS = 0, - VmallocTotal = 0, VmallocUsed = 0, VmallocChunk = 0, - AnonHugePages = 0, HugePages_Total = 0, HugePages_Free = 0, HugePages_Rsvd = 0, HugePages_Surp = 0, Hugepagesize = 0, - DirectMap4k = 0, DirectMap2M = 0, HardwareCorrupted = 0; + unsigned long long MemTotal = 0, + MemFree = 0, + Buffers = 0, + Cached = 0, + //SwapCached = 0, + //Active = 0, + //Inactive = 0, + //ActiveAnon = 0, + //InactiveAnon = 0, + //ActiveFile = 0, + //InactiveFile = 0, + //Unevictable = 0, + //Mlocked = 0, + SwapTotal = 0, + SwapFree = 0, + Dirty = 0, + Writeback = 0, + //AnonPages = 0, + //Mapped = 0, + //Shmem = 0, + Slab = 0, + SReclaimable = 0, + SUnreclaim = 0, + KernelStack = 0, + PageTables = 0, + NFS_Unstable = 0, + Bounce = 0, + WritebackTmp = 0, + //CommitLimit = 0, + Committed_AS = 0, + //VmallocTotal = 0, + VmallocUsed = 0, + //VmallocChunk = 0, + //AnonHugePages = 0, + //HugePages_Total = 0, + //HugePages_Free = 0, + //HugePages_Rsvd = 0, + //HugePages_Surp = 0, + //Hugepagesize = 0, + //DirectMap4k = 0, + //DirectMap2M = 0, + HardwareCorrupted = 0; for(l = 0; l < lines ;l++) { - words = procfile_linewords(ff, l); - if(words < 2) continue; + uint32_t words = procfile_linewords(ff, l); + if(unlikely(words < 2)) continue; char *name = procfile_lineword(ff, l, 0); + uint32_t hash = simple_hash(name); unsigned long long value = strtoull(procfile_lineword(ff, l, 1), NULL, 10); - if(!MemTotal && strcmp(name, "MemTotal") == 0) MemTotal = value; - else if(!MemFree && strcmp(name, "MemFree") == 0) MemFree = value; - else if(!Buffers && strcmp(name, "Buffers") == 0) Buffers = value; - else if(!Cached && strcmp(name, "Cached") == 0) Cached = value; - else if(!SwapCached && strcmp(name, "SwapCached") == 0) SwapCached = value; - else if(!Active && strcmp(name, "Active") == 0) Active = value; - else if(!Inactive && strcmp(name, "Inactive") == 0) Inactive = value; - else if(!ActiveAnon && strcmp(name, "ActiveAnon") == 0) ActiveAnon = value; - else if(!InactiveAnon && strcmp(name, "InactiveAnon") == 0) InactiveAnon = value; - else if(!ActiveFile && strcmp(name, "ActiveFile") == 0) ActiveFile = value; - else if(!InactiveFile && strcmp(name, "InactiveFile") == 0) InactiveFile = value; - else if(!Unevictable && strcmp(name, "Unevictable") == 0) Unevictable = value; - else if(!Mlocked && strcmp(name, "Mlocked") == 0) Mlocked = value; - else if(!SwapTotal && strcmp(name, "SwapTotal") == 0) SwapTotal = value; - else if(!SwapFree && strcmp(name, "SwapFree") == 0) SwapFree = value; - else if(!Dirty && strcmp(name, "Dirty") == 0) Dirty = value; - else if(!Writeback && strcmp(name, "Writeback") == 0) Writeback = value; - else if(!AnonPages && strcmp(name, "AnonPages") == 0) AnonPages = value; - else if(!Mapped && strcmp(name, "Mapped") == 0) Mapped = value; - else if(!Shmem && strcmp(name, "Shmem") == 0) Shmem = value; - else if(!Slab && strcmp(name, "Slab") == 0) Slab = value; - else if(!SReclaimable && strcmp(name, "SReclaimable") == 0) SReclaimable = value; - else if(!SUnreclaim && strcmp(name, "SUnreclaim") == 0) SUnreclaim = value; - else if(!KernelStack && strcmp(name, "KernelStack") == 0) KernelStack = value; - else if(!PageTables && strcmp(name, "PageTables") == 0) PageTables = value; - else if(!NFS_Unstable && strcmp(name, "NFS_Unstable") == 0) NFS_Unstable = value; - else if(!Bounce && strcmp(name, "Bounce") == 0) Bounce = value; - else if(!WritebackTmp && strcmp(name, "WritebackTmp") == 0) WritebackTmp = value; - else if(!CommitLimit && strcmp(name, "CommitLimit") == 0) CommitLimit = value; - else if(!Committed_AS && strcmp(name, "Committed_AS") == 0) Committed_AS = value; - else if(!VmallocTotal && strcmp(name, "VmallocTotal") == 0) VmallocTotal = value; - else if(!VmallocUsed && strcmp(name, "VmallocUsed") == 0) VmallocUsed = value; - else if(!VmallocChunk && strcmp(name, "VmallocChunk") == 0) VmallocChunk = value; - else if(!HardwareCorrupted && strcmp(name, "HardwareCorrupted") == 0) { HardwareCorrupted = value; hwcorrupted = 1; } - else if(!AnonHugePages && strcmp(name, "AnonHugePages") == 0) AnonHugePages = value; - else if(!HugePages_Total && strcmp(name, "HugePages_Total") == 0) HugePages_Total = value; - else if(!HugePages_Free && strcmp(name, "HugePages_Free") == 0) HugePages_Free = value; - else if(!HugePages_Rsvd && strcmp(name, "HugePages_Rsvd") == 0) HugePages_Rsvd = value; - else if(!HugePages_Surp && strcmp(name, "HugePages_Surp") == 0) HugePages_Surp = value; - else if(!Hugepagesize && strcmp(name, "Hugepagesize") == 0) Hugepagesize = value; - else if(!DirectMap4k && strcmp(name, "DirectMap4k") == 0) DirectMap4k = value; - else if(!DirectMap2M && strcmp(name, "DirectMap2M") == 0) DirectMap2M = value; + if(hash == MemTotal_hash && strcmp(name, "MemTotal") == 0) MemTotal = value; + else if(hash == MemFree_hash && strcmp(name, "MemFree") == 0) MemFree = value; + else if(hash == Buffers_hash && strcmp(name, "Buffers") == 0) Buffers = value; + else if(hash == Cached_hash && strcmp(name, "Cached") == 0) Cached = value; + //else if(hash == SwapCached_hash && strcmp(name, "SwapCached") == 0) SwapCached = value; + //else if(hash == Active_hash && strcmp(name, "Active") == 0) Active = value; + //else if(hash == Inactive_hash && strcmp(name, "Inactive") == 0) Inactive = value; + //else if(hash == ActiveAnon_hash && strcmp(name, "ActiveAnon") == 0) ActiveAnon = value; + //else if(hash == InactiveAnon_hash && strcmp(name, "InactiveAnon") == 0) InactiveAnon = value; + //else if(hash == ActiveFile_hash && strcmp(name, "ActiveFile") == 0) ActiveFile = value; + //else if(hash == InactiveFile_hash && strcmp(name, "InactiveFile") == 0) InactiveFile = value; + //else if(hash == Unevictable_hash && strcmp(name, "Unevictable") == 0) Unevictable = value; + //else if(hash == Mlocked_hash && strcmp(name, "Mlocked") == 0) Mlocked = value; + else if(hash == SwapTotal_hash && strcmp(name, "SwapTotal") == 0) SwapTotal = value; + else if(hash == SwapFree_hash && strcmp(name, "SwapFree") == 0) SwapFree = value; + else if(hash == Dirty_hash && strcmp(name, "Dirty") == 0) Dirty = value; + else if(hash == Writeback_hash && strcmp(name, "Writeback") == 0) Writeback = value; + //else if(hash == AnonPages_hash && strcmp(name, "AnonPages") == 0) AnonPages = value; + //else if(hash == Mapped_hash && strcmp(name, "Mapped") == 0) Mapped = value; + //else if(hash == Shmem_hash && strcmp(name, "Shmem") == 0) Shmem = value; + else if(hash == Slab_hash && strcmp(name, "Slab") == 0) Slab = value; + else if(hash == SReclaimable_hash && strcmp(name, "SReclaimable") == 0) SReclaimable = value; + else if(hash == SUnreclaim_hash && strcmp(name, "SUnreclaim") == 0) SUnreclaim = value; + else if(hash == KernelStack_hash && strcmp(name, "KernelStack") == 0) KernelStack = value; + else if(hash == PageTables_hash && strcmp(name, "PageTables") == 0) PageTables = value; + else if(hash == NFS_Unstable_hash && strcmp(name, "NFS_Unstable") == 0) NFS_Unstable = value; + else if(hash == Bounce_hash && strcmp(name, "Bounce") == 0) Bounce = value; + else if(hash == WritebackTmp_hash && strcmp(name, "WritebackTmp") == 0) WritebackTmp = value; + //else if(hash == CommitLimit_hash && strcmp(name, "CommitLimit") == 0) CommitLimit = value; + else if(hash == Committed_AS_hash && strcmp(name, "Committed_AS") == 0) Committed_AS = value; + //else if(hash == VmallocTotal_hash && strcmp(name, "VmallocTotal") == 0) VmallocTotal = value; + else if(hash == VmallocUsed_hash && strcmp(name, "VmallocUsed") == 0) VmallocUsed = value; + //else if(hash == VmallocChunk_hash && strcmp(name, "VmallocChunk") == 0) VmallocChunk = value; + else if(hash == HardwareCorrupted_hash && strcmp(name, "HardwareCorrupted") == 0) { HardwareCorrupted = value; hwcorrupted = 1; } + //else if(hash == AnonHugePages_hash && strcmp(name, "AnonHugePages") == 0) AnonHugePages = value; + //else if(hash == HugePages_Total_hash && strcmp(name, "HugePages_Total") == 0) HugePages_Total = value; + //else if(hash == HugePages_Free_hash && strcmp(name, "HugePages_Free") == 0) HugePages_Free = value; + //else if(hash == HugePages_Rsvd_hash && strcmp(name, "HugePages_Rsvd") == 0) HugePages_Rsvd = value; + //else if(hash == HugePages_Surp_hash && strcmp(name, "HugePages_Surp") == 0) HugePages_Surp = value; + //else if(hash == Hugepagesize_hash && strcmp(name, "Hugepagesize") == 0) Hugepagesize = value; + //else if(hash == DirectMap4k_hash && strcmp(name, "DirectMap4k") == 0) DirectMap4k = value; + //else if(hash == DirectMap2M_hash && strcmp(name, "DirectMap2M") == 0) DirectMap2M = value; } RRDSET *st; diff --git a/src/proc_net_dev.c b/src/proc_net_dev.c index 53981182..33d140c4 100644 --- a/src/proc_net_dev.c +++ b/src/proc_net_dev.c @@ -29,14 +29,13 @@ int do_proc_net_dev(int update_every, unsigned long long dt) { 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); uint32_t lines = procfile_lines(ff), l; - uint32_t words; 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++) { - words = procfile_linewords(ff, l); + uint32_t words = procfile_linewords(ff, l); if(words < 17) continue; iface = procfile_lineword(ff, l, 0); diff --git a/src/proc_net_netstat.c b/src/proc_net_netstat.c index ea38acf2..00d26635 100644 --- a/src/proc_net_netstat.c +++ b/src/proc_net_netstat.c @@ -543,8 +543,8 @@ int do_proc_net_netstat(int update_every, unsigned long long dt) { char filename[FILENAME_MAX + 1]; snprintfz(filename, FILENAME_MAX, "%s%s", global_host_prefix, "/proc/net/netstat"); ff = procfile_open(config_get("plugin:proc:/proc/net/netstat", "filename to monitor", filename), " \t:", PROCFILE_FLAG_DEFAULT); + if(unlikely(!ff)) return 1; } - if(unlikely(!ff)) return 1; ff = procfile_readall(ff); if(unlikely(!ff)) return 0; // we return 0, so that we will retry to open it next time @@ -559,12 +559,12 @@ int do_proc_net_netstat(int update_every, unsigned long long dt) { if(unlikely(hash == hash_ipext && strcmp(key, "IpExt") == 0)) { uint32_t h = l++; - if(strcmp(procfile_lineword(ff, l, 0), "IpExt") != 0) { + if(unlikely(strcmp(procfile_lineword(ff, l, 0), "IpExt") != 0)) { error("Cannot read IpExt line from /proc/net/netstat."); break; } words = procfile_linewords(ff, l); - if(words < 2) { + if(unlikely(words < 2)) { error("Cannot read /proc/net/netstat IpExt line. Expected 2+ params, read %u.", words); continue; } @@ -578,7 +578,7 @@ int do_proc_net_netstat(int update_every, unsigned long long dt) { if(do_bandwidth == CONFIG_ONDEMAND_YES || (do_bandwidth == CONFIG_ONDEMAND_ONDEMAND && (*ipext_InOctets || *ipext_OutOctets))) { do_bandwidth = CONFIG_ONDEMAND_YES; st = rrdset_find("system.ipv4"); - if(!st) { + if(unlikely(!st)) { st = rrdset_create("system", "ipv4", NULL, "network", NULL, "IPv4 Bandwidth", "kilobits/s", 500, update_every, RRDSET_TYPE_AREA); rrddim_add(st, "InOctets", "received", 8, 1024, RRDDIM_INCREMENTAL); @@ -596,7 +596,7 @@ int do_proc_net_netstat(int update_every, unsigned long long dt) { if(do_inerrors == CONFIG_ONDEMAND_YES || (do_inerrors == CONFIG_ONDEMAND_ONDEMAND && (*ipext_InNoRoutes || *ipext_InTruncatedPkts))) { do_inerrors = CONFIG_ONDEMAND_YES; st = rrdset_find("ipv4.inerrors"); - if(!st) { + if(unlikely(!st)) { st = rrdset_create("ipv4", "inerrors", NULL, "errors", NULL, "IPv4 Input Errors", "packets/s", 4000, update_every, RRDSET_TYPE_LINE); st->isdetail = 1; @@ -617,7 +617,7 @@ int do_proc_net_netstat(int update_every, unsigned long long dt) { if(do_mcast == CONFIG_ONDEMAND_YES || (do_mcast == CONFIG_ONDEMAND_ONDEMAND && (*ipext_InMcastOctets || *ipext_OutMcastOctets))) { do_mcast = CONFIG_ONDEMAND_YES; st = rrdset_find("ipv4.mcast"); - if(!st) { + if(unlikely(!st)) { st = rrdset_create("ipv4", "mcast", NULL, "multicast", NULL, "IPv4 Multicast Bandwidth", "kilobits/s", 9000, update_every, RRDSET_TYPE_AREA); st->isdetail = 1; @@ -636,7 +636,7 @@ int do_proc_net_netstat(int update_every, unsigned long long dt) { if(do_bcast == CONFIG_ONDEMAND_YES || (do_bcast == CONFIG_ONDEMAND_ONDEMAND && (*ipext_InBcastOctets || *ipext_OutBcastOctets))) { do_bcast = CONFIG_ONDEMAND_YES; st = rrdset_find("ipv4.bcast"); - if(!st) { + if(unlikely(!st)) { st = rrdset_create("ipv4", "bcast", NULL, "broadcast", NULL, "IPv4 Broadcast Bandwidth", "kilobits/s", 8000, update_every, RRDSET_TYPE_AREA); st->isdetail = 1; @@ -655,7 +655,7 @@ int do_proc_net_netstat(int update_every, unsigned long long dt) { if(do_mcast_p == CONFIG_ONDEMAND_YES || (do_mcast_p == CONFIG_ONDEMAND_ONDEMAND && (*ipext_InMcastPkts || *ipext_OutMcastPkts))) { do_mcast_p = CONFIG_ONDEMAND_YES; st = rrdset_find("ipv4.mcastpkts"); - if(!st) { + if(unlikely(!st)) { st = rrdset_create("ipv4", "mcastpkts", NULL, "multicast", NULL, "IPv4 Multicast Packets", "packets/s", 8600, update_every, RRDSET_TYPE_LINE); st->isdetail = 1; @@ -674,7 +674,7 @@ int do_proc_net_netstat(int update_every, unsigned long long dt) { if(do_bcast_p == CONFIG_ONDEMAND_YES || (do_bcast_p == CONFIG_ONDEMAND_ONDEMAND && (*ipext_InBcastPkts || *ipext_OutBcastPkts))) { do_bcast_p = CONFIG_ONDEMAND_YES; st = rrdset_find("ipv4.bcastpkts"); - if(!st) { + if(unlikely(!st)) { st = rrdset_create("ipv4", "bcastpkts", NULL, "broadcast", NULL, "IPv4 Broadcast Packets", "packets/s", 8500, update_every, RRDSET_TYPE_LINE); st->isdetail = 1; @@ -693,7 +693,7 @@ int do_proc_net_netstat(int update_every, unsigned long long dt) { if(do_ecn == CONFIG_ONDEMAND_YES || (do_ecn == CONFIG_ONDEMAND_ONDEMAND && (*ipext_InCEPkts || *ipext_InECT0Pkts || *ipext_InECT1Pkts || *ipext_InNoECTPkts))) { do_ecn = CONFIG_ONDEMAND_YES; st = rrdset_find("ipv4.ecnpkts"); - if(!st) { + if(unlikely(!st)) { st = rrdset_create("ipv4", "ecnpkts", NULL, "ecn", NULL, "IPv4 ECN Statistics", "packets/s", 8700, update_every, RRDSET_TYPE_LINE); st->isdetail = 1; @@ -714,12 +714,12 @@ int do_proc_net_netstat(int update_every, unsigned long long dt) { else if(unlikely(hash == hash_tcpext && strcmp(key, "TcpExt") == 0)) { uint32_t h = l++; - if(strcmp(procfile_lineword(ff, l, 0), "TcpExt") != 0) { + if(unlikely(strcmp(procfile_lineword(ff, l, 0), "TcpExt") != 0)) { error("Cannot read TcpExt line from /proc/net/netstat."); break; } words = procfile_linewords(ff, l); - if(words < 2) { + if(unlikely(words < 2)) { error("Cannot read /proc/net/netstat TcpExt line. Expected 2+ params, read %u.", words); continue; } @@ -733,7 +733,7 @@ int do_proc_net_netstat(int update_every, unsigned long long dt) { if(do_tcpext_memory == CONFIG_ONDEMAND_YES || (do_tcpext_memory == CONFIG_ONDEMAND_ONDEMAND && (*tcpext_TCPMemoryPressures))) { do_tcpext_memory = CONFIG_ONDEMAND_YES; st = rrdset_find("ipv4.tcpmemorypressures"); - if(!st) { + if(unlikely(!st)) { st = rrdset_create("ipv4", "tcpmemorypressures", NULL, "tcp", NULL, "TCP Memory Pressures", "events/s", 3000, update_every, RRDSET_TYPE_LINE); rrddim_add(st, "TCPMemoryPressures", "pressures", 1, 1, RRDDIM_INCREMENTAL); @@ -749,7 +749,7 @@ int do_proc_net_netstat(int update_every, unsigned long long dt) { if(do_tcpext_connaborts == CONFIG_ONDEMAND_YES || (do_tcpext_connaborts == CONFIG_ONDEMAND_ONDEMAND && (*tcpext_TCPAbortOnData || *tcpext_TCPAbortOnClose || *tcpext_TCPAbortOnMemory || *tcpext_TCPAbortOnTimeout || *tcpext_TCPAbortOnLinger || *tcpext_TCPAbortFailed))) { do_tcpext_connaborts = CONFIG_ONDEMAND_YES; st = rrdset_find("ipv4.tcpconnaborts"); - if(!st) { + if(unlikely(!st)) { st = rrdset_create("ipv4", "tcpconnaborts", NULL, "tcp", NULL, "TCP Connection Aborts", "connections/s", 3010, update_every, RRDSET_TYPE_LINE); rrddim_add(st, "TCPAbortOnData", "baddata", 1, 1, RRDDIM_INCREMENTAL); @@ -774,7 +774,7 @@ int do_proc_net_netstat(int update_every, unsigned long long dt) { if(do_tcpext_reorder == CONFIG_ONDEMAND_YES || (do_tcpext_reorder == CONFIG_ONDEMAND_ONDEMAND && (*tcpext_TCPRenoReorder || *tcpext_TCPFACKReorder || *tcpext_TCPSACKReorder || *tcpext_TCPTSReorder))) { do_tcpext_reorder = CONFIG_ONDEMAND_YES; st = rrdset_find("ipv4.tcpreorders"); - if(!st) { + if(unlikely(!st)) { st = rrdset_create("ipv4", "tcpreorders", NULL, "tcp", NULL, "TCP Reordered Packets by Detection Method", "packets/s", 3020, update_every, RRDSET_TYPE_LINE); rrddim_add(st, "TCPTSReorder", "timestamp", 1, 1, RRDDIM_INCREMENTAL); @@ -796,7 +796,7 @@ int do_proc_net_netstat(int update_every, unsigned long long dt) { if(do_tcpext_ofo == CONFIG_ONDEMAND_YES || (do_tcpext_ofo == CONFIG_ONDEMAND_ONDEMAND && (*tcpext_TCPOFOQueue || *tcpext_TCPOFODrop || *tcpext_TCPOFOMerge))) { do_tcpext_ofo = CONFIG_ONDEMAND_YES; st = rrdset_find("ipv4.tcpofo"); - if(!st) { + if(unlikely(!st)) { st = rrdset_create("ipv4", "tcpofo", NULL, "tcp", NULL, "TCP Out-Of-Order Queue", "packets/s", 3050, update_every, RRDSET_TYPE_LINE); rrddim_add(st, "TCPOFOQueue", "inqueue", 1, 1, RRDDIM_INCREMENTAL); @@ -818,7 +818,7 @@ int do_proc_net_netstat(int update_every, unsigned long long dt) { if(do_tcpext_syscookies == CONFIG_ONDEMAND_YES || (do_tcpext_syscookies == CONFIG_ONDEMAND_ONDEMAND && (*tcpext_SyncookiesSent || *tcpext_SyncookiesRecv || *tcpext_SyncookiesFailed))) { do_tcpext_syscookies = CONFIG_ONDEMAND_YES; st = rrdset_find("ipv4.tcpsyncookies"); - if(!st) { + if(unlikely(!st)) { st = rrdset_create("ipv4", "tcpsyncookies", NULL, "tcp", NULL, "TCP SYN Cookies", "packets/s", 3100, update_every, RRDSET_TYPE_LINE); rrddim_add(st, "SyncookiesRecv", "received", 1, 1, RRDDIM_INCREMENTAL); diff --git a/src/proc_net_rpc_nfs.c b/src/proc_net_rpc_nfs.c index 98acdd81..86e2f70c 100644 --- a/src/proc_net_rpc_nfs.c +++ b/src/proc_net_rpc_nfs.c @@ -159,14 +159,13 @@ int do_proc_net_rpc_nfs(int update_every, unsigned long long dt) { if(do_proc4) do_proc4 = 1; uint32_t lines = procfile_lines(ff), l; - uint32_t words; char *type; unsigned long long net_count = 0, net_udp_count = 0, net_tcp_count = 0, net_tcp_connections = 0; unsigned long long rpc_calls = 0, rpc_retransmits = 0, rpc_auth_refresh = 0; for(l = 0; l < lines ;l++) { - words = procfile_linewords(ff, l); + uint32_t words = procfile_linewords(ff, l); if(!words) continue; type = procfile_lineword(ff, l, 0); diff --git a/src/proc_net_rpc_nfsd.c b/src/proc_net_rpc_nfsd.c index 817e6c86..e0092c72 100644 --- a/src/proc_net_rpc_nfsd.c +++ b/src/proc_net_rpc_nfsd.c @@ -253,7 +253,6 @@ int do_proc_net_rpc_nfsd(int update_every, unsigned long long dt) { if(do_proc4ops) do_proc4ops = 1; uint32_t lines = procfile_lines(ff), l; - uint32_t words; char *type; unsigned long long rc_hits = 0, rc_misses = 0, rc_nocache = 0; @@ -265,7 +264,7 @@ int do_proc_net_rpc_nfsd(int update_every, unsigned long long dt) { unsigned long long rpc_calls = 0, rpc_bad_format = 0, rpc_bad_auth = 0, rpc_bad_client = 0; for(l = 0; l < lines ;l++) { - words = procfile_linewords(ff, l); + uint32_t words = procfile_linewords(ff, l); if(!words) continue; type = procfile_lineword(ff, l, 0); diff --git a/src/proc_net_snmp.c b/src/proc_net_snmp.c index a75c0a96..3ef111ba 100644 --- a/src/proc_net_snmp.c +++ b/src/proc_net_snmp.c @@ -360,8 +360,8 @@ int do_proc_net_snmp(int update_every, unsigned long long dt) { char filename[FILENAME_MAX + 1]; snprintfz(filename, FILENAME_MAX, "%s%s", global_host_prefix, "/proc/net/snmp"); ff = procfile_open(config_get("plugin:proc:/proc/net/snmp", "filename to monitor", filename), " \t:", PROCFILE_FLAG_DEFAULT); + if(unlikely(!ff)) return 1; } - if(unlikely(!ff)) return 1; ff = procfile_readall(ff); if(unlikely(!ff)) return 0; // we return 0, so that we will retry to open it next time diff --git a/src/proc_net_snmp6.c b/src/proc_net_snmp6.c index 97dc20ed..b7ec65c0 100644 --- a/src/proc_net_snmp6.c +++ b/src/proc_net_snmp6.c @@ -4,8 +4,10 @@ #define RRD_TYPE_NET_SNMP6_LEN strlen(RRD_TYPE_NET_SNMP6) int do_proc_net_snmp6(int update_every, unsigned long long dt) { + (void)dt; + static procfile *ff = NULL; - static int gen_hashes = -1; + static int initialized = 0; static int do_ip_packets = -1, do_ip_fragsout = -1, do_ip_fragsin = -1, do_ip_errors = -1, do_udplite_packets = -1, do_udplite_errors = -1, @@ -14,112 +16,113 @@ int do_proc_net_snmp6(int update_every, unsigned long long dt) { do_icmp = -1, do_icmp_redir = -1, do_icmp_errors = -1, do_icmp_echos = -1, do_icmp_groupmemb = -1, do_icmp_router = -1, do_icmp_neighbor = -1, do_icmp_mldv2 = -1, do_icmp_types = -1, do_ect = -1; - static uint32_t hash_Ip6InReceives = -1; - - static uint32_t hash_Ip6InHdrErrors = -1; - static uint32_t hash_Ip6InTooBigErrors = -1; - static uint32_t hash_Ip6InNoRoutes = -1; - static uint32_t hash_Ip6InAddrErrors = -1; - static uint32_t hash_Ip6InUnknownProtos = -1; - static uint32_t hash_Ip6InTruncatedPkts = -1; - static uint32_t hash_Ip6InDiscards = -1; - static uint32_t hash_Ip6InDelivers = -1; - - static uint32_t hash_Ip6OutForwDatagrams = -1; - static uint32_t hash_Ip6OutRequests = -1; - static uint32_t hash_Ip6OutDiscards = -1; - static uint32_t hash_Ip6OutNoRoutes = -1; - - static uint32_t hash_Ip6ReasmTimeout = -1; - static uint32_t hash_Ip6ReasmReqds = -1; - static uint32_t hash_Ip6ReasmOKs = -1; - static uint32_t hash_Ip6ReasmFails = -1; - - static uint32_t hash_Ip6FragOKs = -1; - static uint32_t hash_Ip6FragFails = -1; - static uint32_t hash_Ip6FragCreates = -1; - - static uint32_t hash_Ip6InMcastPkts = -1; - static uint32_t hash_Ip6OutMcastPkts = -1; - - static uint32_t hash_Ip6InOctets = -1; - static uint32_t hash_Ip6OutOctets = -1; - - static uint32_t hash_Ip6InMcastOctets = -1; - static uint32_t hash_Ip6OutMcastOctets = -1; - static uint32_t hash_Ip6InBcastOctets = -1; - static uint32_t hash_Ip6OutBcastOctets = -1; - - static uint32_t hash_Ip6InNoECTPkts = -1; - static uint32_t hash_Ip6InECT1Pkts = -1; - static uint32_t hash_Ip6InECT0Pkts = -1; - static uint32_t hash_Ip6InCEPkts = -1; - - static uint32_t hash_Icmp6InMsgs = -1; - static uint32_t hash_Icmp6InErrors = -1; - static uint32_t hash_Icmp6OutMsgs = -1; - static uint32_t hash_Icmp6OutErrors = -1; - static uint32_t hash_Icmp6InCsumErrors = -1; - static uint32_t hash_Icmp6InDestUnreachs = -1; - static uint32_t hash_Icmp6InPktTooBigs = -1; - static uint32_t hash_Icmp6InTimeExcds = -1; - static uint32_t hash_Icmp6InParmProblems = -1; - static uint32_t hash_Icmp6InEchos = -1; - static uint32_t hash_Icmp6InEchoReplies = -1; - static uint32_t hash_Icmp6InGroupMembQueries = -1; - static uint32_t hash_Icmp6InGroupMembResponses = -1; - static uint32_t hash_Icmp6InGroupMembReductions = -1; - static uint32_t hash_Icmp6InRouterSolicits = -1; - static uint32_t hash_Icmp6InRouterAdvertisements = -1; - static uint32_t hash_Icmp6InNeighborSolicits = -1; - static uint32_t hash_Icmp6InNeighborAdvertisements = -1; - static uint32_t hash_Icmp6InRedirects = -1; - static uint32_t hash_Icmp6InMLDv2Reports = -1; - static uint32_t hash_Icmp6OutDestUnreachs = -1; - static uint32_t hash_Icmp6OutPktTooBigs = -1; - static uint32_t hash_Icmp6OutTimeExcds = -1; - static uint32_t hash_Icmp6OutParmProblems = -1; - static uint32_t hash_Icmp6OutEchos = -1; - static uint32_t hash_Icmp6OutEchoReplies = -1; - static uint32_t hash_Icmp6OutGroupMembQueries = -1; - static uint32_t hash_Icmp6OutGroupMembResponses = -1; - static uint32_t hash_Icmp6OutGroupMembReductions = -1; - static uint32_t hash_Icmp6OutRouterSolicits = -1; - static uint32_t hash_Icmp6OutRouterAdvertisements = -1; - static uint32_t hash_Icmp6OutNeighborSolicits = -1; - static uint32_t hash_Icmp6OutNeighborAdvertisements = -1; - static uint32_t hash_Icmp6OutRedirects = -1; - static uint32_t hash_Icmp6OutMLDv2Reports = -1; - static uint32_t hash_Icmp6InType1 = -1; - static uint32_t hash_Icmp6InType128 = -1; - static uint32_t hash_Icmp6InType129 = -1; - static uint32_t hash_Icmp6InType136 = -1; - static uint32_t hash_Icmp6OutType1 = -1; - static uint32_t hash_Icmp6OutType128 = -1; - static uint32_t hash_Icmp6OutType129 = -1; - static uint32_t hash_Icmp6OutType133 = -1; - static uint32_t hash_Icmp6OutType135 = -1; - static uint32_t hash_Icmp6OutType143 = -1; - - static uint32_t hash_Udp6InDatagrams = -1; - static uint32_t hash_Udp6NoPorts = -1; - static uint32_t hash_Udp6InErrors = -1; - static uint32_t hash_Udp6OutDatagrams = -1; - static uint32_t hash_Udp6RcvbufErrors = -1; - static uint32_t hash_Udp6SndbufErrors = -1; - static uint32_t hash_Udp6InCsumErrors = -1; - static uint32_t hash_Udp6IgnoredMulti = -1; - - static uint32_t hash_UdpLite6InDatagrams = -1; - static uint32_t hash_UdpLite6NoPorts = -1; - static uint32_t hash_UdpLite6InErrors = -1; - static uint32_t hash_UdpLite6OutDatagrams = -1; - static uint32_t hash_UdpLite6RcvbufErrors = -1; - static uint32_t hash_UdpLite6SndbufErrors = -1; - static uint32_t hash_UdpLite6InCsumErrors = -1; - - if(gen_hashes != 1) { - gen_hashes = 1; + static uint32_t hash_Ip6InReceives = 0; + + static uint32_t hash_Ip6InHdrErrors = 0; + static uint32_t hash_Ip6InTooBigErrors = 0; + static uint32_t hash_Ip6InNoRoutes = 0; + static uint32_t hash_Ip6InAddrErrors = 0; + static uint32_t hash_Ip6InUnknownProtos = 0; + static uint32_t hash_Ip6InTruncatedPkts = 0; + static uint32_t hash_Ip6InDiscards = 0; + static uint32_t hash_Ip6InDelivers = 0; + + static uint32_t hash_Ip6OutForwDatagrams = 0; + static uint32_t hash_Ip6OutRequests = 0; + static uint32_t hash_Ip6OutDiscards = 0; + static uint32_t hash_Ip6OutNoRoutes = 0; + + static uint32_t hash_Ip6ReasmTimeout = 0; + static uint32_t hash_Ip6ReasmReqds = 0; + static uint32_t hash_Ip6ReasmOKs = 0; + static uint32_t hash_Ip6ReasmFails = 0; + + static uint32_t hash_Ip6FragOKs = 0; + static uint32_t hash_Ip6FragFails = 0; + static uint32_t hash_Ip6FragCreates = 0; + + static uint32_t hash_Ip6InMcastPkts = 0; + static uint32_t hash_Ip6OutMcastPkts = 0; + + static uint32_t hash_Ip6InOctets = 0; + static uint32_t hash_Ip6OutOctets = 0; + + static uint32_t hash_Ip6InMcastOctets = 0; + static uint32_t hash_Ip6OutMcastOctets = 0; + static uint32_t hash_Ip6InBcastOctets = 0; + static uint32_t hash_Ip6OutBcastOctets = 0; + + static uint32_t hash_Ip6InNoECTPkts = 0; + static uint32_t hash_Ip6InECT1Pkts = 0; + static uint32_t hash_Ip6InECT0Pkts = 0; + static uint32_t hash_Ip6InCEPkts = 0; + + static uint32_t hash_Icmp6InMsgs = 0; + static uint32_t hash_Icmp6InErrors = 0; + static uint32_t hash_Icmp6OutMsgs = 0; + static uint32_t hash_Icmp6OutErrors = 0; + static uint32_t hash_Icmp6InCsumErrors = 0; + static uint32_t hash_Icmp6InDestUnreachs = 0; + static uint32_t hash_Icmp6InPktTooBigs = 0; + static uint32_t hash_Icmp6InTimeExcds = 0; + static uint32_t hash_Icmp6InParmProblems = 0; + static uint32_t hash_Icmp6InEchos = 0; + static uint32_t hash_Icmp6InEchoReplies = 0; + static uint32_t hash_Icmp6InGroupMembQueries = 0; + static uint32_t hash_Icmp6InGroupMembResponses = 0; + static uint32_t hash_Icmp6InGroupMembReductions = 0; + static uint32_t hash_Icmp6InRouterSolicits = 0; + static uint32_t hash_Icmp6InRouterAdvertisements = 0; + static uint32_t hash_Icmp6InNeighborSolicits = 0; + static uint32_t hash_Icmp6InNeighborAdvertisements = 0; + static uint32_t hash_Icmp6InRedirects = 0; + static uint32_t hash_Icmp6InMLDv2Reports = 0; + static uint32_t hash_Icmp6OutDestUnreachs = 0; + static uint32_t hash_Icmp6OutPktTooBigs = 0; + static uint32_t hash_Icmp6OutTimeExcds = 0; + static uint32_t hash_Icmp6OutParmProblems = 0; + static uint32_t hash_Icmp6OutEchos = 0; + static uint32_t hash_Icmp6OutEchoReplies = 0; + static uint32_t hash_Icmp6OutGroupMembQueries = 0; + static uint32_t hash_Icmp6OutGroupMembResponses = 0; + static uint32_t hash_Icmp6OutGroupMembReductions = 0; + static uint32_t hash_Icmp6OutRouterSolicits = 0; + static uint32_t hash_Icmp6OutRouterAdvertisements = 0; + static uint32_t hash_Icmp6OutNeighborSolicits = 0; + static uint32_t hash_Icmp6OutNeighborAdvertisements = 0; + static uint32_t hash_Icmp6OutRedirects = 0; + static uint32_t hash_Icmp6OutMLDv2Reports = 0; + static uint32_t hash_Icmp6InType1 = 0; + static uint32_t hash_Icmp6InType128 = 0; + static uint32_t hash_Icmp6InType129 = 0; + static uint32_t hash_Icmp6InType136 = 0; + static uint32_t hash_Icmp6OutType1 = 0; + static uint32_t hash_Icmp6OutType128 = 0; + static uint32_t hash_Icmp6OutType129 = 0; + static uint32_t hash_Icmp6OutType133 = 0; + static uint32_t hash_Icmp6OutType135 = 0; + static uint32_t hash_Icmp6OutType143 = 0; + + static uint32_t hash_Udp6InDatagrams = 0; + static uint32_t hash_Udp6NoPorts = 0; + static uint32_t hash_Udp6InErrors = 0; + static uint32_t hash_Udp6OutDatagrams = 0; + static uint32_t hash_Udp6RcvbufErrors = 0; + static uint32_t hash_Udp6SndbufErrors = 0; + static uint32_t hash_Udp6InCsumErrors = 0; + static uint32_t hash_Udp6IgnoredMulti = 0; + + static uint32_t hash_UdpLite6InDatagrams = 0; + static uint32_t hash_UdpLite6NoPorts = 0; + static uint32_t hash_UdpLite6InErrors = 0; + static uint32_t hash_UdpLite6OutDatagrams = 0; + static uint32_t hash_UdpLite6RcvbufErrors = 0; + static uint32_t hash_UdpLite6SndbufErrors = 0; + static uint32_t hash_UdpLite6InCsumErrors = 0; + + if(unlikely(!initialized)) { + initialized = 1; + hash_Ip6InReceives = simple_hash("Ip6InReceives"); hash_Ip6InHdrErrors = simple_hash("Ip6InHdrErrors"); hash_Ip6InTooBigErrors = simple_hash("Ip6InTooBigErrors"); @@ -212,45 +215,44 @@ int do_proc_net_snmp6(int update_every, unsigned long long dt) { hash_UdpLite6RcvbufErrors = simple_hash("UdpLite6RcvbufErrors"); hash_UdpLite6SndbufErrors = simple_hash("UdpLite6SndbufErrors"); hash_UdpLite6InCsumErrors = simple_hash("UdpLite6InCsumErrors"); + + do_ip_packets = config_get_boolean_ondemand("plugin:proc:/proc/net/snmp6", "ipv6 packets", CONFIG_ONDEMAND_ONDEMAND); + do_ip_fragsout = config_get_boolean_ondemand("plugin:proc:/proc/net/snmp6", "ipv6 fragments sent", CONFIG_ONDEMAND_ONDEMAND); + do_ip_fragsin = config_get_boolean_ondemand("plugin:proc:/proc/net/snmp6", "ipv6 fragments assembly", CONFIG_ONDEMAND_ONDEMAND); + do_ip_errors = config_get_boolean_ondemand("plugin:proc:/proc/net/snmp6", "ipv6 errors", CONFIG_ONDEMAND_ONDEMAND); + do_udp_packets = config_get_boolean_ondemand("plugin:proc:/proc/net/snmp6", "ipv6 UDP packets", CONFIG_ONDEMAND_ONDEMAND); + do_udp_errors = config_get_boolean_ondemand("plugin:proc:/proc/net/snmp6", "ipv6 UDP errors", CONFIG_ONDEMAND_ONDEMAND); + do_udplite_packets = config_get_boolean_ondemand("plugin:proc:/proc/net/snmp6", "ipv6 UDPlite packets", CONFIG_ONDEMAND_ONDEMAND); + do_udplite_errors = config_get_boolean_ondemand("plugin:proc:/proc/net/snmp6", "ipv6 UDPlite errors", CONFIG_ONDEMAND_ONDEMAND); + do_bandwidth = config_get_boolean_ondemand("plugin:proc:/proc/net/snmp6", "bandwidth", CONFIG_ONDEMAND_ONDEMAND); + do_mcast = config_get_boolean_ondemand("plugin:proc:/proc/net/snmp6", "multicast bandwidth", CONFIG_ONDEMAND_ONDEMAND); + do_bcast = config_get_boolean_ondemand("plugin:proc:/proc/net/snmp6", "broadcast bandwidth", CONFIG_ONDEMAND_ONDEMAND); + do_mcast_p = config_get_boolean_ondemand("plugin:proc:/proc/net/snmp6", "multicast packets", CONFIG_ONDEMAND_ONDEMAND); + do_icmp = config_get_boolean_ondemand("plugin:proc:/proc/net/snmp6", "icmp", CONFIG_ONDEMAND_ONDEMAND); + do_icmp_redir = config_get_boolean_ondemand("plugin:proc:/proc/net/snmp6", "icmp redirects", CONFIG_ONDEMAND_ONDEMAND); + do_icmp_errors = config_get_boolean_ondemand("plugin:proc:/proc/net/snmp6", "icmp errors", CONFIG_ONDEMAND_ONDEMAND); + do_icmp_echos = config_get_boolean_ondemand("plugin:proc:/proc/net/snmp6", "icmp echos", CONFIG_ONDEMAND_ONDEMAND); + do_icmp_groupmemb = config_get_boolean_ondemand("plugin:proc:/proc/net/snmp6", "icmp group membership", CONFIG_ONDEMAND_ONDEMAND); + do_icmp_router = config_get_boolean_ondemand("plugin:proc:/proc/net/snmp6", "icmp router", CONFIG_ONDEMAND_ONDEMAND); + do_icmp_neighbor = config_get_boolean_ondemand("plugin:proc:/proc/net/snmp6", "icmp neighbor", CONFIG_ONDEMAND_ONDEMAND); + do_icmp_mldv2 = config_get_boolean_ondemand("plugin:proc:/proc/net/snmp6", "icmp mldv2", CONFIG_ONDEMAND_ONDEMAND); + do_icmp_types = config_get_boolean_ondemand("plugin:proc:/proc/net/snmp6", "icmp types", CONFIG_ONDEMAND_ONDEMAND); + do_ect = config_get_boolean_ondemand("plugin:proc:/proc/net/snmp6", "ect", CONFIG_ONDEMAND_ONDEMAND); } - if(do_ip_packets == -1) do_ip_packets = config_get_boolean_ondemand("plugin:proc:/proc/net/snmp6", "ipv6 packets", CONFIG_ONDEMAND_ONDEMAND); - if(do_ip_fragsout == -1) do_ip_fragsout = config_get_boolean_ondemand("plugin:proc:/proc/net/snmp6", "ipv6 fragments sent", CONFIG_ONDEMAND_ONDEMAND); - if(do_ip_fragsin == -1) do_ip_fragsin = config_get_boolean_ondemand("plugin:proc:/proc/net/snmp6", "ipv6 fragments assembly", CONFIG_ONDEMAND_ONDEMAND); - if(do_ip_errors == -1) do_ip_errors = config_get_boolean_ondemand("plugin:proc:/proc/net/snmp6", "ipv6 errors", CONFIG_ONDEMAND_ONDEMAND); - if(do_udp_packets == -1) do_udp_packets = config_get_boolean_ondemand("plugin:proc:/proc/net/snmp6", "ipv6 UDP packets", CONFIG_ONDEMAND_ONDEMAND); - if(do_udp_errors == -1) do_udp_errors = config_get_boolean_ondemand("plugin:proc:/proc/net/snmp6", "ipv6 UDP errors", CONFIG_ONDEMAND_ONDEMAND); - if(do_udplite_packets == -1) do_udplite_packets = config_get_boolean_ondemand("plugin:proc:/proc/net/snmp6", "ipv6 UDPlite packets", CONFIG_ONDEMAND_ONDEMAND); - if(do_udplite_errors == -1) do_udplite_errors = config_get_boolean_ondemand("plugin:proc:/proc/net/snmp6", "ipv6 UDPlite errors", CONFIG_ONDEMAND_ONDEMAND); - if(do_bandwidth == -1) do_bandwidth = config_get_boolean_ondemand("plugin:proc:/proc/net/snmp6", "bandwidth", CONFIG_ONDEMAND_ONDEMAND); - if(do_mcast == -1) do_mcast = config_get_boolean_ondemand("plugin:proc:/proc/net/snmp6", "multicast bandwidth", CONFIG_ONDEMAND_ONDEMAND); - if(do_bcast == -1) do_bcast = config_get_boolean_ondemand("plugin:proc:/proc/net/snmp6", "broadcast bandwidth", CONFIG_ONDEMAND_ONDEMAND); - if(do_mcast_p == -1) do_mcast_p = config_get_boolean_ondemand("plugin:proc:/proc/net/snmp6", "multicast packets", CONFIG_ONDEMAND_ONDEMAND); - if(do_icmp == -1) do_icmp = config_get_boolean_ondemand("plugin:proc:/proc/net/snmp6", "icmp", CONFIG_ONDEMAND_ONDEMAND); - if(do_icmp_redir == -1) do_icmp_redir = config_get_boolean_ondemand("plugin:proc:/proc/net/snmp6", "icmp redirects", CONFIG_ONDEMAND_ONDEMAND); - if(do_icmp_errors == -1) do_icmp_errors = config_get_boolean_ondemand("plugin:proc:/proc/net/snmp6", "icmp errors", CONFIG_ONDEMAND_ONDEMAND); - if(do_icmp_echos == -1) do_icmp_echos = config_get_boolean_ondemand("plugin:proc:/proc/net/snmp6", "icmp echos", CONFIG_ONDEMAND_ONDEMAND); - if(do_icmp_groupmemb == -1) do_icmp_groupmemb = config_get_boolean_ondemand("plugin:proc:/proc/net/snmp6", "icmp group membership", CONFIG_ONDEMAND_ONDEMAND); - if(do_icmp_router == -1) do_icmp_router = config_get_boolean_ondemand("plugin:proc:/proc/net/snmp6", "icmp router", CONFIG_ONDEMAND_ONDEMAND); - if(do_icmp_neighbor == -1) do_icmp_neighbor = config_get_boolean_ondemand("plugin:proc:/proc/net/snmp6", "icmp neighbor", CONFIG_ONDEMAND_ONDEMAND); - if(do_icmp_mldv2 == -1) do_icmp_mldv2 = config_get_boolean_ondemand("plugin:proc:/proc/net/snmp6", "icmp mldv2", CONFIG_ONDEMAND_ONDEMAND); - if(do_icmp_types == -1) do_icmp_types = config_get_boolean_ondemand("plugin:proc:/proc/net/snmp6", "icmp types", CONFIG_ONDEMAND_ONDEMAND); - if(do_ect == -1) do_ect = config_get_boolean_ondemand("plugin:proc:/proc/net/snmp6", "ect", CONFIG_ONDEMAND_ONDEMAND); - - if(dt) {}; - - if(!ff) { + if(unlikely(!ff)) { char filename[FILENAME_MAX + 1]; snprintfz(filename, FILENAME_MAX, "%s%s", global_host_prefix, "/proc/net/snmp6"); ff = procfile_open(config_get("plugin:proc:/proc/net/snmp6", "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(unlikely(!ff)) + return 0; // we return 0, so that we will retry to open it next time uint32_t lines = procfile_lines(ff), l; - uint32_t words; unsigned long long Ip6InReceives = 0ULL; unsigned long long Ip6InHdrErrors = 0ULL; @@ -346,111 +348,111 @@ int do_proc_net_snmp6(int update_every, unsigned long long dt) { unsigned long long UdpLite6InCsumErrors = 0ULL; for(l = 0; l < lines ;l++) { - words = procfile_linewords(ff, l); - if(words < 2) { - if(words) error("Cannot read /proc/net/snmp6 line %u. Expected 2 params, read %u.", l, words); + uint32_t words = procfile_linewords(ff, l); + if(unlikely(words < 2)) { + if(unlikely(words)) error("Cannot read /proc/net/snmp6 line %u. Expected 2 params, read %u.", l, words); continue; } char *name = procfile_lineword(ff, l, 0); char * value = procfile_lineword(ff, l, 1); - if(!name || !*name || !value || !*value) continue; + if(unlikely(!name || !*name || !value || !*value)) + continue; uint32_t hash = simple_hash(name); - if(0) ; - else if(hash == hash_Ip6InReceives && strcmp(name, "Ip6InReceives") == 0) Ip6InReceives = strtoull(value, NULL, 10); - else if(hash == hash_Ip6InHdrErrors && strcmp(name, "Ip6InHdrErrors") == 0) Ip6InHdrErrors = strtoull(value, NULL, 10); - else if(hash == hash_Ip6InTooBigErrors && strcmp(name, "Ip6InTooBigErrors") == 0) Ip6InTooBigErrors = strtoull(value, NULL, 10); - else if(hash == hash_Ip6InNoRoutes && strcmp(name, "Ip6InNoRoutes") == 0) Ip6InNoRoutes = strtoull(value, NULL, 10); - else if(hash == hash_Ip6InAddrErrors && strcmp(name, "Ip6InAddrErrors") == 0) Ip6InAddrErrors = strtoull(value, NULL, 10); - else if(hash == hash_Ip6InUnknownProtos && strcmp(name, "Ip6InUnknownProtos") == 0) Ip6InUnknownProtos = strtoull(value, NULL, 10); - else if(hash == hash_Ip6InTruncatedPkts && strcmp(name, "Ip6InTruncatedPkts") == 0) Ip6InTruncatedPkts = strtoull(value, NULL, 10); - else if(hash == hash_Ip6InDiscards && strcmp(name, "Ip6InDiscards") == 0) Ip6InDiscards = strtoull(value, NULL, 10); - else if(hash == hash_Ip6InDelivers && strcmp(name, "Ip6InDelivers") == 0) Ip6InDelivers = strtoull(value, NULL, 10); - else if(hash == hash_Ip6OutForwDatagrams && strcmp(name, "Ip6OutForwDatagrams") == 0) Ip6OutForwDatagrams = strtoull(value, NULL, 10); - else if(hash == hash_Ip6OutRequests && strcmp(name, "Ip6OutRequests") == 0) Ip6OutRequests = strtoull(value, NULL, 10); - else if(hash == hash_Ip6OutDiscards && strcmp(name, "Ip6OutDiscards") == 0) Ip6OutDiscards = strtoull(value, NULL, 10); - else if(hash == hash_Ip6OutNoRoutes && strcmp(name, "Ip6OutNoRoutes") == 0) Ip6OutNoRoutes = strtoull(value, NULL, 10); - else if(hash == hash_Ip6ReasmTimeout && strcmp(name, "Ip6ReasmTimeout") == 0) Ip6ReasmTimeout = strtoull(value, NULL, 10); - else if(hash == hash_Ip6ReasmReqds && strcmp(name, "Ip6ReasmReqds") == 0) Ip6ReasmReqds = strtoull(value, NULL, 10); - else if(hash == hash_Ip6ReasmOKs && strcmp(name, "Ip6ReasmOKs") == 0) Ip6ReasmOKs = strtoull(value, NULL, 10); - else if(hash == hash_Ip6ReasmFails && strcmp(name, "Ip6ReasmFails") == 0) Ip6ReasmFails = strtoull(value, NULL, 10); - else if(hash == hash_Ip6FragOKs && strcmp(name, "Ip6FragOKs") == 0) Ip6FragOKs = strtoull(value, NULL, 10); - else if(hash == hash_Ip6FragFails && strcmp(name, "Ip6FragFails") == 0) Ip6FragFails = strtoull(value, NULL, 10); - else if(hash == hash_Ip6FragCreates && strcmp(name, "Ip6FragCreates") == 0) Ip6FragCreates = strtoull(value, NULL, 10); - else if(hash == hash_Ip6InMcastPkts && strcmp(name, "Ip6InMcastPkts") == 0) Ip6InMcastPkts = strtoull(value, NULL, 10); - else if(hash == hash_Ip6OutMcastPkts && strcmp(name, "Ip6OutMcastPkts") == 0) Ip6OutMcastPkts = strtoull(value, NULL, 10); - else if(hash == hash_Ip6InOctets && strcmp(name, "Ip6InOctets") == 0) Ip6InOctets = strtoull(value, NULL, 10); - else if(hash == hash_Ip6OutOctets && strcmp(name, "Ip6OutOctets") == 0) Ip6OutOctets = strtoull(value, NULL, 10); - else if(hash == hash_Ip6InMcastOctets && strcmp(name, "Ip6InMcastOctets") == 0) Ip6InMcastOctets = strtoull(value, NULL, 10); - else if(hash == hash_Ip6OutMcastOctets && strcmp(name, "Ip6OutMcastOctets") == 0) Ip6OutMcastOctets = strtoull(value, NULL, 10); - else if(hash == hash_Ip6InBcastOctets && strcmp(name, "Ip6InBcastOctets") == 0) Ip6InBcastOctets = strtoull(value, NULL, 10); - else if(hash == hash_Ip6OutBcastOctets && strcmp(name, "Ip6OutBcastOctets") == 0) Ip6OutBcastOctets = strtoull(value, NULL, 10); - else if(hash == hash_Ip6InNoECTPkts && strcmp(name, "Ip6InNoECTPkts") == 0) Ip6InNoECTPkts = strtoull(value, NULL, 10); - else if(hash == hash_Ip6InECT1Pkts && strcmp(name, "Ip6InECT1Pkts") == 0) Ip6InECT1Pkts = strtoull(value, NULL, 10); - else if(hash == hash_Ip6InECT0Pkts && strcmp(name, "Ip6InECT0Pkts") == 0) Ip6InECT0Pkts = strtoull(value, NULL, 10); - else if(hash == hash_Ip6InCEPkts && strcmp(name, "Ip6InCEPkts") == 0) Ip6InCEPkts = strtoull(value, NULL, 10); - else if(hash == hash_Icmp6InMsgs && strcmp(name, "Icmp6InMsgs") == 0) Icmp6InMsgs = strtoull(value, NULL, 10); - else if(hash == hash_Icmp6InErrors && strcmp(name, "Icmp6InErrors") == 0) Icmp6InErrors = strtoull(value, NULL, 10); - else if(hash == hash_Icmp6OutMsgs && strcmp(name, "Icmp6OutMsgs") == 0) Icmp6OutMsgs = strtoull(value, NULL, 10); - else if(hash == hash_Icmp6OutErrors && strcmp(name, "Icmp6OutErrors") == 0) Icmp6OutErrors = strtoull(value, NULL, 10); - else if(hash == hash_Icmp6InCsumErrors && strcmp(name, "Icmp6InCsumErrors") == 0) Icmp6InCsumErrors = strtoull(value, NULL, 10); - else if(hash == hash_Icmp6InDestUnreachs && strcmp(name, "Icmp6InDestUnreachs") == 0) Icmp6InDestUnreachs = strtoull(value, NULL, 10); - else if(hash == hash_Icmp6InPktTooBigs && strcmp(name, "Icmp6InPktTooBigs") == 0) Icmp6InPktTooBigs = strtoull(value, NULL, 10); - else if(hash == hash_Icmp6InTimeExcds && strcmp(name, "Icmp6InTimeExcds") == 0) Icmp6InTimeExcds = strtoull(value, NULL, 10); - else if(hash == hash_Icmp6InParmProblems && strcmp(name, "Icmp6InParmProblems") == 0) Icmp6InParmProblems = strtoull(value, NULL, 10); - else if(hash == hash_Icmp6InEchos && strcmp(name, "Icmp6InEchos") == 0) Icmp6InEchos = strtoull(value, NULL, 10); - else if(hash == hash_Icmp6InEchoReplies && strcmp(name, "Icmp6InEchoReplies") == 0) Icmp6InEchoReplies = strtoull(value, NULL, 10); - else if(hash == hash_Icmp6InGroupMembQueries && strcmp(name, "Icmp6InGroupMembQueries") == 0) Icmp6InGroupMembQueries = strtoull(value, NULL, 10); - else if(hash == hash_Icmp6InGroupMembResponses && strcmp(name, "Icmp6InGroupMembResponses") == 0) Icmp6InGroupMembResponses = strtoull(value, NULL, 10); - else if(hash == hash_Icmp6InGroupMembReductions && strcmp(name, "Icmp6InGroupMembReductions") == 0) Icmp6InGroupMembReductions = strtoull(value, NULL, 10); - else if(hash == hash_Icmp6InRouterSolicits && strcmp(name, "Icmp6InRouterSolicits") == 0) Icmp6InRouterSolicits = strtoull(value, NULL, 10); - else if(hash == hash_Icmp6InRouterAdvertisements && strcmp(name, "Icmp6InRouterAdvertisements") == 0) Icmp6InRouterAdvertisements = strtoull(value, NULL, 10); - else if(hash == hash_Icmp6InNeighborSolicits && strcmp(name, "Icmp6InNeighborSolicits") == 0) Icmp6InNeighborSolicits = strtoull(value, NULL, 10); - else if(hash == hash_Icmp6InNeighborAdvertisements && strcmp(name, "Icmp6InNeighborAdvertisements") == 0) Icmp6InNeighborAdvertisements = strtoull(value, NULL, 10); - else if(hash == hash_Icmp6InRedirects && strcmp(name, "Icmp6InRedirects") == 0) Icmp6InRedirects = strtoull(value, NULL, 10); - else if(hash == hash_Icmp6InMLDv2Reports && strcmp(name, "Icmp6InMLDv2Reports") == 0) Icmp6InMLDv2Reports = strtoull(value, NULL, 10); - else if(hash == hash_Icmp6OutDestUnreachs && strcmp(name, "Icmp6OutDestUnreachs") == 0) Icmp6OutDestUnreachs = strtoull(value, NULL, 10); - else if(hash == hash_Icmp6OutPktTooBigs && strcmp(name, "Icmp6OutPktTooBigs") == 0) Icmp6OutPktTooBigs = strtoull(value, NULL, 10); - else if(hash == hash_Icmp6OutTimeExcds && strcmp(name, "Icmp6OutTimeExcds") == 0) Icmp6OutTimeExcds = strtoull(value, NULL, 10); - else if(hash == hash_Icmp6OutParmProblems && strcmp(name, "Icmp6OutParmProblems") == 0) Icmp6OutParmProblems = strtoull(value, NULL, 10); - else if(hash == hash_Icmp6OutEchos && strcmp(name, "Icmp6OutEchos") == 0) Icmp6OutEchos = strtoull(value, NULL, 10); - else if(hash == hash_Icmp6OutEchoReplies && strcmp(name, "Icmp6OutEchoReplies") == 0) Icmp6OutEchoReplies = strtoull(value, NULL, 10); - else if(hash == hash_Icmp6OutGroupMembQueries && strcmp(name, "Icmp6OutGroupMembQueries") == 0) Icmp6OutGroupMembQueries = strtoull(value, NULL, 10); - else if(hash == hash_Icmp6OutGroupMembResponses && strcmp(name, "Icmp6OutGroupMembResponses") == 0) Icmp6OutGroupMembResponses = strtoull(value, NULL, 10); - else if(hash == hash_Icmp6OutGroupMembReductions && strcmp(name, "Icmp6OutGroupMembReductions") == 0) Icmp6OutGroupMembReductions = strtoull(value, NULL, 10); - else if(hash == hash_Icmp6OutRouterSolicits && strcmp(name, "Icmp6OutRouterSolicits") == 0) Icmp6OutRouterSolicits = strtoull(value, NULL, 10); - else if(hash == hash_Icmp6OutRouterAdvertisements && strcmp(name, "Icmp6OutRouterAdvertisements") == 0) Icmp6OutRouterAdvertisements = strtoull(value, NULL, 10); - else if(hash == hash_Icmp6OutNeighborSolicits && strcmp(name, "Icmp6OutNeighborSolicits") == 0) Icmp6OutNeighborSolicits = strtoull(value, NULL, 10); - else if(hash == hash_Icmp6OutNeighborAdvertisements && strcmp(name, "Icmp6OutNeighborAdvertisements") == 0) Icmp6OutNeighborAdvertisements = strtoull(value, NULL, 10); - else if(hash == hash_Icmp6OutRedirects && strcmp(name, "Icmp6OutRedirects") == 0) Icmp6OutRedirects = strtoull(value, NULL, 10); - else if(hash == hash_Icmp6OutMLDv2Reports && strcmp(name, "Icmp6OutMLDv2Reports") == 0) Icmp6OutMLDv2Reports = strtoull(value, NULL, 10); - else if(hash == hash_Icmp6InType1 && strcmp(name, "Icmp6InType1") == 0) Icmp6InType1 = strtoull(value, NULL, 10); - else if(hash == hash_Icmp6InType128 && strcmp(name, "Icmp6InType128") == 0) Icmp6InType128 = strtoull(value, NULL, 10); - else if(hash == hash_Icmp6InType129 && strcmp(name, "Icmp6InType129") == 0) Icmp6InType129 = strtoull(value, NULL, 10); - else if(hash == hash_Icmp6InType136 && strcmp(name, "Icmp6InType136") == 0) Icmp6InType136 = strtoull(value, NULL, 10); - else if(hash == hash_Icmp6OutType1 && strcmp(name, "Icmp6OutType1") == 0) Icmp6OutType1 = strtoull(value, NULL, 10); - else if(hash == hash_Icmp6OutType128 && strcmp(name, "Icmp6OutType128") == 0) Icmp6OutType128 = strtoull(value, NULL, 10); - else if(hash == hash_Icmp6OutType129 && strcmp(name, "Icmp6OutType129") == 0) Icmp6OutType129 = strtoull(value, NULL, 10); - else if(hash == hash_Icmp6OutType133 && strcmp(name, "Icmp6OutType133") == 0) Icmp6OutType133 = strtoull(value, NULL, 10); - else if(hash == hash_Icmp6OutType135 && strcmp(name, "Icmp6OutType135") == 0) Icmp6OutType135 = strtoull(value, NULL, 10); - else if(hash == hash_Icmp6OutType143 && strcmp(name, "Icmp6OutType143") == 0) Icmp6OutType143 = strtoull(value, NULL, 10); - else if(hash == hash_Udp6InDatagrams && strcmp(name, "Udp6InDatagrams") == 0) Udp6InDatagrams = strtoull(value, NULL, 10); - else if(hash == hash_Udp6NoPorts && strcmp(name, "Udp6NoPorts") == 0) Udp6NoPorts = strtoull(value, NULL, 10); - else if(hash == hash_Udp6InErrors && strcmp(name, "Udp6InErrors") == 0) Udp6InErrors = strtoull(value, NULL, 10); - else if(hash == hash_Udp6OutDatagrams && strcmp(name, "Udp6OutDatagrams") == 0) Udp6OutDatagrams = strtoull(value, NULL, 10); - else if(hash == hash_Udp6RcvbufErrors && strcmp(name, "Udp6RcvbufErrors") == 0) Udp6RcvbufErrors = strtoull(value, NULL, 10); - else if(hash == hash_Udp6SndbufErrors && strcmp(name, "Udp6SndbufErrors") == 0) Udp6SndbufErrors = strtoull(value, NULL, 10); - else if(hash == hash_Udp6InCsumErrors && strcmp(name, "Udp6InCsumErrors") == 0) Udp6InCsumErrors = strtoull(value, NULL, 10); - else if(hash == hash_Udp6IgnoredMulti && strcmp(name, "Udp6IgnoredMulti") == 0) Udp6IgnoredMulti = strtoull(value, NULL, 10); - else if(hash == hash_UdpLite6InDatagrams && strcmp(name, "UdpLite6InDatagrams") == 0) UdpLite6InDatagrams = strtoull(value, NULL, 10); - else if(hash == hash_UdpLite6NoPorts && strcmp(name, "UdpLite6NoPorts") == 0) UdpLite6NoPorts = strtoull(value, NULL, 10); - else if(hash == hash_UdpLite6InErrors && strcmp(name, "UdpLite6InErrors") == 0) UdpLite6InErrors = strtoull(value, NULL, 10); - else if(hash == hash_UdpLite6OutDatagrams && strcmp(name, "UdpLite6OutDatagrams") == 0) UdpLite6OutDatagrams = strtoull(value, NULL, 10); - else if(hash == hash_UdpLite6RcvbufErrors && strcmp(name, "UdpLite6RcvbufErrors") == 0) UdpLite6RcvbufErrors = strtoull(value, NULL, 10); - else if(hash == hash_UdpLite6SndbufErrors && strcmp(name, "UdpLite6SndbufErrors") == 0) UdpLite6SndbufErrors = strtoull(value, NULL, 10); - else if(hash == hash_UdpLite6InCsumErrors && strcmp(name, "UdpLite6InCsumErrors") == 0) UdpLite6InCsumErrors = strtoull(value, NULL, 10); + if(unlikely(hash == hash_Ip6InReceives && strcmp(name, "Ip6InReceives") == 0)) Ip6InReceives = strtoull(value, NULL, 10); + else if(unlikely(hash == hash_Ip6InHdrErrors && strcmp(name, "Ip6InHdrErrors") == 0)) Ip6InHdrErrors = strtoull(value, NULL, 10); + else if(unlikely(hash == hash_Ip6InTooBigErrors && strcmp(name, "Ip6InTooBigErrors") == 0)) Ip6InTooBigErrors = strtoull(value, NULL, 10); + else if(unlikely(hash == hash_Ip6InNoRoutes && strcmp(name, "Ip6InNoRoutes") == 0)) Ip6InNoRoutes = strtoull(value, NULL, 10); + else if(unlikely(hash == hash_Ip6InAddrErrors && strcmp(name, "Ip6InAddrErrors") == 0)) Ip6InAddrErrors = strtoull(value, NULL, 10); + else if(unlikely(hash == hash_Ip6InUnknownProtos && strcmp(name, "Ip6InUnknownProtos") == 0)) Ip6InUnknownProtos = strtoull(value, NULL, 10); + else if(unlikely(hash == hash_Ip6InTruncatedPkts && strcmp(name, "Ip6InTruncatedPkts") == 0)) Ip6InTruncatedPkts = strtoull(value, NULL, 10); + else if(unlikely(hash == hash_Ip6InDiscards && strcmp(name, "Ip6InDiscards") == 0)) Ip6InDiscards = strtoull(value, NULL, 10); + else if(unlikely(hash == hash_Ip6InDelivers && strcmp(name, "Ip6InDelivers") == 0)) Ip6InDelivers = strtoull(value, NULL, 10); + else if(unlikely(hash == hash_Ip6OutForwDatagrams && strcmp(name, "Ip6OutForwDatagrams") == 0)) Ip6OutForwDatagrams = strtoull(value, NULL, 10); + else if(unlikely(hash == hash_Ip6OutRequests && strcmp(name, "Ip6OutRequests") == 0)) Ip6OutRequests = strtoull(value, NULL, 10); + else if(unlikely(hash == hash_Ip6OutDiscards && strcmp(name, "Ip6OutDiscards") == 0)) Ip6OutDiscards = strtoull(value, NULL, 10); + else if(unlikely(hash == hash_Ip6OutNoRoutes && strcmp(name, "Ip6OutNoRoutes") == 0)) Ip6OutNoRoutes = strtoull(value, NULL, 10); + else if(unlikely(hash == hash_Ip6ReasmTimeout && strcmp(name, "Ip6ReasmTimeout") == 0)) Ip6ReasmTimeout = strtoull(value, NULL, 10); + else if(unlikely(hash == hash_Ip6ReasmReqds && strcmp(name, "Ip6ReasmReqds") == 0)) Ip6ReasmReqds = strtoull(value, NULL, 10); + else if(unlikely(hash == hash_Ip6ReasmOKs && strcmp(name, "Ip6ReasmOKs") == 0)) Ip6ReasmOKs = strtoull(value, NULL, 10); + else if(unlikely(hash == hash_Ip6ReasmFails && strcmp(name, "Ip6ReasmFails") == 0)) Ip6ReasmFails = strtoull(value, NULL, 10); + else if(unlikely(hash == hash_Ip6FragOKs && strcmp(name, "Ip6FragOKs") == 0)) Ip6FragOKs = strtoull(value, NULL, 10); + else if(unlikely(hash == hash_Ip6FragFails && strcmp(name, "Ip6FragFails") == 0)) Ip6FragFails = strtoull(value, NULL, 10); + else if(unlikely(hash == hash_Ip6FragCreates && strcmp(name, "Ip6FragCreates") == 0)) Ip6FragCreates = strtoull(value, NULL, 10); + else if(unlikely(hash == hash_Ip6InMcastPkts && strcmp(name, "Ip6InMcastPkts") == 0)) Ip6InMcastPkts = strtoull(value, NULL, 10); + else if(unlikely(hash == hash_Ip6OutMcastPkts && strcmp(name, "Ip6OutMcastPkts") == 0)) Ip6OutMcastPkts = strtoull(value, NULL, 10); + else if(unlikely(hash == hash_Ip6InOctets && strcmp(name, "Ip6InOctets") == 0)) Ip6InOctets = strtoull(value, NULL, 10); + else if(unlikely(hash == hash_Ip6OutOctets && strcmp(name, "Ip6OutOctets") == 0)) Ip6OutOctets = strtoull(value, NULL, 10); + else if(unlikely(hash == hash_Ip6InMcastOctets && strcmp(name, "Ip6InMcastOctets") == 0)) Ip6InMcastOctets = strtoull(value, NULL, 10); + else if(unlikely(hash == hash_Ip6OutMcastOctets && strcmp(name, "Ip6OutMcastOctets") == 0)) Ip6OutMcastOctets = strtoull(value, NULL, 10); + else if(unlikely(hash == hash_Ip6InBcastOctets && strcmp(name, "Ip6InBcastOctets") == 0)) Ip6InBcastOctets = strtoull(value, NULL, 10); + else if(unlikely(hash == hash_Ip6OutBcastOctets && strcmp(name, "Ip6OutBcastOctets") == 0)) Ip6OutBcastOctets = strtoull(value, NULL, 10); + else if(unlikely(hash == hash_Ip6InNoECTPkts && strcmp(name, "Ip6InNoECTPkts") == 0)) Ip6InNoECTPkts = strtoull(value, NULL, 10); + else if(unlikely(hash == hash_Ip6InECT1Pkts && strcmp(name, "Ip6InECT1Pkts") == 0)) Ip6InECT1Pkts = strtoull(value, NULL, 10); + else if(unlikely(hash == hash_Ip6InECT0Pkts && strcmp(name, "Ip6InECT0Pkts") == 0)) Ip6InECT0Pkts = strtoull(value, NULL, 10); + else if(unlikely(hash == hash_Ip6InCEPkts && strcmp(name, "Ip6InCEPkts") == 0)) Ip6InCEPkts = strtoull(value, NULL, 10); + else if(unlikely(hash == hash_Icmp6InMsgs && strcmp(name, "Icmp6InMsgs") == 0)) Icmp6InMsgs = strtoull(value, NULL, 10); + else if(unlikely(hash == hash_Icmp6InErrors && strcmp(name, "Icmp6InErrors") == 0)) Icmp6InErrors = strtoull(value, NULL, 10); + else if(unlikely(hash == hash_Icmp6OutMsgs && strcmp(name, "Icmp6OutMsgs") == 0)) Icmp6OutMsgs = strtoull(value, NULL, 10); + else if(unlikely(hash == hash_Icmp6OutErrors && strcmp(name, "Icmp6OutErrors") == 0)) Icmp6OutErrors = strtoull(value, NULL, 10); + else if(unlikely(hash == hash_Icmp6InCsumErrors && strcmp(name, "Icmp6InCsumErrors") == 0)) Icmp6InCsumErrors = strtoull(value, NULL, 10); + else if(unlikely(hash == hash_Icmp6InDestUnreachs && strcmp(name, "Icmp6InDestUnreachs") == 0)) Icmp6InDestUnreachs = strtoull(value, NULL, 10); + else if(unlikely(hash == hash_Icmp6InPktTooBigs && strcmp(name, "Icmp6InPktTooBigs") == 0)) Icmp6InPktTooBigs = strtoull(value, NULL, 10); + else if(unlikely(hash == hash_Icmp6InTimeExcds && strcmp(name, "Icmp6InTimeExcds") == 0)) Icmp6InTimeExcds = strtoull(value, NULL, 10); + else if(unlikely(hash == hash_Icmp6InParmProblems && strcmp(name, "Icmp6InParmProblems") == 0)) Icmp6InParmProblems = strtoull(value, NULL, 10); + else if(unlikely(hash == hash_Icmp6InEchos && strcmp(name, "Icmp6InEchos") == 0)) Icmp6InEchos = strtoull(value, NULL, 10); + else if(unlikely(hash == hash_Icmp6InEchoReplies && strcmp(name, "Icmp6InEchoReplies") == 0)) Icmp6InEchoReplies = strtoull(value, NULL, 10); + else if(unlikely(hash == hash_Icmp6InGroupMembQueries && strcmp(name, "Icmp6InGroupMembQueries") == 0)) Icmp6InGroupMembQueries = strtoull(value, NULL, 10); + else if(unlikely(hash == hash_Icmp6InGroupMembResponses && strcmp(name, "Icmp6InGroupMembResponses") == 0)) Icmp6InGroupMembResponses = strtoull(value, NULL, 10); + else if(unlikely(hash == hash_Icmp6InGroupMembReductions && strcmp(name, "Icmp6InGroupMembReductions") == 0)) Icmp6InGroupMembReductions = strtoull(value, NULL, 10); + else if(unlikely(hash == hash_Icmp6InRouterSolicits && strcmp(name, "Icmp6InRouterSolicits") == 0)) Icmp6InRouterSolicits = strtoull(value, NULL, 10); + else if(unlikely(hash == hash_Icmp6InRouterAdvertisements && strcmp(name, "Icmp6InRouterAdvertisements") == 0)) Icmp6InRouterAdvertisements = strtoull(value, NULL, 10); + else if(unlikely(hash == hash_Icmp6InNeighborSolicits && strcmp(name, "Icmp6InNeighborSolicits") == 0)) Icmp6InNeighborSolicits = strtoull(value, NULL, 10); + else if(unlikely(hash == hash_Icmp6InNeighborAdvertisements && strcmp(name, "Icmp6InNeighborAdvertisements") == 0)) Icmp6InNeighborAdvertisements = strtoull(value, NULL, 10); + else if(unlikely(hash == hash_Icmp6InRedirects && strcmp(name, "Icmp6InRedirects") == 0)) Icmp6InRedirects = strtoull(value, NULL, 10); + else if(unlikely(hash == hash_Icmp6InMLDv2Reports && strcmp(name, "Icmp6InMLDv2Reports") == 0)) Icmp6InMLDv2Reports = strtoull(value, NULL, 10); + else if(unlikely(hash == hash_Icmp6OutDestUnreachs && strcmp(name, "Icmp6OutDestUnreachs") == 0)) Icmp6OutDestUnreachs = strtoull(value, NULL, 10); + else if(unlikely(hash == hash_Icmp6OutPktTooBigs && strcmp(name, "Icmp6OutPktTooBigs") == 0)) Icmp6OutPktTooBigs = strtoull(value, NULL, 10); + else if(unlikely(hash == hash_Icmp6OutTimeExcds && strcmp(name, "Icmp6OutTimeExcds") == 0)) Icmp6OutTimeExcds = strtoull(value, NULL, 10); + else if(unlikely(hash == hash_Icmp6OutParmProblems && strcmp(name, "Icmp6OutParmProblems") == 0)) Icmp6OutParmProblems = strtoull(value, NULL, 10); + else if(unlikely(hash == hash_Icmp6OutEchos && strcmp(name, "Icmp6OutEchos") == 0)) Icmp6OutEchos = strtoull(value, NULL, 10); + else if(unlikely(hash == hash_Icmp6OutEchoReplies && strcmp(name, "Icmp6OutEchoReplies") == 0)) Icmp6OutEchoReplies = strtoull(value, NULL, 10); + else if(unlikely(hash == hash_Icmp6OutGroupMembQueries && strcmp(name, "Icmp6OutGroupMembQueries") == 0)) Icmp6OutGroupMembQueries = strtoull(value, NULL, 10); + else if(unlikely(hash == hash_Icmp6OutGroupMembResponses && strcmp(name, "Icmp6OutGroupMembResponses") == 0)) Icmp6OutGroupMembResponses = strtoull(value, NULL, 10); + else if(unlikely(hash == hash_Icmp6OutGroupMembReductions && strcmp(name, "Icmp6OutGroupMembReductions") == 0)) Icmp6OutGroupMembReductions = strtoull(value, NULL, 10); + else if(unlikely(hash == hash_Icmp6OutRouterSolicits && strcmp(name, "Icmp6OutRouterSolicits") == 0)) Icmp6OutRouterSolicits = strtoull(value, NULL, 10); + else if(unlikely(hash == hash_Icmp6OutRouterAdvertisements && strcmp(name, "Icmp6OutRouterAdvertisements") == 0)) Icmp6OutRouterAdvertisements = strtoull(value, NULL, 10); + else if(unlikely(hash == hash_Icmp6OutNeighborSolicits && strcmp(name, "Icmp6OutNeighborSolicits") == 0)) Icmp6OutNeighborSolicits = strtoull(value, NULL, 10); + else if(unlikely(hash == hash_Icmp6OutNeighborAdvertisements && strcmp(name, "Icmp6OutNeighborAdvertisements") == 0)) Icmp6OutNeighborAdvertisements = strtoull(value, NULL, 10); + else if(unlikely(hash == hash_Icmp6OutRedirects && strcmp(name, "Icmp6OutRedirects") == 0)) Icmp6OutRedirects = strtoull(value, NULL, 10); + else if(unlikely(hash == hash_Icmp6OutMLDv2Reports && strcmp(name, "Icmp6OutMLDv2Reports") == 0)) Icmp6OutMLDv2Reports = strtoull(value, NULL, 10); + else if(unlikely(hash == hash_Icmp6InType1 && strcmp(name, "Icmp6InType1") == 0)) Icmp6InType1 = strtoull(value, NULL, 10); + else if(unlikely(hash == hash_Icmp6InType128 && strcmp(name, "Icmp6InType128") == 0)) Icmp6InType128 = strtoull(value, NULL, 10); + else if(unlikely(hash == hash_Icmp6InType129 && strcmp(name, "Icmp6InType129") == 0)) Icmp6InType129 = strtoull(value, NULL, 10); + else if(unlikely(hash == hash_Icmp6InType136 && strcmp(name, "Icmp6InType136") == 0)) Icmp6InType136 = strtoull(value, NULL, 10); + else if(unlikely(hash == hash_Icmp6OutType1 && strcmp(name, "Icmp6OutType1") == 0)) Icmp6OutType1 = strtoull(value, NULL, 10); + else if(unlikely(hash == hash_Icmp6OutType128 && strcmp(name, "Icmp6OutType128") == 0)) Icmp6OutType128 = strtoull(value, NULL, 10); + else if(unlikely(hash == hash_Icmp6OutType129 && strcmp(name, "Icmp6OutType129") == 0)) Icmp6OutType129 = strtoull(value, NULL, 10); + else if(unlikely(hash == hash_Icmp6OutType133 && strcmp(name, "Icmp6OutType133") == 0)) Icmp6OutType133 = strtoull(value, NULL, 10); + else if(unlikely(hash == hash_Icmp6OutType135 && strcmp(name, "Icmp6OutType135") == 0)) Icmp6OutType135 = strtoull(value, NULL, 10); + else if(unlikely(hash == hash_Icmp6OutType143 && strcmp(name, "Icmp6OutType143") == 0)) Icmp6OutType143 = strtoull(value, NULL, 10); + else if(unlikely(hash == hash_Udp6InDatagrams && strcmp(name, "Udp6InDatagrams") == 0)) Udp6InDatagrams = strtoull(value, NULL, 10); + else if(unlikely(hash == hash_Udp6NoPorts && strcmp(name, "Udp6NoPorts") == 0)) Udp6NoPorts = strtoull(value, NULL, 10); + else if(unlikely(hash == hash_Udp6InErrors && strcmp(name, "Udp6InErrors") == 0)) Udp6InErrors = strtoull(value, NULL, 10); + else if(unlikely(hash == hash_Udp6OutDatagrams && strcmp(name, "Udp6OutDatagrams") == 0)) Udp6OutDatagrams = strtoull(value, NULL, 10); + else if(unlikely(hash == hash_Udp6RcvbufErrors && strcmp(name, "Udp6RcvbufErrors") == 0)) Udp6RcvbufErrors = strtoull(value, NULL, 10); + else if(unlikely(hash == hash_Udp6SndbufErrors && strcmp(name, "Udp6SndbufErrors") == 0)) Udp6SndbufErrors = strtoull(value, NULL, 10); + else if(unlikely(hash == hash_Udp6InCsumErrors && strcmp(name, "Udp6InCsumErrors") == 0)) Udp6InCsumErrors = strtoull(value, NULL, 10); + else if(unlikely(hash == hash_Udp6IgnoredMulti && strcmp(name, "Udp6IgnoredMulti") == 0)) Udp6IgnoredMulti = strtoull(value, NULL, 10); + else if(unlikely(hash == hash_UdpLite6InDatagrams && strcmp(name, "UdpLite6InDatagrams") == 0)) UdpLite6InDatagrams = strtoull(value, NULL, 10); + else if(unlikely(hash == hash_UdpLite6NoPorts && strcmp(name, "UdpLite6NoPorts") == 0)) UdpLite6NoPorts = strtoull(value, NULL, 10); + else if(unlikely(hash == hash_UdpLite6InErrors && strcmp(name, "UdpLite6InErrors") == 0)) UdpLite6InErrors = strtoull(value, NULL, 10); + else if(unlikely(hash == hash_UdpLite6OutDatagrams && strcmp(name, "UdpLite6OutDatagrams") == 0)) UdpLite6OutDatagrams = strtoull(value, NULL, 10); + else if(unlikely(hash == hash_UdpLite6RcvbufErrors && strcmp(name, "UdpLite6RcvbufErrors") == 0)) UdpLite6RcvbufErrors = strtoull(value, NULL, 10); + else if(unlikely(hash == hash_UdpLite6SndbufErrors && strcmp(name, "UdpLite6SndbufErrors") == 0)) UdpLite6SndbufErrors = strtoull(value, NULL, 10); + else if(unlikely(hash == hash_UdpLite6InCsumErrors && strcmp(name, "UdpLite6InCsumErrors") == 0)) UdpLite6InCsumErrors = strtoull(value, NULL, 10); } RRDSET *st; @@ -460,7 +462,7 @@ int do_proc_net_snmp6(int update_every, unsigned long long dt) { if(do_bandwidth == CONFIG_ONDEMAND_YES || (do_bandwidth == CONFIG_ONDEMAND_ONDEMAND && (Ip6InOctets || Ip6OutOctets))) { do_bandwidth = CONFIG_ONDEMAND_YES; st = rrdset_find("system.ipv6"); - if(!st) { + if(unlikely(!st)) { st = rrdset_create("system", "ipv6", NULL, "network", NULL, "IPv6 Bandwidth", "kilobits/s", 500, update_every, RRDSET_TYPE_AREA); rrddim_add(st, "received", NULL, 8, 1024, RRDDIM_INCREMENTAL); @@ -478,7 +480,7 @@ int do_proc_net_snmp6(int update_every, unsigned long long dt) { if(do_ip_packets == CONFIG_ONDEMAND_YES || (do_ip_packets == CONFIG_ONDEMAND_ONDEMAND && (Ip6InReceives || Ip6OutRequests || Ip6InDelivers || Ip6OutForwDatagrams))) { do_ip_packets = CONFIG_ONDEMAND_YES; st = rrdset_find(RRD_TYPE_NET_SNMP6 ".packets"); - if(!st) { + if(unlikely(!st)) { st = rrdset_create(RRD_TYPE_NET_SNMP6, "packets", NULL, "packets", NULL, "IPv6 Packets", "packets/s", 3000, update_every, RRDSET_TYPE_LINE); rrddim_add(st, "received", NULL, 1, 1, RRDDIM_INCREMENTAL); @@ -500,7 +502,7 @@ int do_proc_net_snmp6(int update_every, unsigned long long dt) { if(do_ip_fragsout == CONFIG_ONDEMAND_YES || (do_ip_fragsout == CONFIG_ONDEMAND_ONDEMAND && (Ip6FragOKs || Ip6FragFails || Ip6FragCreates))) { do_ip_fragsout = CONFIG_ONDEMAND_YES; st = rrdset_find(RRD_TYPE_NET_SNMP6 ".fragsout"); - if(!st) { + if(unlikely(!st)) { st = rrdset_create(RRD_TYPE_NET_SNMP6, "fragsout", NULL, "fragments", NULL, "IPv6 Fragments Sent", "packets/s", 3010, update_every, RRDSET_TYPE_LINE); st->isdetail = 1; @@ -527,7 +529,7 @@ int do_proc_net_snmp6(int update_every, unsigned long long dt) { ))) { do_ip_fragsin = CONFIG_ONDEMAND_YES; st = rrdset_find(RRD_TYPE_NET_SNMP6 ".fragsin"); - if(!st) { + if(unlikely(!st)) { st = rrdset_create(RRD_TYPE_NET_SNMP6, "fragsin", NULL, "fragments", NULL, "IPv6 Fragments Reassembly", "packets/s", 3011, update_every, RRDSET_TYPE_LINE); st->isdetail = 1; @@ -560,7 +562,7 @@ int do_proc_net_snmp6(int update_every, unsigned long long dt) { ))) { do_ip_errors = CONFIG_ONDEMAND_YES; st = rrdset_find(RRD_TYPE_NET_SNMP6 ".errors"); - if(!st) { + if(unlikely(!st)) { st = rrdset_create(RRD_TYPE_NET_SNMP6, "errors", NULL, "errors", NULL, "IPv6 Errors", "packets/s", 3002, update_every, RRDSET_TYPE_LINE); st->isdetail = 1; @@ -597,7 +599,7 @@ int do_proc_net_snmp6(int update_every, unsigned long long dt) { if(do_udp_packets == CONFIG_ONDEMAND_YES || (do_udp_packets == CONFIG_ONDEMAND_ONDEMAND && (Udp6InDatagrams || Udp6OutDatagrams))) { do_udp_packets = CONFIG_ONDEMAND_YES; st = rrdset_find(RRD_TYPE_NET_SNMP6 ".udppackets"); - if(!st) { + if(unlikely(!st)) { st = rrdset_create(RRD_TYPE_NET_SNMP6, "udppackets", NULL, "udp", NULL, "IPv6 UDP Packets", "packets/s", 3601, update_every, RRDSET_TYPE_LINE); rrddim_add(st, "received", NULL, 1, 1, RRDDIM_INCREMENTAL); @@ -623,7 +625,7 @@ int do_proc_net_snmp6(int update_every, unsigned long long dt) { ))) { do_udp_errors = CONFIG_ONDEMAND_YES; st = rrdset_find(RRD_TYPE_NET_SNMP6 ".udperrors"); - if(!st) { + if(unlikely(!st)) { st = rrdset_create(RRD_TYPE_NET_SNMP6, "udperrors", NULL, "udp", NULL, "IPv6 UDP Errors", "events/s", 3701, update_every, RRDSET_TYPE_LINE); st->isdetail = 1; @@ -650,7 +652,7 @@ int do_proc_net_snmp6(int update_every, unsigned long long dt) { if(do_udplite_packets == CONFIG_ONDEMAND_YES || (do_udplite_packets == CONFIG_ONDEMAND_ONDEMAND && (UdpLite6InDatagrams || UdpLite6OutDatagrams))) { do_udplite_packets = CONFIG_ONDEMAND_YES; st = rrdset_find(RRD_TYPE_NET_SNMP6 ".udplitepackets"); - if(!st) { + if(unlikely(!st)) { st = rrdset_create(RRD_TYPE_NET_SNMP6, "udplitepackets", NULL, "udplite", NULL, "IPv6 UDPlite Packets", "packets/s", 3601, update_every, RRDSET_TYPE_LINE); rrddim_add(st, "received", NULL, 1, 1, RRDDIM_INCREMENTAL); @@ -676,7 +678,7 @@ int do_proc_net_snmp6(int update_every, unsigned long long dt) { ))) { do_udplite_errors = CONFIG_ONDEMAND_YES; st = rrdset_find(RRD_TYPE_NET_SNMP6 ".udpliteerrors"); - if(!st) { + if(unlikely(!st)) { st = rrdset_create(RRD_TYPE_NET_SNMP6, "udpliteerrors", NULL, "udplite", NULL, "IPv6 UDP Lite Errors", "events/s", 3701, update_every, RRDSET_TYPE_LINE); st->isdetail = 1; @@ -701,7 +703,7 @@ int do_proc_net_snmp6(int update_every, unsigned long long dt) { if(do_mcast == CONFIG_ONDEMAND_YES || (do_mcast == CONFIG_ONDEMAND_ONDEMAND && (Ip6OutMcastOctets || Ip6InMcastOctets))) { do_mcast = CONFIG_ONDEMAND_YES; st = rrdset_find(RRD_TYPE_NET_SNMP6 ".mcast"); - if(!st) { + if(unlikely(!st)) { st = rrdset_create(RRD_TYPE_NET_SNMP6, "mcast", NULL, "multicast", NULL, "IPv6 Multicast Bandwidth", "kilobits/s", 9000, update_every, RRDSET_TYPE_AREA); st->isdetail = 1; @@ -720,7 +722,7 @@ int do_proc_net_snmp6(int update_every, unsigned long long dt) { if(do_bcast == CONFIG_ONDEMAND_YES || (do_bcast == CONFIG_ONDEMAND_ONDEMAND && (Ip6OutBcastOctets || Ip6InBcastOctets))) { do_bcast = CONFIG_ONDEMAND_YES; st = rrdset_find(RRD_TYPE_NET_SNMP6 ".bcast"); - if(!st) { + if(unlikely(!st)) { st = rrdset_create(RRD_TYPE_NET_SNMP6, "bcast", NULL, "broadcast", NULL, "IPv6 Broadcast Bandwidth", "kilobits/s", 8000, update_every, RRDSET_TYPE_AREA); st->isdetail = 1; @@ -739,7 +741,7 @@ int do_proc_net_snmp6(int update_every, unsigned long long dt) { if(do_mcast_p == CONFIG_ONDEMAND_YES || (do_mcast_p == CONFIG_ONDEMAND_ONDEMAND && (Ip6OutMcastPkts || Ip6InMcastPkts))) { do_mcast_p = CONFIG_ONDEMAND_YES; st = rrdset_find(RRD_TYPE_NET_SNMP6 ".mcastpkts"); - if(!st) { + if(unlikely(!st)) { st = rrdset_create(RRD_TYPE_NET_SNMP6, "mcastpkts", NULL, "multicast", NULL, "IPv6 Multicast Packets", "packets/s", 9500, update_every, RRDSET_TYPE_LINE); st->isdetail = 1; @@ -758,7 +760,7 @@ int do_proc_net_snmp6(int update_every, unsigned long long dt) { if(do_icmp == CONFIG_ONDEMAND_YES || (do_icmp == CONFIG_ONDEMAND_ONDEMAND && (Icmp6InMsgs || Icmp6OutMsgs))) { do_icmp = CONFIG_ONDEMAND_YES; st = rrdset_find(RRD_TYPE_NET_SNMP6 ".icmp"); - if(!st) { + if(unlikely(!st)) { st = rrdset_create(RRD_TYPE_NET_SNMP6, "icmp", NULL, "icmp", NULL, "IPv6 ICMP Messages", "messages/s", 10000, update_every, RRDSET_TYPE_LINE); rrddim_add(st, "received", NULL, 1, 1, RRDDIM_INCREMENTAL); @@ -776,7 +778,7 @@ int do_proc_net_snmp6(int update_every, unsigned long long dt) { if(do_icmp_redir == CONFIG_ONDEMAND_YES || (do_icmp_redir == CONFIG_ONDEMAND_ONDEMAND && (Icmp6InRedirects || Icmp6OutRedirects))) { do_icmp_redir = CONFIG_ONDEMAND_YES; st = rrdset_find(RRD_TYPE_NET_SNMP6 ".icmpredir"); - if(!st) { + if(unlikely(!st)) { st = rrdset_create(RRD_TYPE_NET_SNMP6, "icmpredir", NULL, "icmp", NULL, "IPv6 ICMP Redirects", "redirects/s", 10050, update_every, RRDSET_TYPE_LINE); rrddim_add(st, "received", NULL, 1, 1, RRDDIM_INCREMENTAL); @@ -807,7 +809,7 @@ int do_proc_net_snmp6(int update_every, unsigned long long dt) { ))) { do_icmp_errors = CONFIG_ONDEMAND_YES; st = rrdset_find(RRD_TYPE_NET_SNMP6 ".icmperrors"); - if(!st) { + if(unlikely(!st)) { st = rrdset_create(RRD_TYPE_NET_SNMP6, "icmperrors", NULL, "icmp", NULL, "IPv6 ICMP Errors", "errors/s", 10100, update_every, RRDSET_TYPE_LINE); rrddim_add(st, "InErrors", NULL, 1, 1, RRDDIM_INCREMENTAL); @@ -850,7 +852,7 @@ int do_proc_net_snmp6(int update_every, unsigned long long dt) { ))) { do_icmp_echos = CONFIG_ONDEMAND_YES; st = rrdset_find(RRD_TYPE_NET_SNMP6 ".icmpechos"); - if(!st) { + if(unlikely(!st)) { st = rrdset_create(RRD_TYPE_NET_SNMP6, "icmpechos", NULL, "icmp", NULL, "IPv6 ICMP Echo", "messages/s", 10200, update_every, RRDSET_TYPE_LINE); rrddim_add(st, "InEchos", NULL, 1, 1, RRDDIM_INCREMENTAL); @@ -880,7 +882,7 @@ int do_proc_net_snmp6(int update_every, unsigned long long dt) { ))) { do_icmp_groupmemb = CONFIG_ONDEMAND_YES; st = rrdset_find(RRD_TYPE_NET_SNMP6 ".groupmemb"); - if(!st) { + if(unlikely(!st)) { st = rrdset_create(RRD_TYPE_NET_SNMP6, "groupmemb", NULL, "icmp", NULL, "IPv6 ICMP Group Membership", "messages/s", 10300, update_every, RRDSET_TYPE_LINE); rrddim_add(st, "InQueries", NULL, 1, 1, RRDDIM_INCREMENTAL); @@ -912,7 +914,7 @@ int do_proc_net_snmp6(int update_every, unsigned long long dt) { ))) { do_icmp_router = CONFIG_ONDEMAND_YES; st = rrdset_find(RRD_TYPE_NET_SNMP6 ".icmprouter"); - if(!st) { + if(unlikely(!st)) { st = rrdset_create(RRD_TYPE_NET_SNMP6, "icmprouter", NULL, "icmp", NULL, "IPv6 Router Messages", "messages/s", 10400, update_every, RRDSET_TYPE_LINE); rrddim_add(st, "InSolicits", NULL, 1, 1, RRDDIM_INCREMENTAL); @@ -940,7 +942,7 @@ int do_proc_net_snmp6(int update_every, unsigned long long dt) { ))) { do_icmp_neighbor = CONFIG_ONDEMAND_YES; st = rrdset_find(RRD_TYPE_NET_SNMP6 ".icmpneighbor"); - if(!st) { + if(unlikely(!st)) { st = rrdset_create(RRD_TYPE_NET_SNMP6, "icmpneighbor", NULL, "icmp", NULL, "IPv6 Neighbor Messages", "messages/s", 10500, update_every, RRDSET_TYPE_LINE); rrddim_add(st, "InSolicits", NULL, 1, 1, RRDDIM_INCREMENTAL); @@ -962,7 +964,7 @@ int do_proc_net_snmp6(int update_every, unsigned long long dt) { if(do_icmp_mldv2 == CONFIG_ONDEMAND_YES || (do_icmp_mldv2 == CONFIG_ONDEMAND_ONDEMAND && (Icmp6InMLDv2Reports || Icmp6OutMLDv2Reports))) { do_icmp_mldv2 = CONFIG_ONDEMAND_YES; st = rrdset_find(RRD_TYPE_NET_SNMP6 ".icmpmldv2"); - if(!st) { + if(unlikely(!st)) { st = rrdset_create(RRD_TYPE_NET_SNMP6, "icmpmldv2", NULL, "icmp", NULL, "IPv6 ICMP MLDv2 Reports", "reports/s", 10600, update_every, RRDSET_TYPE_LINE); rrddim_add(st, "received", NULL, 1, 1, RRDDIM_INCREMENTAL); @@ -992,7 +994,7 @@ int do_proc_net_snmp6(int update_every, unsigned long long dt) { ))) { do_icmp_types = CONFIG_ONDEMAND_YES; st = rrdset_find(RRD_TYPE_NET_SNMP6 ".icmptypes"); - if(!st) { + if(unlikely(!st)) { st = rrdset_create(RRD_TYPE_NET_SNMP6, "icmptypes", NULL, "icmp", NULL, "IPv6 ICMP Types", "messages/s", 10700, update_every, RRDSET_TYPE_LINE); rrddim_add(st, "InType1", NULL, 1, 1, RRDDIM_INCREMENTAL); @@ -1032,7 +1034,7 @@ int do_proc_net_snmp6(int update_every, unsigned long long dt) { ))) { do_ect = CONFIG_ONDEMAND_YES; st = rrdset_find(RRD_TYPE_NET_SNMP6 ".ect"); - if(!st) { + if(unlikely(!st)) { st = rrdset_create(RRD_TYPE_NET_SNMP6, "ect", NULL, "packets", NULL, "IPv6 ECT Packets", "packets/s", 10800, update_every, RRDSET_TYPE_LINE); rrddim_add(st, "InNoECTPkts", NULL, 1, 1, RRDDIM_INCREMENTAL); diff --git a/src/proc_net_softnet_stat.c b/src/proc_net_softnet_stat.c index b0131586..0187dbbc 100644 --- a/src/proc_net_softnet_stat.c +++ b/src/proc_net_softnet_stat.c @@ -19,28 +19,28 @@ int do_proc_net_softnet_stat(int update_every, unsigned long long dt) { static int do_per_core = -1; static uint32_t allocated_lines = 0, allocated_columns = 0, *data = NULL; - if(do_per_core == -1) do_per_core = config_get_boolean("plugin:proc:/proc/net/softnet_stat", "softnet_stat per core", 1); + if(unlikely(do_per_core == -1)) do_per_core = config_get_boolean("plugin:proc:/proc/net/softnet_stat", "softnet_stat per core", 1); - if(!ff) { + if(unlikely(!ff)) { char filename[FILENAME_MAX + 1]; snprintfz(filename, FILENAME_MAX, "%s%s", global_host_prefix, "/proc/net/softnet_stat"); ff = procfile_open(config_get("plugin:proc:/proc/net/softnet_stat", "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(unlikely(!ff)) return 0; // we return 0, so that we will retry to open it next time uint32_t lines = procfile_lines(ff), l; uint32_t words = procfile_linewords(ff, 0), w; - if(!lines || !words) { + if(unlikely(!lines || !words)) { error("Cannot read /proc/net/softnet_stat, %u lines and %u columns reported.", lines, words); return 1; } - if(lines > 200) lines = 200; - if(words > 50) words = 50; + if(unlikely(lines > 200)) lines = 200; + if(unlikely(words > 50)) words = 50; if(unlikely(!data || lines > allocated_lines || words > allocated_columns)) { freez(data); @@ -55,9 +55,10 @@ int do_proc_net_softnet_stat(int update_every, unsigned long long dt) { // parse the values for(l = 0; l < lines ;l++) { words = procfile_linewords(ff, l); - if(!words) continue; + if(unlikely(!words)) continue; - if(words > allocated_columns) words = allocated_columns; + if(unlikely(words > allocated_columns)) + words = allocated_columns; for(w = 0; w < words ; w++) { if(unlikely(softnet_column_name(w))) { @@ -68,7 +69,7 @@ int do_proc_net_softnet_stat(int update_every, unsigned long long dt) { } } - if(data[(lines * allocated_columns)] == 0) + if(unlikely(data[(lines * allocated_columns)] == 0)) lines--; RRDSET *st; @@ -76,7 +77,7 @@ int do_proc_net_softnet_stat(int update_every, unsigned long long dt) { // -------------------------------------------------------------------- st = rrdset_find_bytype("system", "softnet_stat"); - if(!st) { + if(unlikely(!st)) { st = rrdset_create("system", "softnet_stat", NULL, "softnet_stat", NULL, "System softnet_stat", "events/s", 955, update_every, RRDSET_TYPE_LINE); for(w = 0; w < allocated_columns ;w++) if(unlikely(softnet_column_name(w))) @@ -96,7 +97,7 @@ int do_proc_net_softnet_stat(int update_every, unsigned long long dt) { snprintfz(id, 50, "cpu%u_softnet_stat", l); st = rrdset_find_bytype("cpu", id); - if(!st) { + if(unlikely(!st)) { char title[100+1]; snprintfz(title, 100, "CPU%u softnet_stat", l); diff --git a/src/proc_net_stat_conntrack.c b/src/proc_net_stat_conntrack.c index 54e250bf..807a9bae 100644 --- a/src/proc_net_stat_conntrack.c +++ b/src/proc_net_stat_conntrack.c @@ -2,41 +2,43 @@ #define RRD_TYPE_NET_STAT_NETFILTER "netfilter" #define RRD_TYPE_NET_STAT_CONNTRACK "conntrack" -#define RRD_TYPE_NET_STAT_CONNTRACK_LEN strlen(RRD_TYPE_NET_STAT_CONNTRACK) int do_proc_net_stat_conntrack(int update_every, unsigned long long dt) { + (void)dt; + static procfile *ff = NULL; static int do_sockets = -1, do_new = -1, do_changes = -1, do_expect = -1, do_search = -1, do_errors = -1; - if(do_sockets == -1) do_sockets = config_get_boolean("plugin:proc:/proc/net/stat/nf_conntrack", "netfilter connections", 1); - if(do_new == -1) do_new = config_get_boolean("plugin:proc:/proc/net/stat/nf_conntrack", "netfilter new connections", 1); - if(do_changes == -1) do_changes = config_get_boolean("plugin:proc:/proc/net/stat/nf_conntrack", "netfilter connection changes", 1); - if(do_expect == -1) do_expect = config_get_boolean("plugin:proc:/proc/net/stat/nf_conntrack", "netfilter connection expectations", 1); - if(do_search == -1) do_search = config_get_boolean("plugin:proc:/proc/net/stat/nf_conntrack", "netfilter connection searches", 1); - if(do_errors == -1) do_errors = config_get_boolean("plugin:proc:/proc/net/stat/nf_conntrack", "netfilter errors", 1); - - if(dt) {}; + if(unlikely(do_sockets == -1)) { + do_sockets = config_get_boolean("plugin:proc:/proc/net/stat/nf_conntrack", "netfilter connections", 1); + do_new = config_get_boolean("plugin:proc:/proc/net/stat/nf_conntrack", "netfilter new connections", 1); + do_changes = config_get_boolean("plugin:proc:/proc/net/stat/nf_conntrack", "netfilter connection changes", 1); + do_expect = config_get_boolean("plugin:proc:/proc/net/stat/nf_conntrack", "netfilter connection expectations", 1); + do_search = config_get_boolean("plugin:proc:/proc/net/stat/nf_conntrack", "netfilter connection searches", 1); + do_errors = config_get_boolean("plugin:proc:/proc/net/stat/nf_conntrack", "netfilter errors", 1); + } - if(!ff) { + if(unlikely(!ff)) { char filename[FILENAME_MAX + 1]; snprintfz(filename, FILENAME_MAX, "%s%s", global_host_prefix, "/proc/net/stat/nf_conntrack"); ff = procfile_open(config_get("plugin:proc:/proc/net/stat/nf_conntrack", "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(unlikely(!ff)) + return 0; // we return 0, so that we will retry to open it next time uint32_t lines = procfile_lines(ff), l; - uint32_t words; unsigned long long aentries = 0, asearched = 0, afound = 0, anew = 0, ainvalid = 0, aignore = 0, adelete = 0, adelete_list = 0, ainsert = 0, ainsert_failed = 0, adrop = 0, aearly_drop = 0, aicmp_error = 0, aexpect_new = 0, aexpect_create = 0, aexpect_delete = 0, asearch_restart = 0; for(l = 1; l < lines ;l++) { - words = procfile_linewords(ff, l); - if(words < 17) { - if(words) error("Cannot read /proc/net/stat/nf_conntrack line. Expected 17 params, read %u.", words); + uint32_t words = procfile_linewords(ff, l); + if(unlikely(words < 17)) { + if(unlikely(words)) error("Cannot read /proc/net/stat/nf_conntrack line. Expected 17 params, read %u.", words); continue; } @@ -60,7 +62,7 @@ int do_proc_net_stat_conntrack(int update_every, unsigned long long dt) { texpect_delete = strtoull(procfile_lineword(ff, l, 15), NULL, 16); tsearch_restart = strtoull(procfile_lineword(ff, l, 16), NULL, 16); - if(!aentries) aentries = tentries; + if(unlikely(!aentries)) aentries = tentries; // sum all the cpus together asearched += tsearched; // conntrack.search @@ -87,7 +89,7 @@ int do_proc_net_stat_conntrack(int update_every, unsigned long long dt) { if(do_sockets) { st = rrdset_find(RRD_TYPE_NET_STAT_NETFILTER "." RRD_TYPE_NET_STAT_CONNTRACK "_sockets"); - if(!st) { + if(unlikely(!st)) { st = rrdset_create(RRD_TYPE_NET_STAT_NETFILTER, RRD_TYPE_NET_STAT_CONNTRACK "_sockets", NULL, RRD_TYPE_NET_STAT_CONNTRACK, NULL, "Connection Tracker Connections", "active connections", 3000, update_every, RRDSET_TYPE_LINE); rrddim_add(st, "connections", NULL, 1, 1, RRDDIM_ABSOLUTE); @@ -102,7 +104,7 @@ int do_proc_net_stat_conntrack(int update_every, unsigned long long dt) { if(do_new) { st = rrdset_find(RRD_TYPE_NET_STAT_NETFILTER "." RRD_TYPE_NET_STAT_CONNTRACK "_new"); - if(!st) { + if(unlikely(!st)) { st = rrdset_create(RRD_TYPE_NET_STAT_NETFILTER, RRD_TYPE_NET_STAT_CONNTRACK "_new", NULL, RRD_TYPE_NET_STAT_CONNTRACK, NULL, "Connection Tracker New Connections", "connections/s", 3001, update_every, RRDSET_TYPE_LINE); rrddim_add(st, "new", NULL, 1, 1, RRDDIM_INCREMENTAL); @@ -121,7 +123,7 @@ int do_proc_net_stat_conntrack(int update_every, unsigned long long dt) { if(do_changes) { st = rrdset_find(RRD_TYPE_NET_STAT_NETFILTER "." RRD_TYPE_NET_STAT_CONNTRACK "_changes"); - if(!st) { + if(unlikely(!st)) { st = rrdset_create(RRD_TYPE_NET_STAT_NETFILTER, RRD_TYPE_NET_STAT_CONNTRACK "_changes", NULL, RRD_TYPE_NET_STAT_CONNTRACK, NULL, "Connection Tracker Changes", "changes/s", 3002, update_every, RRDSET_TYPE_LINE); st->isdetail = 1; @@ -141,7 +143,7 @@ int do_proc_net_stat_conntrack(int update_every, unsigned long long dt) { if(do_expect) { st = rrdset_find(RRD_TYPE_NET_STAT_NETFILTER "." RRD_TYPE_NET_STAT_CONNTRACK "_expect"); - if(!st) { + if(unlikely(!st)) { st = rrdset_create(RRD_TYPE_NET_STAT_NETFILTER, RRD_TYPE_NET_STAT_CONNTRACK "_expect", NULL, RRD_TYPE_NET_STAT_CONNTRACK, NULL, "Connection Tracker Expectations", "expectations/s", 3003, update_every, RRDSET_TYPE_LINE); st->isdetail = 1; @@ -161,7 +163,7 @@ int do_proc_net_stat_conntrack(int update_every, unsigned long long dt) { if(do_search) { st = rrdset_find(RRD_TYPE_NET_STAT_NETFILTER "." RRD_TYPE_NET_STAT_CONNTRACK "_search"); - if(!st) { + if(unlikely(!st)) { st = rrdset_create(RRD_TYPE_NET_STAT_NETFILTER, RRD_TYPE_NET_STAT_CONNTRACK "_search", NULL, RRD_TYPE_NET_STAT_CONNTRACK, NULL, "Connection Tracker Searches", "searches/s", 3010, update_every, RRDSET_TYPE_LINE); st->isdetail = 1; @@ -181,7 +183,7 @@ int do_proc_net_stat_conntrack(int update_every, unsigned long long dt) { if(do_errors) { st = rrdset_find(RRD_TYPE_NET_STAT_NETFILTER "." RRD_TYPE_NET_STAT_CONNTRACK "_errors"); - if(!st) { + if(unlikely(!st)) { st = rrdset_create(RRD_TYPE_NET_STAT_NETFILTER, RRD_TYPE_NET_STAT_CONNTRACK "_errors", NULL, RRD_TYPE_NET_STAT_CONNTRACK, NULL, "Connection Tracker Errors", "events/s", 3005, update_every, RRDSET_TYPE_LINE); st->isdetail = 1; diff --git a/src/proc_net_stat_synproxy.c b/src/proc_net_stat_synproxy.c index 102805f7..01c91978 100644 --- a/src/proc_net_stat_synproxy.c +++ b/src/proc_net_stat_synproxy.c @@ -2,32 +2,35 @@ #define RRD_TYPE_NET_STAT_NETFILTER "netfilter" #define RRD_TYPE_NET_STAT_SYNPROXY "synproxy" -#define RRD_TYPE_NET_STAT_SYNPROXY_LEN strlen(RRD_TYPE_NET_STAT_SYNPROXY) int do_proc_net_stat_synproxy(int update_every, unsigned long long dt) { + (void)dt; + static int do_entries = -1, do_cookies = -1, do_syns = -1, do_reopened = -1; static procfile *ff = NULL; - if(do_entries == -1) do_entries = config_get_boolean_ondemand("plugin:proc:/proc/net/stat/synproxy", "SYNPROXY entries", CONFIG_ONDEMAND_ONDEMAND); - if(do_cookies == -1) do_cookies = config_get_boolean_ondemand("plugin:proc:/proc/net/stat/synproxy", "SYNPROXY cookies", CONFIG_ONDEMAND_ONDEMAND); - if(do_syns == -1) do_syns = config_get_boolean_ondemand("plugin:proc:/proc/net/stat/synproxy", "SYNPROXY SYN received", CONFIG_ONDEMAND_ONDEMAND); - if(do_reopened == -1) do_reopened = config_get_boolean_ondemand("plugin:proc:/proc/net/stat/synproxy", "SYNPROXY connections reopened", CONFIG_ONDEMAND_ONDEMAND); - - if(dt) {}; + if(unlikely(do_entries == -1)) { + do_entries = config_get_boolean_ondemand("plugin:proc:/proc/net/stat/synproxy", "SYNPROXY entries", CONFIG_ONDEMAND_ONDEMAND); + do_cookies = config_get_boolean_ondemand("plugin:proc:/proc/net/stat/synproxy", "SYNPROXY cookies", CONFIG_ONDEMAND_ONDEMAND); + do_syns = config_get_boolean_ondemand("plugin:proc:/proc/net/stat/synproxy", "SYNPROXY SYN received", CONFIG_ONDEMAND_ONDEMAND); + do_reopened = config_get_boolean_ondemand("plugin:proc:/proc/net/stat/synproxy", "SYNPROXY connections reopened", CONFIG_ONDEMAND_ONDEMAND); + } - if(!ff) { + if(unlikely(!ff)) { char filename[FILENAME_MAX + 1]; snprintfz(filename, FILENAME_MAX, "%s%s", global_host_prefix, "/proc/net/stat/synproxy"); ff = procfile_open(config_get("plugin:proc:/proc/net/stat/synproxy", "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(unlikely(!ff)) + return 0; // we return 0, so that we will retry to open it next time // make sure we have 3 lines size_t lines = procfile_lines(ff), l; - if(lines < 2) { + if(unlikely(lines < 2)) { error("/proc/net/stat/synproxy has %zu lines, expected no less than 2. Disabling it.", lines); return 1; } @@ -37,7 +40,8 @@ int do_proc_net_stat_synproxy(int update_every, unsigned long long dt) { // synproxy gives its values per CPU for(l = 1; l < lines ;l++) { int words = procfile_linewords(ff, l); - if(words < 6) continue; + if(unlikely(words < 6)) + continue; entries += strtoull(procfile_lineword(ff, l, 0), NULL, 16); syn_received += strtoull(procfile_lineword(ff, l, 1), NULL, 16); @@ -57,7 +61,7 @@ int do_proc_net_stat_synproxy(int update_every, unsigned long long dt) { do_entries = CONFIG_ONDEMAND_YES; st = rrdset_find(RRD_TYPE_NET_STAT_NETFILTER "." RRD_TYPE_NET_STAT_SYNPROXY "_entries"); - if(!st) { + if(unlikely(!st)) { st = rrdset_create(RRD_TYPE_NET_STAT_NETFILTER, RRD_TYPE_NET_STAT_SYNPROXY "_entries", NULL, RRD_TYPE_NET_STAT_SYNPROXY, NULL, "SYNPROXY Entries Used", "entries", 3304, update_every, RRDSET_TYPE_LINE); rrddim_add(st, "entries", NULL, 1, 1, RRDDIM_ABSOLUTE); @@ -74,7 +78,7 @@ int do_proc_net_stat_synproxy(int update_every, unsigned long long dt) { do_syns = CONFIG_ONDEMAND_YES; st = rrdset_find(RRD_TYPE_NET_STAT_NETFILTER "." RRD_TYPE_NET_STAT_SYNPROXY "_syn_received"); - if(!st) { + if(unlikely(!st)) { st = rrdset_create(RRD_TYPE_NET_STAT_NETFILTER, RRD_TYPE_NET_STAT_SYNPROXY "_syn_received", NULL, RRD_TYPE_NET_STAT_SYNPROXY, NULL, "SYNPROXY SYN Packets received", "SYN/s", 3301, update_every, RRDSET_TYPE_LINE); rrddim_add(st, "received", NULL, 1, 1, RRDDIM_INCREMENTAL); @@ -91,7 +95,7 @@ int do_proc_net_stat_synproxy(int update_every, unsigned long long dt) { do_reopened = CONFIG_ONDEMAND_YES; st = rrdset_find(RRD_TYPE_NET_STAT_NETFILTER "." RRD_TYPE_NET_STAT_SYNPROXY "_conn_reopened"); - if(!st) { + if(unlikely(!st)) { st = rrdset_create(RRD_TYPE_NET_STAT_NETFILTER, RRD_TYPE_NET_STAT_SYNPROXY "_conn_reopened", NULL, RRD_TYPE_NET_STAT_SYNPROXY, NULL, "SYNPROXY Connections Reopened", "connections/s", 3303, update_every, RRDSET_TYPE_LINE); rrddim_add(st, "reopened", NULL, 1, 1, RRDDIM_INCREMENTAL); @@ -108,7 +112,7 @@ int do_proc_net_stat_synproxy(int update_every, unsigned long long dt) { do_cookies = CONFIG_ONDEMAND_YES; st = rrdset_find(RRD_TYPE_NET_STAT_NETFILTER "." RRD_TYPE_NET_STAT_SYNPROXY "_cookies"); - if(!st) { + if(unlikely(!st)) { st = rrdset_create(RRD_TYPE_NET_STAT_NETFILTER, RRD_TYPE_NET_STAT_SYNPROXY "_cookies", NULL, RRD_TYPE_NET_STAT_SYNPROXY, NULL, "SYNPROXY TCP Cookies", "cookies/s", 3302, update_every, RRDSET_TYPE_LINE); rrddim_add(st, "valid", NULL, 1, 1, RRDDIM_INCREMENTAL); diff --git a/src/proc_self_mountinfo.c b/src/proc_self_mountinfo.c index 22be1aa6..d2708f2e 100644 --- a/src/proc_self_mountinfo.c +++ b/src/proc_self_mountinfo.c @@ -49,7 +49,7 @@ struct mountinfo *mountinfo_find(struct mountinfo *root, unsigned long major, un struct mountinfo *mi; for(mi = root; mi ; mi = mi->next) - if(mi->major == major && mi->minor == minor) + if(unlikely(mi->major == major && mi->minor == minor)) return mi; return NULL; @@ -62,12 +62,12 @@ struct mountinfo *mountinfo_find_by_filesystem_mount_source(struct mountinfo *ro uint32_t filesystem_hash = simple_hash(filesystem), mount_source_hash = simple_hash(mount_source); for(mi = root; mi ; mi = mi->next) - if(mi->filesystem + if(unlikely(mi->filesystem && mi->mount_source && mi->filesystem_hash == filesystem_hash && mi->mount_source_hash == mount_source_hash && !strcmp(mi->filesystem, filesystem) - && !strcmp(mi->mount_source, mount_source)) + && !strcmp(mi->mount_source, mount_source))) return mi; return NULL; @@ -80,10 +80,10 @@ struct mountinfo *mountinfo_find_by_filesystem_super_option(struct mountinfo *ro size_t solen = strlen(super_options); for(mi = root; mi ; mi = mi->next) - if(mi->filesystem + if(unlikely(mi->filesystem && mi->super_options && mi->filesystem_hash == filesystem_hash - && !strcmp(mi->filesystem, filesystem)) { + && !strcmp(mi->filesystem, filesystem))) { // super_options is a comma separated list char *s = mi->super_options, *e; @@ -92,7 +92,7 @@ struct mountinfo *mountinfo_find_by_filesystem_super_option(struct mountinfo *ro while(*e && *e != ',') e++; size_t len = e - s; - if(len == solen && !strncmp(s, super_options, len)) + if(unlikely(len == solen && !strncmp(s, super_options, len))) return mi; if(*e == ',') s = ++e; @@ -159,25 +159,24 @@ static char *strdupz_decoding_octal(const char *string) { // read the whole mountinfo into a linked list struct mountinfo *mountinfo_read() { - procfile *ff = NULL; - char filename[FILENAME_MAX + 1]; snprintfz(filename, FILENAME_MAX, "%s/proc/self/mountinfo", global_host_prefix); - ff = procfile_open(filename, " \t", PROCFILE_FLAG_DEFAULT); - if(!ff) { + procfile *ff = procfile_open(filename, " \t", PROCFILE_FLAG_DEFAULT); + if(unlikely(!ff)) { snprintfz(filename, FILENAME_MAX, "%s/proc/1/mountinfo", global_host_prefix); ff = procfile_open(filename, " \t", PROCFILE_FLAG_DEFAULT); - if(!ff) return NULL; + if(unlikely(!ff)) return NULL; } ff = procfile_readall(ff); - if(!ff) return NULL; + if(unlikely(!ff)) + return NULL; struct mountinfo *root = NULL, *last = NULL, *mi = NULL; unsigned long l, lines = procfile_lines(ff); for(l = 0; l < lines ;l++) { - if(procfile_linewords(ff, l) < 5) + if(unlikely(procfile_linewords(ff, l) < 5)) continue; mi = mallocz(sizeof(struct mountinfo)); @@ -189,7 +188,7 @@ struct mountinfo *mountinfo_read() { char *major = procfile_lineword(ff, l, w), *minor; w++; for(minor = major; *minor && *minor != ':' ;minor++) ; - if(!*minor) { + if(unlikely(!*minor)) { error("Cannot parse major:minor on '%s' at line %lu of '%s'", major, l + 1, filename); freez(mi); continue; @@ -232,14 +231,11 @@ struct mountinfo *mountinfo_read() { // we have some optional fields // read them into a new array of pointers; - mi->optional_fields = malloc(mi->optional_fields_count * sizeof(char *)); - if(unlikely(!mi->optional_fields)) - fatal("Cannot allocate memory for %d mountinfo optional fields", mi->optional_fields_count); + mi->optional_fields = mallocz(mi->optional_fields_count * sizeof(char *)); int i; for(i = 0; i < mi->optional_fields_count ; i++) { - *mi->optional_fields[wo] = strdup(procfile_lineword(ff, l, w)); - if(!mi->optional_fields[wo]) fatal("Cannot allocate memory"); + *mi->optional_fields[wo] = strdupz(procfile_lineword(ff, l, w)); wo++; } } @@ -258,10 +254,10 @@ struct mountinfo *mountinfo_read() { mi->super_options = strdupz(procfile_lineword(ff, l, w)); w++; - if(ME_DUMMY(mi->mount_source, mi->filesystem)) + if(unlikely(ME_DUMMY(mi->mount_source, mi->filesystem))) mi->flags |= MOUNTINFO_IS_DUMMY; - if(ME_REMOTE(mi->mount_source, mi->filesystem)) + if(unlikely(ME_REMOTE(mi->mount_source, mi->filesystem))) mi->flags |= MOUNTINFO_IS_REMOTE; // mark as BIND the duplicates (i.e. same filesystem + same source) @@ -301,10 +297,10 @@ struct mountinfo *mountinfo_read() { // check if it has size { struct statvfs buff_statvfs; - if(statvfs(mi->mount_point, &buff_statvfs) < 0) { + if(unlikely(statvfs(mi->mount_point, &buff_statvfs) < 0)) { mi->flags |= MOUNTINFO_NO_STAT; } - else if(!buff_statvfs.f_blocks /* || !buff_statvfs.f_files */) { + else if(unlikely(!buff_statvfs.f_blocks /* || !buff_statvfs.f_files */)) { mi->flags |= MOUNTINFO_NO_SIZE; } } @@ -353,10 +349,10 @@ struct mountinfo *mountinfo_read() { while ((mnt = getmntent_r(fp, &mntbuf, buf, 4096))) { char *bind = hasmntopt(mnt, "bind"); - if(bind) { + if(unlikely(bind)) { struct mountinfo *mi; for(mi = root; mi ; mi = mi->next) { - if(strcmp(mnt->mnt_dir, mi->mount_point) == 0) { + if(unlikely(strcmp(mnt->mnt_dir, mi->mount_point) == 0)) { fprintf(stderr, "Mount point '%s' is BIND\n", mi->mount_point); mi->flags |= MOUNTINFO_IS_BIND; break; @@ -364,7 +360,7 @@ struct mountinfo *mountinfo_read() { } #ifdef NETDATA_INTERNAL_CHECKS - if(!mi) { + if(unlikely(!mi)) { error("Mount point '%s' not found in /proc/self/mountinfo", mnt->mnt_dir); } #endif diff --git a/src/proc_softirqs.c b/src/proc_softirqs.c index ebbbf2ae..818a6a70 100644 --- a/src/proc_softirqs.c +++ b/src/proc_softirqs.c @@ -21,7 +21,7 @@ static inline struct interrupt *get_interrupts_array(int lines, int cpus) { static struct interrupt *irrs = NULL; static int allocated = 0; - if(lines > allocated) { + if(unlikely(lines > allocated)) { irrs = (struct interrupt *)reallocz(irrs, lines * recordsize(cpus)); allocated = lines; } @@ -30,43 +30,44 @@ static inline struct interrupt *get_interrupts_array(int lines, int cpus) { } int do_proc_softirqs(int update_every, unsigned long long dt) { + (void)dt; + static procfile *ff = NULL; static int cpus = -1, do_per_core = -1; struct interrupt *irrs = NULL; - if(dt) {}; - - if(do_per_core == -1) do_per_core = config_get_boolean("plugin:proc:/proc/softirqs", "interrupts per core", 1); + if(unlikely(do_per_core == -1)) do_per_core = config_get_boolean("plugin:proc:/proc/softirqs", "interrupts per core", 1); - if(!ff) { + if(unlikely(!ff)) { char filename[FILENAME_MAX + 1]; snprintfz(filename, FILENAME_MAX, "%s%s", global_host_prefix, "/proc/softirqs"); ff = procfile_open(config_get("plugin:proc:/proc/softirqs", "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(unlikely(!ff)) return 0; // we return 0, so that we will retry to open it next time uint32_t lines = procfile_lines(ff), l; - uint32_t words = procfile_linewords(ff, 0), w; + uint32_t words = procfile_linewords(ff, 0); - if(!lines) { + if(unlikely(!lines)) { error("Cannot read /proc/softirqs, zero lines reported."); return 1; } // find how many CPUs are there - if(cpus == -1) { + if(unlikely(cpus == -1)) { + uint32_t w; cpus = 0; for(w = 0; w < words ; w++) { - if(strncmp(procfile_lineword(ff, 0, w), "CPU", 3) == 0) + if(unlikely(strncmp(procfile_lineword(ff, 0, w), "CPU", 3) == 0)) cpus++; } } - if(!cpus) { + if(unlikely(!cpus)) { error("PLUGIN: PROC_SOFTIRQS: Cannot find the number of CPUs in /proc/softirqs"); return 1; } @@ -82,18 +83,18 @@ int do_proc_softirqs(int update_every, unsigned long long dt) { irr->total = 0; words = procfile_linewords(ff, l); - if(!words) continue; + if(unlikely(!words)) continue; irr->id = procfile_lineword(ff, l, 0); - if(!irr->id || !irr->id[0]) continue; + if(unlikely(!irr->id || !irr->id[0])) continue; int idlen = strlen(irr->id); - if(irr->id[idlen - 1] == ':') + if(unlikely(irr->id[idlen - 1] == ':')) irr->id[idlen - 1] = '\0'; int c; for(c = 0; c < cpus ;c++) { - if((c + 1) < (int)words) + if(unlikely((c + 1) < (int)words)) irr->value[c] = strtoull(procfile_lineword(ff, l, (uint32_t)(c + 1)), NULL, 10); else irr->value[c] = 0; @@ -111,12 +112,12 @@ int do_proc_softirqs(int update_every, unsigned long long dt) { // -------------------------------------------------------------------- st = rrdset_find_bytype("system", "softirqs"); - if(!st) { + if(unlikely(!st)) { st = rrdset_create("system", "softirqs", NULL, "softirqs", NULL, "System softirqs", "softirqs/s", 950, update_every, RRDSET_TYPE_STACKED); for(l = 0; l < lines ;l++) { struct interrupt *irr = irrindex(irrs, l, cpus); - if(!irr->used) continue; + if(unlikely(!irr->used)) continue; rrddim_add(st, irr->id, irr->name, 1, 1, RRDDIM_INCREMENTAL); } } @@ -124,7 +125,7 @@ int do_proc_softirqs(int update_every, unsigned long long dt) { for(l = 0; l < lines ;l++) { struct interrupt *irr = irrindex(irrs, l, cpus); - if(!irr->used) continue; + if(unlikely(!irr->used)) continue; rrddim_set(st, irr->id, irr->total); } rrdset_done(st); @@ -137,15 +138,15 @@ int do_proc_softirqs(int update_every, unsigned long long dt) { snprintfz(id, 50, "cpu%d_softirqs", c); st = rrdset_find_bytype("cpu", id); - if(!st) { + if(unlikely(!st)) { // find if everything is zero unsigned long long core_sum = 0 ; for(l = 0; l < lines ;l++) { struct interrupt *irr = irrindex(irrs, l, cpus); - if(!irr->used) continue; + if(unlikely(!irr->used)) continue; core_sum += irr->value[c]; } - if(core_sum == 0) continue; // try next core + if(unlikely(core_sum == 0)) continue; // try next core char title[100+1]; snprintfz(title, 100, "CPU%d softirqs", c); @@ -153,7 +154,7 @@ int do_proc_softirqs(int update_every, unsigned long long dt) { for(l = 0; l < lines ;l++) { struct interrupt *irr = irrindex(irrs, l, cpus); - if(!irr->used) continue; + if(unlikely(!irr->used)) continue; rrddim_add(st, irr->id, irr->name, 1, 1, RRDDIM_INCREMENTAL); } } @@ -161,7 +162,7 @@ int do_proc_softirqs(int update_every, unsigned long long dt) { for(l = 0; l < lines ;l++) { struct interrupt *irr = irrindex(irrs, l, cpus); - if(!irr->used) continue; + if(unlikely(!irr->used)) continue; rrddim_set(st, irr->id, irr->value[c]); } rrdset_done(st); diff --git a/src/proc_stat.c b/src/proc_stat.c index 88cb820b..0e34f2ee 100644 --- a/src/proc_stat.c +++ b/src/proc_stat.c @@ -126,7 +126,7 @@ int do_proc_stat(int update_every, unsigned long long dt) { rrdset_done(st); } } - else if(hash == hash_intr && strcmp(row_key, "intr") == 0) { + else if(unlikely(hash == hash_intr && strcmp(row_key, "intr") == 0)) { unsigned long long value = strtoull(procfile_lineword(ff, l, 1), NULL, 10); // -------------------------------------------------------------------- @@ -145,7 +145,7 @@ int do_proc_stat(int update_every, unsigned long long dt) { rrdset_done(st); } } - else if(hash == hash_ctxt && strcmp(row_key, "ctxt") == 0) { + else if(unlikely(hash == hash_ctxt && strcmp(row_key, "ctxt") == 0)) { unsigned long long value = strtoull(procfile_lineword(ff, l, 1), NULL, 10); // -------------------------------------------------------------------- @@ -163,13 +163,13 @@ int do_proc_stat(int update_every, unsigned long long dt) { rrdset_done(st); } } - else if(hash == hash_processes && !processes && strcmp(row_key, "processes") == 0) { + else if(unlikely(hash == hash_processes && !processes && strcmp(row_key, "processes") == 0)) { processes = strtoull(procfile_lineword(ff, l, 1), NULL, 10); } - else if(hash == hash_procs_running && !running && strcmp(row_key, "procs_running") == 0) { + else if(unlikely(hash == hash_procs_running && !running && strcmp(row_key, "procs_running") == 0)) { running = strtoull(procfile_lineword(ff, l, 1), NULL, 10); } - else if(hash == hash_procs_blocked && !blocked && strcmp(row_key, "procs_blocked") == 0) { + else if(unlikely(hash == hash_procs_blocked && !blocked && strcmp(row_key, "procs_blocked") == 0)) { blocked = strtoull(procfile_lineword(ff, l, 1), NULL, 10); } } diff --git a/src/proc_sys_kernel_random_entropy_avail.c b/src/proc_sys_kernel_random_entropy_avail.c index 9515dad6..bde74f45 100644 --- a/src/proc_sys_kernel_random_entropy_avail.c +++ b/src/proc_sys_kernel_random_entropy_avail.c @@ -1,24 +1,24 @@ #include "common.h" int do_proc_sys_kernel_random_entropy_avail(int update_every, unsigned long long dt) { - static procfile *ff = NULL; + (void)dt; - if(dt) {} ; + static procfile *ff = NULL; - if(!ff) { + if(unlikely(!ff)) { char filename[FILENAME_MAX + 1]; snprintfz(filename, FILENAME_MAX, "%s%s", global_host_prefix, "/proc/sys/kernel/random/entropy_avail"); ff = procfile_open(config_get("plugin:proc:/proc/sys/kernel/random/entropy_avail", "filename to monitor", filename), "", 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(unlikely(!ff)) return 0; // we return 0, so that we will retry to open it next time unsigned long long entropy = strtoull(procfile_lineword(ff, 0, 0), NULL, 10); RRDSET *st = rrdset_find_bytype("system", "entropy"); - if(!st) { + if(unlikely(!st)) { st = rrdset_create("system", "entropy", NULL, "entropy", NULL, "Available Entropy", "entropy", 1000, update_every, RRDSET_TYPE_LINE); rrddim_add(st, "entropy", NULL, 1, 1, RRDDIM_ABSOLUTE); } diff --git a/src/proc_vmstat.c b/src/proc_vmstat.c index 5f4e5aad..a8058398 100644 --- a/src/proc_vmstat.c +++ b/src/proc_vmstat.c @@ -1,104 +1,109 @@ #include "common.h" int do_proc_vmstat(int update_every, unsigned long long dt) { + (void)dt; + static procfile *ff = NULL; - static int do_swapio = -1, do_io = -1, do_pgfaults = -1, gen_hashes = -1; + static int do_swapio = -1, do_io = -1, do_pgfaults = -1; + + // static uint32_t hash_allocstall = 0; + // static uint32_t hash_compact_blocks_moved = 0; + // static uint32_t hash_compact_fail = 0; + // static uint32_t hash_compact_pagemigrate_failed = 0; + // static uint32_t hash_compact_pages_moved = 0; + // static uint32_t hash_compact_stall = 0; + // static uint32_t hash_compact_success = 0; + // static uint32_t hash_htlb_buddy_alloc_fail = 0; + // static uint32_t hash_htlb_buddy_alloc_success = 0; + // static uint32_t hash_kswapd_high_wmark_hit_quickly = 0; + // static uint32_t hash_kswapd_inodesteal = 0; + // static uint32_t hash_kswapd_low_wmark_hit_quickly = 0; + // static uint32_t hash_kswapd_skip_congestion_wait = 0; + // static uint32_t hash_nr_active_anon = 0; + // static uint32_t hash_nr_active_file = 0; + // static uint32_t hash_nr_anon_pages = 0; + // static uint32_t hash_nr_anon_transparent_hugepages = 0; + // static uint32_t hash_nr_bounce = 0; + // static uint32_t hash_nr_dirtied = 0; + // static uint32_t hash_nr_dirty = 0; + // static uint32_t hash_nr_dirty_background_threshold = 0; + // static uint32_t hash_nr_dirty_threshold = 0; + // static uint32_t hash_nr_file_pages = 0; + // static uint32_t hash_nr_free_pages = 0; + // static uint32_t hash_nr_inactive_anon = 0; + // static uint32_t hash_nr_inactive_file = 0; + // static uint32_t hash_nr_isolated_anon = 0; + // static uint32_t hash_nr_isolated_file = 0; + // static uint32_t hash_nr_kernel_stack = 0; + // static uint32_t hash_nr_mapped = 0; + // static uint32_t hash_nr_mlock = 0; + // static uint32_t hash_nr_page_table_pages = 0; + // static uint32_t hash_nr_shmem = 0; + // static uint32_t hash_nr_slab_reclaimable = 0; + // static uint32_t hash_nr_slab_unreclaimable = 0; + // static uint32_t hash_nr_unevictable = 0; + // static uint32_t hash_nr_unstable = 0; + // static uint32_t hash_nr_vmscan_immediate_reclaim = 0; + // static uint32_t hash_nr_vmscan_write = 0; + // static uint32_t hash_nr_writeback = 0; + // static uint32_t hash_nr_writeback_temp = 0; + // static uint32_t hash_nr_written = 0; + // static uint32_t hash_pageoutrun = 0; + // static uint32_t hash_pgactivate = 0; + // static uint32_t hash_pgalloc_dma = 0; + // static uint32_t hash_pgalloc_dma32 = 0; + // static uint32_t hash_pgalloc_movable = 0; + // static uint32_t hash_pgalloc_normal = 0; + // static uint32_t hash_pgdeactivate = 0; + static uint32_t hash_pgfault = 0; + // static uint32_t hash_pgfree = 0; + // static uint32_t hash_pginodesteal = 0; + static uint32_t hash_pgmajfault = 0; + static uint32_t hash_pgpgin = 0; + static uint32_t hash_pgpgout = 0; + // static uint32_t hash_pgrefill_dma = 0; + // static uint32_t hash_pgrefill_dma32 = 0; + // static uint32_t hash_pgrefill_movable = 0; + // static uint32_t hash_pgrefill_normal = 0; + // static uint32_t hash_pgrotated = 0; + // static uint32_t hash_pgscan_direct_dma = 0; + // static uint32_t hash_pgscan_direct_dma32 = 0; + // static uint32_t hash_pgscan_direct_movable = 0; + // static uint32_t hash_pgscan_direct_normal = 0; + // static uint32_t hash_pgscan_kswapd_dma = 0; + // static uint32_t hash_pgscan_kswapd_dma32 = 0; + // static uint32_t hash_pgscan_kswapd_movable = 0; + // static uint32_t hash_pgscan_kswapd_normal = 0; + // static uint32_t hash_pgsteal_direct_dma = 0; + // static uint32_t hash_pgsteal_direct_dma32 = 0; + // static uint32_t hash_pgsteal_direct_movable = 0; + // static uint32_t hash_pgsteal_direct_normal = 0; + // static uint32_t hash_pgsteal_kswapd_dma = 0; + // static uint32_t hash_pgsteal_kswapd_dma32 = 0; + // static uint32_t hash_pgsteal_kswapd_movable = 0; + // static uint32_t hash_pgsteal_kswapd_normal = 0; + static uint32_t hash_pswpin = 0; + static uint32_t hash_pswpout = 0; + // static uint32_t hash_slabs_scanned = 0; + // static uint32_t hash_thp_collapse_alloc = 0; + // static uint32_t hash_thp_collapse_alloc_failed = 0; + // static uint32_t hash_thp_fault_alloc = 0; + // static uint32_t hash_thp_fault_fallback = 0; + // static uint32_t hash_thp_split = 0; + // static uint32_t hash_unevictable_pgs_cleared = 0; + // static uint32_t hash_unevictable_pgs_culled = 0; + // static uint32_t hash_unevictable_pgs_mlocked = 0; + // static uint32_t hash_unevictable_pgs_mlockfreed = 0; + // static uint32_t hash_unevictable_pgs_munlocked = 0; + // static uint32_t hash_unevictable_pgs_rescued = 0; + // static uint32_t hash_unevictable_pgs_scanned = 0; + // static uint32_t hash_unevictable_pgs_stranded = 0; - // static uint32_t hash_allocstall = -1; - // static uint32_t hash_compact_blocks_moved = -1; - // static uint32_t hash_compact_fail = -1; - // static uint32_t hash_compact_pagemigrate_failed = -1; - // static uint32_t hash_compact_pages_moved = -1; - // static uint32_t hash_compact_stall = -1; - // static uint32_t hash_compact_success = -1; - // static uint32_t hash_htlb_buddy_alloc_fail = -1; - // static uint32_t hash_htlb_buddy_alloc_success = -1; - // static uint32_t hash_kswapd_high_wmark_hit_quickly = -1; - // static uint32_t hash_kswapd_inodesteal = -1; - // static uint32_t hash_kswapd_low_wmark_hit_quickly = -1; - // static uint32_t hash_kswapd_skip_congestion_wait = -1; - // static uint32_t hash_nr_active_anon = -1; - // static uint32_t hash_nr_active_file = -1; - // static uint32_t hash_nr_anon_pages = -1; - // static uint32_t hash_nr_anon_transparent_hugepages = -1; - // static uint32_t hash_nr_bounce = -1; - // static uint32_t hash_nr_dirtied = -1; - // static uint32_t hash_nr_dirty = -1; - // static uint32_t hash_nr_dirty_background_threshold = -1; - // static uint32_t hash_nr_dirty_threshold = -1; - // static uint32_t hash_nr_file_pages = -1; - // static uint32_t hash_nr_free_pages = -1; - // static uint32_t hash_nr_inactive_anon = -1; - // static uint32_t hash_nr_inactive_file = -1; - // static uint32_t hash_nr_isolated_anon = -1; - // static uint32_t hash_nr_isolated_file = -1; - // static uint32_t hash_nr_kernel_stack = -1; - // static uint32_t hash_nr_mapped = -1; - // static uint32_t hash_nr_mlock = -1; - // static uint32_t hash_nr_page_table_pages = -1; - // static uint32_t hash_nr_shmem = -1; - // static uint32_t hash_nr_slab_reclaimable = -1; - // static uint32_t hash_nr_slab_unreclaimable = -1; - // static uint32_t hash_nr_unevictable = -1; - // static uint32_t hash_nr_unstable = -1; - // static uint32_t hash_nr_vmscan_immediate_reclaim = -1; - // static uint32_t hash_nr_vmscan_write = -1; - // static uint32_t hash_nr_writeback = -1; - // static uint32_t hash_nr_writeback_temp = -1; - // static uint32_t hash_nr_written = -1; - // static uint32_t hash_pageoutrun = -1; - // static uint32_t hash_pgactivate = -1; - // static uint32_t hash_pgalloc_dma = -1; - // static uint32_t hash_pgalloc_dma32 = -1; - // static uint32_t hash_pgalloc_movable = -1; - // static uint32_t hash_pgalloc_normal = -1; - // static uint32_t hash_pgdeactivate = -1; - static uint32_t hash_pgfault = -1; - // static uint32_t hash_pgfree = -1; - // static uint32_t hash_pginodesteal = -1; - static uint32_t hash_pgmajfault = -1; - static uint32_t hash_pgpgin = -1; - static uint32_t hash_pgpgout = -1; - // static uint32_t hash_pgrefill_dma = -1; - // static uint32_t hash_pgrefill_dma32 = -1; - // static uint32_t hash_pgrefill_movable = -1; - // static uint32_t hash_pgrefill_normal = -1; - // static uint32_t hash_pgrotated = -1; - // static uint32_t hash_pgscan_direct_dma = -1; - // static uint32_t hash_pgscan_direct_dma32 = -1; - // static uint32_t hash_pgscan_direct_movable = -1; - // static uint32_t hash_pgscan_direct_normal = -1; - // static uint32_t hash_pgscan_kswapd_dma = -1; - // static uint32_t hash_pgscan_kswapd_dma32 = -1; - // static uint32_t hash_pgscan_kswapd_movable = -1; - // static uint32_t hash_pgscan_kswapd_normal = -1; - // static uint32_t hash_pgsteal_direct_dma = -1; - // static uint32_t hash_pgsteal_direct_dma32 = -1; - // static uint32_t hash_pgsteal_direct_movable = -1; - // static uint32_t hash_pgsteal_direct_normal = -1; - // static uint32_t hash_pgsteal_kswapd_dma = -1; - // static uint32_t hash_pgsteal_kswapd_dma32 = -1; - // static uint32_t hash_pgsteal_kswapd_movable = -1; - // static uint32_t hash_pgsteal_kswapd_normal = -1; - static uint32_t hash_pswpin = -1; - static uint32_t hash_pswpout = -1; - // static uint32_t hash_slabs_scanned = -1; - // static uint32_t hash_thp_collapse_alloc = -1; - // static uint32_t hash_thp_collapse_alloc_failed = -1; - // static uint32_t hash_thp_fault_alloc = -1; - // static uint32_t hash_thp_fault_fallback = -1; - // static uint32_t hash_thp_split = -1; - // static uint32_t hash_unevictable_pgs_cleared = -1; - // static uint32_t hash_unevictable_pgs_culled = -1; - // static uint32_t hash_unevictable_pgs_mlocked = -1; - // static uint32_t hash_unevictable_pgs_mlockfreed = -1; - // static uint32_t hash_unevictable_pgs_munlocked = -1; - // static uint32_t hash_unevictable_pgs_rescued = -1; - // static uint32_t hash_unevictable_pgs_scanned = -1; - // static uint32_t hash_unevictable_pgs_stranded = -1; + if(unlikely(do_swapio == -1)) { + do_swapio = config_get_boolean_ondemand("plugin:proc:/proc/vmstat", "swap i/o", CONFIG_ONDEMAND_ONDEMAND); + do_io = config_get_boolean("plugin:proc:/proc/vmstat", "disk i/o", 1); + do_pgfaults = config_get_boolean("plugin:proc:/proc/vmstat", "memory page faults", 1); - if(gen_hashes != 1) { - gen_hashes = 1; // hash_allocstall = simple_hash("allocstall"); // hash_compact_blocks_moved = simple_hash("compact_blocks_moved"); // hash_compact_fail = simple_hash("compact_fail"); @@ -193,24 +198,17 @@ int do_proc_vmstat(int update_every, unsigned long long dt) { // hash_unevictable_pgs_stranded = simple_hash("unevictable_pgs_stranded"); } - if(do_swapio == -1) do_swapio = config_get_boolean_ondemand("plugin:proc:/proc/vmstat", "swap i/o", CONFIG_ONDEMAND_ONDEMAND); - if(do_io == -1) do_io = config_get_boolean("plugin:proc:/proc/vmstat", "disk i/o", 1); - if(do_pgfaults == -1) do_pgfaults = config_get_boolean("plugin:proc:/proc/vmstat", "memory page faults", 1); - - (void)dt; - - if(!ff) { + if(unlikely(!ff)) { char filename[FILENAME_MAX + 1]; snprintfz(filename, FILENAME_MAX, "%s%s", global_host_prefix, "/proc/vmstat"); ff = procfile_open(config_get("plugin:proc:/proc/vmstat", "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(unlikely(!ff)) return 0; // we return 0, so that we will retry to open it next time uint32_t lines = procfile_lines(ff), l; - uint32_t words; // unsigned long long allocstall = 0ULL; // unsigned long long compact_blocks_moved = 0ULL; @@ -306,111 +304,111 @@ int do_proc_vmstat(int update_every, unsigned long long dt) { // unsigned long long unevictable_pgs_stranded = 0ULL; for(l = 0; l < lines ;l++) { - words = procfile_linewords(ff, l); - if(words < 2) { - if(words) error("Cannot read /proc/vmstat line %u. Expected 2 params, read %u.", l, words); + uint32_t words = procfile_linewords(ff, l); + if(unlikely(words < 2)) { + if(unlikely(words)) error("Cannot read /proc/vmstat line %u. Expected 2 params, read %u.", l, words); continue; } char *name = procfile_lineword(ff, l, 0); char * value = procfile_lineword(ff, l, 1); - if(!name || !*name || !value || !*value) continue; + if(unlikely(!name || !*name || !value || !*value)) continue; uint32_t hash = simple_hash(name); - if(0) ; - // else if(hash == hash_allocstall && strcmp(name, "allocstall") == 0) allocstall = strtoull(value, NULL, 10); - // else if(hash == hash_compact_blocks_moved && strcmp(name, "compact_blocks_moved") == 0) compact_blocks_moved = strtoull(value, NULL, 10); - // else if(hash == hash_compact_fail && strcmp(name, "compact_fail") == 0) compact_fail = strtoull(value, NULL, 10); - // else if(hash == hash_compact_pagemigrate_failed && strcmp(name, "compact_pagemigrate_failed") == 0) compact_pagemigrate_failed = strtoull(value, NULL, 10); - // else if(hash == hash_compact_pages_moved && strcmp(name, "compact_pages_moved") == 0) compact_pages_moved = strtoull(value, NULL, 10); - // else if(hash == hash_compact_stall && strcmp(name, "compact_stall") == 0) compact_stall = strtoull(value, NULL, 10); - // else if(hash == hash_compact_success && strcmp(name, "compact_success") == 0) compact_success = strtoull(value, NULL, 10); - // else if(hash == hash_htlb_buddy_alloc_fail && strcmp(name, "htlb_buddy_alloc_fail") == 0) htlb_buddy_alloc_fail = strtoull(value, NULL, 10); - // else if(hash == hash_htlb_buddy_alloc_success && strcmp(name, "htlb_buddy_alloc_success") == 0) htlb_buddy_alloc_success = strtoull(value, NULL, 10); - // else if(hash == hash_kswapd_high_wmark_hit_quickly && strcmp(name, "kswapd_high_wmark_hit_quickly") == 0) kswapd_high_wmark_hit_quickly = strtoull(value, NULL, 10); - // else if(hash == hash_kswapd_inodesteal && strcmp(name, "kswapd_inodesteal") == 0) kswapd_inodesteal = strtoull(value, NULL, 10); - // else if(hash == hash_kswapd_low_wmark_hit_quickly && strcmp(name, "kswapd_low_wmark_hit_quickly") == 0) kswapd_low_wmark_hit_quickly = strtoull(value, NULL, 10); - // else if(hash == hash_kswapd_skip_congestion_wait && strcmp(name, "kswapd_skip_congestion_wait") == 0) kswapd_skip_congestion_wait = strtoull(value, NULL, 10); - // else if(hash == hash_nr_active_anon && strcmp(name, "nr_active_anon") == 0) nr_active_anon = strtoull(value, NULL, 10); - // else if(hash == hash_nr_active_file && strcmp(name, "nr_active_file") == 0) nr_active_file = strtoull(value, NULL, 10); - // else if(hash == hash_nr_anon_pages && strcmp(name, "nr_anon_pages") == 0) nr_anon_pages = strtoull(value, NULL, 10); - // else if(hash == hash_nr_anon_transparent_hugepages && strcmp(name, "nr_anon_transparent_hugepages") == 0) nr_anon_transparent_hugepages = strtoull(value, NULL, 10); - // else if(hash == hash_nr_bounce && strcmp(name, "nr_bounce") == 0) nr_bounce = strtoull(value, NULL, 10); - // else if(hash == hash_nr_dirtied && strcmp(name, "nr_dirtied") == 0) nr_dirtied = strtoull(value, NULL, 10); - // else if(hash == hash_nr_dirty && strcmp(name, "nr_dirty") == 0) nr_dirty = strtoull(value, NULL, 10); - // else if(hash == hash_nr_dirty_background_threshold && strcmp(name, "nr_dirty_background_threshold") == 0) nr_dirty_background_threshold = strtoull(value, NULL, 10); - // else if(hash == hash_nr_dirty_threshold && strcmp(name, "nr_dirty_threshold") == 0) nr_dirty_threshold = strtoull(value, NULL, 10); - // else if(hash == hash_nr_file_pages && strcmp(name, "nr_file_pages") == 0) nr_file_pages = strtoull(value, NULL, 10); - // else if(hash == hash_nr_free_pages && strcmp(name, "nr_free_pages") == 0) nr_free_pages = strtoull(value, NULL, 10); - // else if(hash == hash_nr_inactive_anon && strcmp(name, "nr_inactive_anon") == 0) nr_inactive_anon = strtoull(value, NULL, 10); - // else if(hash == hash_nr_inactive_file && strcmp(name, "nr_inactive_file") == 0) nr_inactive_file = strtoull(value, NULL, 10); - // else if(hash == hash_nr_isolated_anon && strcmp(name, "nr_isolated_anon") == 0) nr_isolated_anon = strtoull(value, NULL, 10); - // else if(hash == hash_nr_isolated_file && strcmp(name, "nr_isolated_file") == 0) nr_isolated_file = strtoull(value, NULL, 10); - // else if(hash == hash_nr_kernel_stack && strcmp(name, "nr_kernel_stack") == 0) nr_kernel_stack = strtoull(value, NULL, 10); - // else if(hash == hash_nr_mapped && strcmp(name, "nr_mapped") == 0) nr_mapped = strtoull(value, NULL, 10); - // else if(hash == hash_nr_mlock && strcmp(name, "nr_mlock") == 0) nr_mlock = strtoull(value, NULL, 10); - // else if(hash == hash_nr_page_table_pages && strcmp(name, "nr_page_table_pages") == 0) nr_page_table_pages = strtoull(value, NULL, 10); - // else if(hash == hash_nr_shmem && strcmp(name, "nr_shmem") == 0) nr_shmem = strtoull(value, NULL, 10); - // else if(hash == hash_nr_slab_reclaimable && strcmp(name, "nr_slab_reclaimable") == 0) nr_slab_reclaimable = strtoull(value, NULL, 10); - // else if(hash == hash_nr_slab_unreclaimable && strcmp(name, "nr_slab_unreclaimable") == 0) nr_slab_unreclaimable = strtoull(value, NULL, 10); - // else if(hash == hash_nr_unevictable && strcmp(name, "nr_unevictable") == 0) nr_unevictable = strtoull(value, NULL, 10); - // else if(hash == hash_nr_unstable && strcmp(name, "nr_unstable") == 0) nr_unstable = strtoull(value, NULL, 10); - // else if(hash == hash_nr_vmscan_immediate_reclaim && strcmp(name, "nr_vmscan_immediate_reclaim") == 0) nr_vmscan_immediate_reclaim = strtoull(value, NULL, 10); - // else if(hash == hash_nr_vmscan_write && strcmp(name, "nr_vmscan_write") == 0) nr_vmscan_write = strtoull(value, NULL, 10); - // else if(hash == hash_nr_writeback && strcmp(name, "nr_writeback") == 0) nr_writeback = strtoull(value, NULL, 10); - // else if(hash == hash_nr_writeback_temp && strcmp(name, "nr_writeback_temp") == 0) nr_writeback_temp = strtoull(value, NULL, 10); - // else if(hash == hash_nr_written && strcmp(name, "nr_written") == 0) nr_written = strtoull(value, NULL, 10); - // else if(hash == hash_pageoutrun && strcmp(name, "pageoutrun") == 0) pageoutrun = strtoull(value, NULL, 10); - // else if(hash == hash_pgactivate && strcmp(name, "pgactivate") == 0) pgactivate = strtoull(value, NULL, 10); - // else if(hash == hash_pgalloc_dma && strcmp(name, "pgalloc_dma") == 0) pgalloc_dma = strtoull(value, NULL, 10); - // else if(hash == hash_pgalloc_dma32 && strcmp(name, "pgalloc_dma32") == 0) pgalloc_dma32 = strtoull(value, NULL, 10); - // else if(hash == hash_pgalloc_movable && strcmp(name, "pgalloc_movable") == 0) pgalloc_movable = strtoull(value, NULL, 10); - // else if(hash == hash_pgalloc_normal && strcmp(name, "pgalloc_normal") == 0) pgalloc_normal = strtoull(value, NULL, 10); - // else if(hash == hash_pgdeactivate && strcmp(name, "pgdeactivate") == 0) pgdeactivate = strtoull(value, NULL, 10); - else if(hash == hash_pgfault && strcmp(name, "pgfault") == 0) pgfault = strtoull(value, NULL, 10); - // else if(hash == hash_pgfree && strcmp(name, "pgfree") == 0) pgfree = strtoull(value, NULL, 10); - // else if(hash == hash_pginodesteal && strcmp(name, "pginodesteal") == 0) pginodesteal = strtoull(value, NULL, 10); - else if(hash == hash_pgmajfault && strcmp(name, "pgmajfault") == 0) pgmajfault = strtoull(value, NULL, 10); - else if(hash == hash_pgpgin && strcmp(name, "pgpgin") == 0) pgpgin = strtoull(value, NULL, 10); - else if(hash == hash_pgpgout && strcmp(name, "pgpgout") == 0) pgpgout = strtoull(value, NULL, 10); - // else if(hash == hash_pgrefill_dma && strcmp(name, "pgrefill_dma") == 0) pgrefill_dma = strtoull(value, NULL, 10); - // else if(hash == hash_pgrefill_dma32 && strcmp(name, "pgrefill_dma32") == 0) pgrefill_dma32 = strtoull(value, NULL, 10); - // else if(hash == hash_pgrefill_movable && strcmp(name, "pgrefill_movable") == 0) pgrefill_movable = strtoull(value, NULL, 10); - // else if(hash == hash_pgrefill_normal && strcmp(name, "pgrefill_normal") == 0) pgrefill_normal = strtoull(value, NULL, 10); - // else if(hash == hash_pgrotated && strcmp(name, "pgrotated") == 0) pgrotated = strtoull(value, NULL, 10); - // else if(hash == hash_pgscan_direct_dma && strcmp(name, "pgscan_direct_dma") == 0) pgscan_direct_dma = strtoull(value, NULL, 10); - // else if(hash == hash_pgscan_direct_dma32 && strcmp(name, "pgscan_direct_dma32") == 0) pgscan_direct_dma32 = strtoull(value, NULL, 10); - // else if(hash == hash_pgscan_direct_movable && strcmp(name, "pgscan_direct_movable") == 0) pgscan_direct_movable = strtoull(value, NULL, 10); - // else if(hash == hash_pgscan_direct_normal && strcmp(name, "pgscan_direct_normal") == 0) pgscan_direct_normal = strtoull(value, NULL, 10); - // else if(hash == hash_pgscan_kswapd_dma && strcmp(name, "pgscan_kswapd_dma") == 0) pgscan_kswapd_dma = strtoull(value, NULL, 10); - // else if(hash == hash_pgscan_kswapd_dma32 && strcmp(name, "pgscan_kswapd_dma32") == 0) pgscan_kswapd_dma32 = strtoull(value, NULL, 10); - // else if(hash == hash_pgscan_kswapd_movable && strcmp(name, "pgscan_kswapd_movable") == 0) pgscan_kswapd_movable = strtoull(value, NULL, 10); - // else if(hash == hash_pgscan_kswapd_normal && strcmp(name, "pgscan_kswapd_normal") == 0) pgscan_kswapd_normal = strtoull(value, NULL, 10); - // else if(hash == hash_pgsteal_direct_dma && strcmp(name, "pgsteal_direct_dma") == 0) pgsteal_direct_dma = strtoull(value, NULL, 10); - // else if(hash == hash_pgsteal_direct_dma32 && strcmp(name, "pgsteal_direct_dma32") == 0) pgsteal_direct_dma32 = strtoull(value, NULL, 10); - // else if(hash == hash_pgsteal_direct_movable && strcmp(name, "pgsteal_direct_movable") == 0) pgsteal_direct_movable = strtoull(value, NULL, 10); - // else if(hash == hash_pgsteal_direct_normal && strcmp(name, "pgsteal_direct_normal") == 0) pgsteal_direct_normal = strtoull(value, NULL, 10); - // else if(hash == hash_pgsteal_kswapd_dma && strcmp(name, "pgsteal_kswapd_dma") == 0) pgsteal_kswapd_dma = strtoull(value, NULL, 10); - // else if(hash == hash_pgsteal_kswapd_dma32 && strcmp(name, "pgsteal_kswapd_dma32") == 0) pgsteal_kswapd_dma32 = strtoull(value, NULL, 10); - // else if(hash == hash_pgsteal_kswapd_movable && strcmp(name, "pgsteal_kswapd_movable") == 0) pgsteal_kswapd_movable = strtoull(value, NULL, 10); - // else if(hash == hash_pgsteal_kswapd_normal && strcmp(name, "pgsteal_kswapd_normal") == 0) pgsteal_kswapd_normal = strtoull(value, NULL, 10); - else if(hash == hash_pswpin && strcmp(name, "pswpin") == 0) pswpin = strtoull(value, NULL, 10); - else if(hash == hash_pswpout && strcmp(name, "pswpout") == 0) pswpout = strtoull(value, NULL, 10); - // else if(hash == hash_slabs_scanned && strcmp(name, "slabs_scanned") == 0) slabs_scanned = strtoull(value, NULL, 10); - // else if(hash == hash_thp_collapse_alloc && strcmp(name, "thp_collapse_alloc") == 0) thp_collapse_alloc = strtoull(value, NULL, 10); - // else if(hash == hash_thp_collapse_alloc_failed && strcmp(name, "thp_collapse_alloc_failed") == 0) thp_collapse_alloc_failed = strtoull(value, NULL, 10); - // else if(hash == hash_thp_fault_alloc && strcmp(name, "thp_fault_alloc") == 0) thp_fault_alloc = strtoull(value, NULL, 10); - // else if(hash == hash_thp_fault_fallback && strcmp(name, "thp_fault_fallback") == 0) thp_fault_fallback = strtoull(value, NULL, 10); - // else if(hash == hash_thp_split && strcmp(name, "thp_split") == 0) thp_split = strtoull(value, NULL, 10); - // else if(hash == hash_unevictable_pgs_cleared && strcmp(name, "unevictable_pgs_cleared") == 0) unevictable_pgs_cleared = strtoull(value, NULL, 10); - // else if(hash == hash_unevictable_pgs_culled && strcmp(name, "unevictable_pgs_culled") == 0) unevictable_pgs_culled = strtoull(value, NULL, 10); - // else if(hash == hash_unevictable_pgs_mlocked && strcmp(name, "unevictable_pgs_mlocked") == 0) unevictable_pgs_mlocked = strtoull(value, NULL, 10); - // else if(hash == hash_unevictable_pgs_mlockfreed && strcmp(name, "unevictable_pgs_mlockfreed") == 0) unevictable_pgs_mlockfreed = strtoull(value, NULL, 10); - // else if(hash == hash_unevictable_pgs_munlocked && strcmp(name, "unevictable_pgs_munlocked") == 0) unevictable_pgs_munlocked = strtoull(value, NULL, 10); - // else if(hash == hash_unevictable_pgs_rescued && strcmp(name, "unevictable_pgs_rescued") == 0) unevictable_pgs_rescued = strtoull(value, NULL, 10); - // else if(hash == hash_unevictable_pgs_scanned && strcmp(name, "unevictable_pgs_scanned") == 0) unevictable_pgs_scanned = strtoull(value, NULL, 10); - // else if(hash == hash_unevictable_pgs_stranded && strcmp(name, "unevictable_pgs_stranded") == 0) unevictable_pgs_stranded = strtoull(value, NULL, 10); + if(unlikely(0)) ; + // else if(unlikely(hash == hash_allocstall && strcmp(name, "allocstall") == 0)) allocstall = strtoull(value, NULL, 10); + // else if(unlikely(hash == hash_compact_blocks_moved && strcmp(name, "compact_blocks_moved") == 0)) compact_blocks_moved = strtoull(value, NULL, 10); + // else if(unlikely(hash == hash_compact_fail && strcmp(name, "compact_fail") == 0)) compact_fail = strtoull(value, NULL, 10); + // else if(unlikely(hash == hash_compact_pagemigrate_failed && strcmp(name, "compact_pagemigrate_failed") == 0)) compact_pagemigrate_failed = strtoull(value, NULL, 10); + // else if(unlikely(hash == hash_compact_pages_moved && strcmp(name, "compact_pages_moved") == 0)) compact_pages_moved = strtoull(value, NULL, 10); + // else if(unlikely(hash == hash_compact_stall && strcmp(name, "compact_stall") == 0)) compact_stall = strtoull(value, NULL, 10); + // else if(unlikely(hash == hash_compact_success && strcmp(name, "compact_success") == 0)) compact_success = strtoull(value, NULL, 10); + // else if(unlikely(hash == hash_htlb_buddy_alloc_fail && strcmp(name, "htlb_buddy_alloc_fail") == 0)) htlb_buddy_alloc_fail = strtoull(value, NULL, 10); + // else if(unlikely(hash == hash_htlb_buddy_alloc_success && strcmp(name, "htlb_buddy_alloc_success") == 0)) htlb_buddy_alloc_success = strtoull(value, NULL, 10); + // else if(unlikely(hash == hash_kswapd_high_wmark_hit_quickly && strcmp(name, "kswapd_high_wmark_hit_quickly") == 0)) kswapd_high_wmark_hit_quickly = strtoull(value, NULL, 10); + // else if(unlikely(hash == hash_kswapd_inodesteal && strcmp(name, "kswapd_inodesteal") == 0)) kswapd_inodesteal = strtoull(value, NULL, 10); + // else if(unlikely(hash == hash_kswapd_low_wmark_hit_quickly && strcmp(name, "kswapd_low_wmark_hit_quickly") == 0)) kswapd_low_wmark_hit_quickly = strtoull(value, NULL, 10); + // else if(unlikely(hash == hash_kswapd_skip_congestion_wait && strcmp(name, "kswapd_skip_congestion_wait") == 0)) kswapd_skip_congestion_wait = strtoull(value, NULL, 10); + // else if(unlikely(hash == hash_nr_active_anon && strcmp(name, "nr_active_anon") == 0)) nr_active_anon = strtoull(value, NULL, 10); + // else if(unlikely(hash == hash_nr_active_file && strcmp(name, "nr_active_file") == 0)) nr_active_file = strtoull(value, NULL, 10); + // else if(unlikely(hash == hash_nr_anon_pages && strcmp(name, "nr_anon_pages") == 0)) nr_anon_pages = strtoull(value, NULL, 10); + // else if(unlikely(hash == hash_nr_anon_transparent_hugepages && strcmp(name, "nr_anon_transparent_hugepages") == 0)) nr_anon_transparent_hugepages = strtoull(value, NULL, 10); + // else if(unlikely(hash == hash_nr_bounce && strcmp(name, "nr_bounce") == 0)) nr_bounce = strtoull(value, NULL, 10); + // else if(unlikely(hash == hash_nr_dirtied && strcmp(name, "nr_dirtied") == 0)) nr_dirtied = strtoull(value, NULL, 10); + // else if(unlikely(hash == hash_nr_dirty && strcmp(name, "nr_dirty") == 0)) nr_dirty = strtoull(value, NULL, 10); + // else if(unlikely(hash == hash_nr_dirty_background_threshold && strcmp(name, "nr_dirty_background_threshold") == 0)) nr_dirty_background_threshold = strtoull(value, NULL, 10); + // else if(unlikely(hash == hash_nr_dirty_threshold && strcmp(name, "nr_dirty_threshold") == 0)) nr_dirty_threshold = strtoull(value, NULL, 10); + // else if(unlikely(hash == hash_nr_file_pages && strcmp(name, "nr_file_pages") == 0)) nr_file_pages = strtoull(value, NULL, 10); + // else if(unlikely(hash == hash_nr_free_pages && strcmp(name, "nr_free_pages") == 0)) nr_free_pages = strtoull(value, NULL, 10); + // else if(unlikely(hash == hash_nr_inactive_anon && strcmp(name, "nr_inactive_anon") == 0)) nr_inactive_anon = strtoull(value, NULL, 10); + // else if(unlikely(hash == hash_nr_inactive_file && strcmp(name, "nr_inactive_file") == 0)) nr_inactive_file = strtoull(value, NULL, 10); + // else if(unlikely(hash == hash_nr_isolated_anon && strcmp(name, "nr_isolated_anon") == 0)) nr_isolated_anon = strtoull(value, NULL, 10); + // else if(unlikely(hash == hash_nr_isolated_file && strcmp(name, "nr_isolated_file") == 0)) nr_isolated_file = strtoull(value, NULL, 10); + // else if(unlikely(hash == hash_nr_kernel_stack && strcmp(name, "nr_kernel_stack") == 0)) nr_kernel_stack = strtoull(value, NULL, 10); + // else if(unlikely(hash == hash_nr_mapped && strcmp(name, "nr_mapped") == 0)) nr_mapped = strtoull(value, NULL, 10); + // else if(unlikely(hash == hash_nr_mlock && strcmp(name, "nr_mlock") == 0)) nr_mlock = strtoull(value, NULL, 10); + // else if(unlikely(hash == hash_nr_page_table_pages && strcmp(name, "nr_page_table_pages") == 0)) nr_page_table_pages = strtoull(value, NULL, 10); + // else if(unlikely(hash == hash_nr_shmem && strcmp(name, "nr_shmem") == 0)) nr_shmem = strtoull(value, NULL, 10); + // else if(unlikely(hash == hash_nr_slab_reclaimable && strcmp(name, "nr_slab_reclaimable") == 0)) nr_slab_reclaimable = strtoull(value, NULL, 10); + // else if(unlikely(hash == hash_nr_slab_unreclaimable && strcmp(name, "nr_slab_unreclaimable") == 0)) nr_slab_unreclaimable = strtoull(value, NULL, 10); + // else if(unlikely(hash == hash_nr_unevictable && strcmp(name, "nr_unevictable") == 0)) nr_unevictable = strtoull(value, NULL, 10); + // else if(unlikely(hash == hash_nr_unstable && strcmp(name, "nr_unstable") == 0)) nr_unstable = strtoull(value, NULL, 10); + // else if(unlikely(hash == hash_nr_vmscan_immediate_reclaim && strcmp(name, "nr_vmscan_immediate_reclaim") == 0)) nr_vmscan_immediate_reclaim = strtoull(value, NULL, 10); + // else if(unlikely(hash == hash_nr_vmscan_write && strcmp(name, "nr_vmscan_write") == 0)) nr_vmscan_write = strtoull(value, NULL, 10); + // else if(unlikely(hash == hash_nr_writeback && strcmp(name, "nr_writeback") == 0)) nr_writeback = strtoull(value, NULL, 10); + // else if(unlikely(hash == hash_nr_writeback_temp && strcmp(name, "nr_writeback_temp") == 0)) nr_writeback_temp = strtoull(value, NULL, 10); + // else if(unlikely(hash == hash_nr_written && strcmp(name, "nr_written") == 0)) nr_written = strtoull(value, NULL, 10); + // else if(unlikely(hash == hash_pageoutrun && strcmp(name, "pageoutrun") == 0)) pageoutrun = strtoull(value, NULL, 10); + // else if(unlikely(hash == hash_pgactivate && strcmp(name, "pgactivate") == 0)) pgactivate = strtoull(value, NULL, 10); + // else if(unlikely(hash == hash_pgalloc_dma && strcmp(name, "pgalloc_dma") == 0)) pgalloc_dma = strtoull(value, NULL, 10); + // else if(unlikely(hash == hash_pgalloc_dma32 && strcmp(name, "pgalloc_dma32") == 0)) pgalloc_dma32 = strtoull(value, NULL, 10); + // else if(unlikely(hash == hash_pgalloc_movable && strcmp(name, "pgalloc_movable") == 0)) pgalloc_movable = strtoull(value, NULL, 10); + // else if(unlikely(hash == hash_pgalloc_normal && strcmp(name, "pgalloc_normal") == 0)) pgalloc_normal = strtoull(value, NULL, 10); + // else if(unlikely(hash == hash_pgdeactivate && strcmp(name, "pgdeactivate") == 0)) pgdeactivate = strtoull(value, NULL, 10); + else if(unlikely(hash == hash_pgfault && strcmp(name, "pgfault") == 0)) pgfault = strtoull(value, NULL, 10); + // else if(unlikely(hash == hash_pgfree && strcmp(name, "pgfree") == 0)) pgfree = strtoull(value, NULL, 10); + // else if(unlikely(hash == hash_pginodesteal && strcmp(name, "pginodesteal") == 0)) pginodesteal = strtoull(value, NULL, 10); + else if(unlikely(hash == hash_pgmajfault && strcmp(name, "pgmajfault") == 0)) pgmajfault = strtoull(value, NULL, 10); + else if(unlikely(hash == hash_pgpgin && strcmp(name, "pgpgin") == 0)) pgpgin = strtoull(value, NULL, 10); + else if(unlikely(hash == hash_pgpgout && strcmp(name, "pgpgout") == 0)) pgpgout = strtoull(value, NULL, 10); + // else if(unlikely(hash == hash_pgrefill_dma && strcmp(name, "pgrefill_dma") == 0)) pgrefill_dma = strtoull(value, NULL, 10); + // else if(unlikely(hash == hash_pgrefill_dma32 && strcmp(name, "pgrefill_dma32") == 0)) pgrefill_dma32 = strtoull(value, NULL, 10); + // else if(unlikely(hash == hash_pgrefill_movable && strcmp(name, "pgrefill_movable") == 0)) pgrefill_movable = strtoull(value, NULL, 10); + // else if(unlikely(hash == hash_pgrefill_normal && strcmp(name, "pgrefill_normal") == 0)) pgrefill_normal = strtoull(value, NULL, 10); + // else if(unlikely(hash == hash_pgrotated && strcmp(name, "pgrotated") == 0)) pgrotated = strtoull(value, NULL, 10); + // else if(unlikely(hash == hash_pgscan_direct_dma && strcmp(name, "pgscan_direct_dma") == 0)) pgscan_direct_dma = strtoull(value, NULL, 10); + // else if(unlikely(hash == hash_pgscan_direct_dma32 && strcmp(name, "pgscan_direct_dma32") == 0)) pgscan_direct_dma32 = strtoull(value, NULL, 10); + // else if(unlikely(hash == hash_pgscan_direct_movable && strcmp(name, "pgscan_direct_movable") == 0)) pgscan_direct_movable = strtoull(value, NULL, 10); + // else if(unlikely(hash == hash_pgscan_direct_normal && strcmp(name, "pgscan_direct_normal") == 0)) pgscan_direct_normal = strtoull(value, NULL, 10); + // else if(unlikely(hash == hash_pgscan_kswapd_dma && strcmp(name, "pgscan_kswapd_dma") == 0)) pgscan_kswapd_dma = strtoull(value, NULL, 10); + // else if(unlikely(hash == hash_pgscan_kswapd_dma32 && strcmp(name, "pgscan_kswapd_dma32") == 0)) pgscan_kswapd_dma32 = strtoull(value, NULL, 10); + // else if(unlikely(hash == hash_pgscan_kswapd_movable && strcmp(name, "pgscan_kswapd_movable") == 0)) pgscan_kswapd_movable = strtoull(value, NULL, 10); + // else if(unlikely(hash == hash_pgscan_kswapd_normal && strcmp(name, "pgscan_kswapd_normal") == 0)) pgscan_kswapd_normal = strtoull(value, NULL, 10); + // else if(unlikely(hash == hash_pgsteal_direct_dma && strcmp(name, "pgsteal_direct_dma") == 0)) pgsteal_direct_dma = strtoull(value, NULL, 10); + // else if(unlikely(hash == hash_pgsteal_direct_dma32 && strcmp(name, "pgsteal_direct_dma32") == 0)) pgsteal_direct_dma32 = strtoull(value, NULL, 10); + // else if(unlikely(hash == hash_pgsteal_direct_movable && strcmp(name, "pgsteal_direct_movable") == 0)) pgsteal_direct_movable = strtoull(value, NULL, 10); + // else if(unlikely(hash == hash_pgsteal_direct_normal && strcmp(name, "pgsteal_direct_normal") == 0)) pgsteal_direct_normal = strtoull(value, NULL, 10); + // else if(unlikely(hash == hash_pgsteal_kswapd_dma && strcmp(name, "pgsteal_kswapd_dma") == 0)) pgsteal_kswapd_dma = strtoull(value, NULL, 10); + // else if(unlikely(hash == hash_pgsteal_kswapd_dma32 && strcmp(name, "pgsteal_kswapd_dma32") == 0)) pgsteal_kswapd_dma32 = strtoull(value, NULL, 10); + // else if(unlikely(hash == hash_pgsteal_kswapd_movable && strcmp(name, "pgsteal_kswapd_movable") == 0)) pgsteal_kswapd_movable = strtoull(value, NULL, 10); + // else if(unlikely(hash == hash_pgsteal_kswapd_normal && strcmp(name, "pgsteal_kswapd_normal") == 0)) pgsteal_kswapd_normal = strtoull(value, NULL, 10); + else if(unlikely(hash == hash_pswpin && strcmp(name, "pswpin") == 0)) pswpin = strtoull(value, NULL, 10); + else if(unlikely(hash == hash_pswpout && strcmp(name, "pswpout") == 0)) pswpout = strtoull(value, NULL, 10); + // else if(unlikely(hash == hash_slabs_scanned && strcmp(name, "slabs_scanned") == 0)) slabs_scanned = strtoull(value, NULL, 10); + // else if(unlikely(hash == hash_thp_collapse_alloc && strcmp(name, "thp_collapse_alloc") == 0)) thp_collapse_alloc = strtoull(value, NULL, 10); + // else if(unlikely(hash == hash_thp_collapse_alloc_failed && strcmp(name, "thp_collapse_alloc_failed") == 0)) thp_collapse_alloc_failed = strtoull(value, NULL, 10); + // else if(unlikely(hash == hash_thp_fault_alloc && strcmp(name, "thp_fault_alloc") == 0)) thp_fault_alloc = strtoull(value, NULL, 10); + // else if(unlikely(hash == hash_thp_fault_fallback && strcmp(name, "thp_fault_fallback") == 0)) thp_fault_fallback = strtoull(value, NULL, 10); + // else if(unlikely(hash == hash_thp_split && strcmp(name, "thp_split") == 0)) thp_split = strtoull(value, NULL, 10); + // else if(unlikely(hash == hash_unevictable_pgs_cleared && strcmp(name, "unevictable_pgs_cleared") == 0)) unevictable_pgs_cleared = strtoull(value, NULL, 10); + // else if(unlikely(hash == hash_unevictable_pgs_culled && strcmp(name, "unevictable_pgs_culled") == 0)) unevictable_pgs_culled = strtoull(value, NULL, 10); + // else if(unlikely(hash == hash_unevictable_pgs_mlocked && strcmp(name, "unevictable_pgs_mlocked") == 0)) unevictable_pgs_mlocked = strtoull(value, NULL, 10); + // else if(unlikely(hash == hash_unevictable_pgs_mlockfreed && strcmp(name, "unevictable_pgs_mlockfreed") == 0)) unevictable_pgs_mlockfreed = strtoull(value, NULL, 10); + // else if(unlikely(hash == hash_unevictable_pgs_munlocked && strcmp(name, "unevictable_pgs_munlocked") == 0)) unevictable_pgs_munlocked = strtoull(value, NULL, 10); + // else if(unlikely(hash == hash_unevictable_pgs_rescued && strcmp(name, "unevictable_pgs_rescued") == 0)) unevictable_pgs_rescued = strtoull(value, NULL, 10); + // else if(unlikely(hash == hash_unevictable_pgs_scanned && strcmp(name, "unevictable_pgs_scanned") == 0)) unevictable_pgs_scanned = strtoull(value, NULL, 10); + // else if(unlikely(hash == hash_unevictable_pgs_stranded && strcmp(name, "unevictable_pgs_stranded") == 0)) unevictable_pgs_stranded = strtoull(value, NULL, 10); } // -------------------------------------------------------------------- @@ -419,7 +417,7 @@ int do_proc_vmstat(int update_every, unsigned long long dt) { do_swapio = CONFIG_ONDEMAND_YES; static RRDSET *st_swapio = NULL; - if(!st_swapio) { + if(unlikely(!st_swapio)) { st_swapio = rrdset_create("system", "swapio", NULL, "swap", NULL, "Swap I/O", "kilobytes/s", 250, update_every, RRDSET_TYPE_AREA); rrddim_add(st_swapio, "in", NULL, sysconf(_SC_PAGESIZE), 1024, RRDDIM_INCREMENTAL); @@ -436,7 +434,7 @@ int do_proc_vmstat(int update_every, unsigned long long dt) { if(do_io) { static RRDSET *st_io = NULL; - if(!st_io) { + if(unlikely(!st_io)) { st_io = rrdset_create("system", "io", NULL, "disk", NULL, "Disk I/O", "kilobytes/s", 150, update_every, RRDSET_TYPE_AREA); rrddim_add(st_io, "in", NULL, 1, 1, RRDDIM_INCREMENTAL); @@ -453,7 +451,7 @@ int do_proc_vmstat(int update_every, unsigned long long dt) { if(do_pgfaults) { static RRDSET *st_pgfaults = NULL; - if(!st_pgfaults) { + if(unlikely(!st_pgfaults)) { st_pgfaults = rrdset_create("mem", "pgfaults", NULL, "system", NULL, "Memory Page Faults", "page faults/s", 500, update_every, RRDSET_TYPE_LINE); st_pgfaults->isdetail = 1; diff --git a/src/procfile.c b/src/procfile.c index e2aa6058..31bdb5e2 100644 --- a/src/procfile.c +++ b/src/procfile.c @@ -267,14 +267,14 @@ cleanup: procfile *procfile_readall(procfile *ff) { debug(D_PROCFILE, PF_PREFIX ": Reading file '%s'.", ff->filename); - ssize_t s, r = 1, x; + ssize_t r = 1; ff->len = 0; while(likely(r > 0)) { - s = ff->len; - x = ff->size - s; + ssize_t s = ff->len; + ssize_t x = ff->size - s; - if(!x) { + if(unlikely(!x)) { debug(D_PROCFILE, PF_PREFIX ": Expanding data buffer for file '%s'.", ff->filename); ff = reallocz(ff, sizeof(procfile) + ff->size + PROCFILE_INCREMENT_BUFFER); @@ -316,13 +316,13 @@ procfile *procfile_readall(procfile *ff) { static void procfile_set_separators(procfile *ff, const char *separators) { static char def[256] = { [0 ... 255] = 0 }; - int i; if(unlikely(!def[255])) { // this is thread safe // we check that the last byte is non-zero // if it is zero, multiple threads may be executing this at the same time // setting in def[] the exact same values + int i; for(i = 0; likely(i < 256) ;i++) { if(unlikely(i == '\n' || i == '\r')) def[i] = PF_CHAR_IS_NEWLINE; else if(unlikely(isspace(i) || !isprint(i))) def[i] = PF_CHAR_IS_SEPARATOR; @@ -348,7 +348,7 @@ void procfile_set_quotes(procfile *ff, const char *quotes) { // remove all quotes int i; for(i = 0; i < 256 ; i++) - if(ff->separators[i] == PF_CHAR_IS_QUOTE) + if(unlikely(ff->separators[i] == PF_CHAR_IS_QUOTE)) ff->separators[i] = PF_CHAR_IS_WORD; // if nothing given, return @@ -366,7 +366,7 @@ void procfile_set_open_close(procfile *ff, const char *open, const char *close) // remove all open/close int i; for(i = 0; i < 256 ; i++) - if(ff->separators[i] == PF_CHAR_IS_OPEN || ff->separators[i] == PF_CHAR_IS_CLOSE) + if(unlikely(ff->separators[i] == PF_CHAR_IS_OPEN || ff->separators[i] == PF_CHAR_IS_CLOSE)) ff->separators[i] = PF_CHAR_IS_WORD; // if nothing given, return @@ -443,16 +443,16 @@ procfile *procfile_reopen(procfile *ff, const char *filename, const char *separa void procfile_print(procfile *ff) { uint32_t lines = procfile_lines(ff), l; - uint32_t words, w; char *s; debug(D_PROCFILE, "File '%s' with %u lines and %u words", ff->filename, ff->lines->len, ff->words->len); for(l = 0; likely(l < lines) ;l++) { - words = procfile_linewords(ff, l); + uint32_t words = procfile_linewords(ff, l); debug(D_PROCFILE, " line %u starts at word %u and has %u words", l, ff->lines->lines[l].first, ff->lines->lines[l].words); + uint32_t w; for(w = 0; likely(w < words) ;w++) { s = procfile_lineword(ff, l, w); debug(D_PROCFILE, " [%u.%u] '%s'", l, w, s); diff --git a/src/rrd.c b/src/rrd.c index f9b5d4e0..7d8bf394 100644 --- a/src/rrd.c +++ b/src/rrd.c @@ -353,20 +353,33 @@ char *rrdset_strncpyz_name(char *to, const char *from, size_t length) void rrdset_set_name(RRDSET *st, const char *name) { - debug(D_RRD_CALLS, "rrdset_set_name() old: %s, new: %s", st->name, name); + if(unlikely(st->name && !strcmp(st->name, name))) + return; - if(st->name) { - rrdset_index_del_name(&localhost, st); - rrdsetvar_rename_all(st); - } + debug(D_RRD_CALLS, "rrdset_set_name() old: %s, new: %s", st->name, name); char b[CONFIG_MAX_VALUE + 1]; char n[RRD_ID_LENGTH_MAX + 1]; snprintfz(n, RRD_ID_LENGTH_MAX, "%s.%s", st->type, name); rrdset_strncpyz_name(b, n, CONFIG_MAX_VALUE); - st->name = config_get(st->id, "name", b); - st->hash_name = simple_hash(st->name); + + if(st->name) { + rrdset_index_del_name(&localhost, st); + st->name = config_set_default(st->id, "name", b); + st->hash_name = simple_hash(st->name); + rrdsetvar_rename_all(st); + } + else { + st->name = config_get(st->id, "name", b); + st->hash_name = simple_hash(st->name); + } + + pthread_rwlock_wrlock(&st->rwlock); + RRDDIM *rd; + for(rd = st->dimensions; rd ;rd = rd->next) + rrddimvar_rename_all(rd); + pthread_rwlock_unlock(&st->rwlock); rrdset_index_add_name(&localhost, st); } @@ -461,11 +474,10 @@ RRDSET *rrdset_create(const char *type, const char *id, const char *name, const char fullid[RRD_ID_LENGTH_MAX + 1]; char fullfilename[FILENAME_MAX + 1]; - RRDSET *st = NULL; snprintfz(fullid, RRD_ID_LENGTH_MAX, "%s.%s", type, id); - st = rrdset_find(fullid); + RRDSET *st = rrdset_find(fullid); if(st) { error("Cannot create rrd stats for '%s', it already exists.", fullid); return st; @@ -513,6 +525,12 @@ RRDSET *rrdset_create(const char *type, const char *id, const char *name, const error("File %s is too old. Clearing it.", fullfilename); memset(st, 0, size); } + + // make sure the database is aligned + if(st->last_updated.tv_sec % update_every) { + st->last_updated.tv_sec -= st->last_updated.tv_sec % update_every; + st->last_updated.tv_usec = 0; + } } if(st) { @@ -755,11 +773,14 @@ RRDDIM *rrddim_add(RRDSET *st, const char *id, const char *name, long multiplier void rrddim_set_name(RRDSET *st, RRDDIM *rd, const char *name) { - debug(D_RRD_CALLS, "rrddim_set_name() %s.%s", st->name, rd->name); + if(unlikely(rd->name && !strcmp(rd->name, name))) + return; + + debug(D_RRD_CALLS, "rrddim_set_name() from %s.%s to %s.%s", st->name, rd->name, st->name, name); char varname[CONFIG_MAX_NAME + 1]; snprintfz(varname, CONFIG_MAX_NAME, "dim %s name", rd->id); - config_set_default(st->id, varname, name); + rd->name = config_set_default(st->id, varname, name); rrddimvar_rename_all(rd); } @@ -974,35 +995,58 @@ collected_number rrddim_set(RRDSET *st, const char *id, collected_number value) return rrddim_set_by_pointer(st, rd, value); } -void rrdset_next_usec(RRDSET *st, unsigned long long microseconds) +void rrdset_next_usec_unfiltered(RRDSET *st, unsigned long long microseconds) { - if(!microseconds) rrdset_next(st); - else { - debug(D_RRD_CALLS, "rrdset_next_usec() for chart %s with microseconds %llu", st->name, microseconds); - - if(unlikely(st->debug)) debug(D_RRD_STATS, "%s: NEXT: %llu microseconds", st->name, microseconds); - st->usec_since_last_update = microseconds; + if(unlikely(!st->last_collected_time.tv_sec || !microseconds)) { + // the first entry + microseconds = st->update_every * 1000000ULL; } + st->usec_since_last_update = microseconds; } -void rrdset_next(RRDSET *st) +void rrdset_next_usec(RRDSET *st, unsigned long long microseconds) { - unsigned long long microseconds = 0; + struct timeval now; + gettimeofday(&now, NULL); - if(likely(st->last_collected_time.tv_sec)) { - struct timeval now; - gettimeofday(&now, NULL); + if(unlikely(!st->last_collected_time.tv_sec)) { + // the first entry + microseconds = st->update_every * 1000000ULL; + } + else if(unlikely(!microseconds)) { + // no dt given by the plugin microseconds = usec_dt(&now, &st->last_collected_time); } - // prevent infinite loop - else microseconds = st->update_every * 1000000ULL; + else { + // microseconds has the time since the last collection + unsigned long long now_usec = timeval_usec(&now); + unsigned long long last_usec = timeval_usec(&st->last_collected_time); + unsigned long long since_last_usec = usec_dt(&now, &st->last_collected_time); - rrdset_next_usec(st, microseconds); -} + // verify the microseconds given is good + if(unlikely(microseconds > since_last_usec)) { + debug(D_RRD_CALLS, "dt %llu usec given is too big - it leads %llu usec to the future, for chart '%s' (%s).", microseconds, microseconds - since_last_usec, st->name, st->id); -void rrdset_next_plugins(RRDSET *st) -{ - rrdset_next(st); +#ifdef NETDATA_INTERNAL_CHECKS + if(unlikely(last_usec + microseconds > now_usec + 1000)) + error("dt %llu usec given is too big - it leads %llu usec to the future, for chart '%s' (%s).", microseconds, microseconds - since_last_usec, st->name, st->id); +#endif + + microseconds = since_last_usec; + } + else if(unlikely(microseconds < since_last_usec * 0.8)) { + debug(D_RRD_CALLS, "dt %llu usec given is too small - expected %llu usec up to -20%%, for chart '%s' (%s).", microseconds, since_last_usec, st->name, st->id); + +#ifdef NETDATA_INTERNAL_CHECKS + error("dt %llu usec given is too small - expected %llu usec up to -20%%, for chart '%s' (%s).", microseconds, since_last_usec, st->name, st->id); +#endif + microseconds = since_last_usec; + } + } + debug(D_RRD_CALLS, "rrdset_next_usec() for chart %s with microseconds %llu", st->name, microseconds); + + if(unlikely(st->debug)) debug(D_RRD_STATS, "%s: NEXT: %llu microseconds", st->name, microseconds); + st->usec_since_last_update = microseconds; } unsigned long long rrdset_done(RRDSET *st) @@ -1056,6 +1100,11 @@ unsigned long long rrdset_done(RRDSET *st) // it is the first entry // set the last_collected_time to now gettimeofday(&st->last_collected_time, NULL); + + // align it to update_every + st->last_collected_time.tv_sec -= st->last_collected_time.tv_sec % st->update_every; + st->last_collected_time.tv_usec = 0; + last_collect_ut = st->last_collected_time.tv_sec * 1000000ULL + st->last_collected_time.tv_usec - update_every_ut; // the first entry should not be stored @@ -1098,6 +1147,10 @@ unsigned long long rrdset_done(RRDSET *st) gettimeofday(&st->last_collected_time, NULL); + // align it to update_every + st->last_collected_time.tv_sec -= st->last_collected_time.tv_sec % st->update_every; + st->last_collected_time.tv_usec = 0; + unsigned long long ut = st->last_collected_time.tv_sec * 1000000ULL + st->last_collected_time.tv_usec - st->usec_since_last_update; st->last_updated.tv_sec = (time_t) (ut / 1000000ULL); st->last_updated.tv_usec = (suseconds_t) (ut % 1000000ULL); @@ -1311,6 +1364,9 @@ unsigned long long rrdset_done(RRDSET *st) if(unlikely(now_collect_ut < next_store_ut)) { // this is collected in the same interpolation point if(unlikely(st->debug)) debug(D_RRD_STATS, "%s: THIS IS IN THE SAME INTERPOLATION POINT", st->name); +#ifdef NETDATA_INTERNAL_CHECKS + info("%s is collected in the same interpolation point: short by %llu microseconds", st->name, next_store_ut - now_collect_ut); +#endif } unsigned long long first_ut = last_stored_ut; diff --git a/src/rrd.h b/src/rrd.h index 92a65fe8..f0d86540 100644 --- a/src/rrd.h +++ b/src/rrd.h @@ -355,9 +355,9 @@ extern RRDSET *rrdset_find(const char *id); extern RRDSET *rrdset_find_bytype(const char *type, const char *id); extern RRDSET *rrdset_find_byname(const char *name); +extern void rrdset_next_usec_unfiltered(RRDSET *st, unsigned long long microseconds); extern void rrdset_next_usec(RRDSET *st, unsigned long long microseconds); -extern void rrdset_next(RRDSET *st); -extern void rrdset_next_plugins(RRDSET *st); +#define rrdset_next(st) rrdset_next_usec(st, 0ULL) extern unsigned long long rrdset_done(RRDSET *st); diff --git a/src/rrd2json.c b/src/rrd2json.c index b2c1a055..ac04ca72 100644 --- a/src/rrd2json.c +++ b/src/rrd2json.c @@ -1209,19 +1209,32 @@ RRDR *rrd2rrdr(RRDSET *st, long points, long long after, long long before, int g time_t last_entry_t = rrdset_last_entry_t(st); if(before == 0 && after == 0) { + // dump the all the data before = last_entry_t; after = first_entry_t; absolute_period_requested = 0; } - // allow relative for before and after (smaller than 3 years) - if(((before < 0)?-before:before) <= (3 * 365 * 86400)) { - before = last_entry_t + before; + // allow relative for before (smaller than API_RELATIVE_TIME_MAX) + if(((before < 0)?-before:before) <= API_RELATIVE_TIME_MAX) { + if(abs(before) % st->update_every) { + // make sure it is multiple of st->update_every + if(before < 0) before = before - st->update_every - before % st->update_every; + else before = before + st->update_every - before % st->update_every; + } + if(before > 0) before = first_entry_t + before; + else before = last_entry_t + before; absolute_period_requested = 0; } - if(((after < 0)?-after:after) <= (3 * 365 * 86400)) { + // allow relative for after (smaller than API_RELATIVE_TIME_MAX) + if(((after < 0)?-after:after) <= API_RELATIVE_TIME_MAX) { if(after == 0) after = -st->update_every; + if(abs(after) % st->update_every) { + // make sure it is multiple of st->update_every + if(after < 0) after = after - st->update_every - after % st->update_every; + else after = after + st->update_every - after % st->update_every; + } after = before + after; absolute_period_requested = 0; } diff --git a/src/rrd2json.h b/src/rrd2json.h index e3e5cb69..d3dc44e0 100644 --- a/src/rrd2json.h +++ b/src/rrd2json.h @@ -4,6 +4,8 @@ #define HOSTNAME_MAX 1024 extern char *hostname; +#define API_RELATIVE_TIME_MAX (3 * 365 * 86400) + // type of JSON generations #define DATASOURCE_INVALID -1 #define DATASOURCE_JSON 0 diff --git a/src/sys_fs_cgroup.c b/src/sys_fs_cgroup.c index 5e49f33e..cef7cb44 100644 --- a/src/sys_fs_cgroup.c +++ b/src/sys_fs_cgroup.c @@ -269,7 +269,7 @@ void cgroup_read_cpuacct_usage(struct cpuacct_usage *ca) { } unsigned long i = procfile_linewords(ff, 0); - if(i <= 0) return; + if(i == 0) return; // we may have 1 more CPU reported while(i > 0) { @@ -1437,11 +1437,11 @@ void *cgroups_main(void *ptr) // the next time we will run - aligned properly unsigned long long sunext = (time(NULL) - (time(NULL) % rrd_update_every) + rrd_update_every) * 1000000ULL; - unsigned long long sunow; RRDSET *stcpu_thread = NULL; for(;;) { + unsigned long long sunow; if(unlikely(netdata_exit)) break; // delay until it is our time to run diff --git a/src/unit_test.c b/src/unit_test.c index d699707a..139e9975 100644 --- a/src/unit_test.c +++ b/src/unit_test.c @@ -915,7 +915,7 @@ int run_test(struct test *test) (float)time_now / 1000000.0, ((calculated_number)test->feed[c].value - (calculated_number)last) * (calculated_number)test->multiplier / (calculated_number)test->divisor, (((calculated_number)test->feed[c].value - (calculated_number)last) * (calculated_number)test->multiplier / (calculated_number)test->divisor) / (calculated_number)test->feed[c].microseconds * (calculated_number)1000000); - rrdset_next_usec(st, test->feed[c].microseconds); + rrdset_next_usec_unfiltered(st, test->feed[c].microseconds); } else { fprintf(stderr, " > %s: feeding position %lu\n", test->name, c+1); @@ -975,8 +975,55 @@ int run_test(struct test *test) return errors; } +static int test_variable_renames(void) { + fprintf(stderr, "Creating chart\n"); + RRDSET *st = rrdset_create("chart", "ID", NULL, "family", "context", "Unit Testing", "a value", 1, 1, RRDSET_TYPE_LINE); + fprintf(stderr, "Created chart with id '%s', name '%s'\n", st->id, st->name); + + fprintf(stderr, "Creating dimension DIM1\n"); + RRDDIM *rd1 = rrddim_add(st, "DIM1", NULL, 1, 1, RRDDIM_INCREMENTAL); + fprintf(stderr, "Created dimension with id '%s', name '%s'\n", rd1->id, rd1->name); + + fprintf(stderr, "Creating dimension DIM2\n"); + RRDDIM *rd2 = rrddim_add(st, "DIM2", NULL, 1, 1, RRDDIM_INCREMENTAL); + fprintf(stderr, "Created dimension with id '%s', name '%s'\n", rd2->id, rd2->name); + + fprintf(stderr, "Renaming chart to CHARTNAME1\n"); + rrdset_set_name(st, "CHARTNAME1"); + fprintf(stderr, "Renamed chart with id '%s' to name '%s'\n", st->id, st->name); + + fprintf(stderr, "Renaming chart to CHARTNAME2\n"); + rrdset_set_name(st, "CHARTNAME2"); + fprintf(stderr, "Renamed chart with id '%s' to name '%s'\n", st->id, st->name); + + fprintf(stderr, "Renaming dimension DIM1 to DIM1NAME1\n"); + rrddim_set_name(st, rd1, "DIM1NAME1"); + fprintf(stderr, "Renamed dimension with id '%s' to name '%s'\n", rd1->id, rd1->name); + + fprintf(stderr, "Renaming dimension DIM1 to DIM1NAME2\n"); + rrddim_set_name(st, rd1, "DIM1NAME2"); + fprintf(stderr, "Renamed dimension with id '%s' to name '%s'\n", rd1->id, rd1->name); + + fprintf(stderr, "Renaming dimension DIM2 to DIM2NAME1\n"); + rrddim_set_name(st, rd2, "DIM2NAME1"); + fprintf(stderr, "Renamed dimension with id '%s' to name '%s'\n", rd2->id, rd2->name); + + fprintf(stderr, "Renaming dimension DIM2 to DIM2NAME2\n"); + rrddim_set_name(st, rd2, "DIM2NAME2"); + fprintf(stderr, "Renamed dimension with id '%s' to name '%s'\n", rd2->id, rd2->name); + + BUFFER *buf = buffer_create(1); + health_api_v1_chart_variables2json(st, buf); + fprintf(stderr, "%s", buffer_tostring(buf)); + buffer_free(buf); + return 1; +} + int run_all_mockup_tests(void) { + if(!test_variable_renames()) + return 1; + if(run_test(&test1)) return 1; @@ -1028,6 +1075,8 @@ int run_all_mockup_tests(void) if(run_test(&test15)) return 1; + + return 0; } @@ -1073,7 +1122,7 @@ int unit_test(long delay, long shift) fprintf(stderr, "\n\nLOOP = %lu, DELAY = %ld, VALUE = " COLLECTED_NUMBER_FORMAT "\n", c, delay, i); if(c) { - rrdset_next_usec(st, delay); + rrdset_next_usec_unfiltered(st, delay); } if(do_abs) rrddim_set(st, "absolute", i); if(do_inc) rrddim_set(st, "incremental", i); diff --git a/src/web_client.c b/src/web_client.c index c16acfa0..2b2402f4 100644 --- a/src/web_client.c +++ b/src/web_client.c @@ -490,7 +490,7 @@ void buffer_data_options2string(BUFFER *wb, uint32_t options) { if(options & RRDR_OPTION_ABSOLUTE) { if(count++) buffer_strcat(wb, " "); - buffer_strcat(wb, "abs"); + buffer_strcat(wb, "absolute"); } if(options & RRDR_OPTION_SECONDS) { @@ -700,17 +700,7 @@ int web_client_api_request_v1_alarm_log(struct web_client *w, char *url) return 200; } -int web_client_api_request_v1_charts(struct web_client *w, char *url) -{ - (void)url; - - buffer_flush(w->response.data); - w->response.data->contenttype = CT_APPLICATION_JSON; - rrd_stats_api_v1_charts(w->response.data); - return 200; -} - -int web_client_api_request_v1_chart(struct web_client *w, char *url) +int web_client_api_request_single_chart(struct web_client *w, char *url, void callback(RRDSET *st, BUFFER *buf)) { int ret = 400; char *chart = NULL; @@ -749,13 +739,33 @@ int web_client_api_request_v1_chart(struct web_client *w, char *url) } w->response.data->contenttype = CT_APPLICATION_JSON; - rrd_stats_api_v1_chart(st, w->response.data); + callback(st, w->response.data); return 200; -cleanup: + cleanup: return ret; } +int web_client_api_request_v1_alarm_variables(struct web_client *w, char *url) +{ + return web_client_api_request_single_chart(w, url, health_api_v1_chart_variables2json); +} + +int web_client_api_request_v1_charts(struct web_client *w, char *url) +{ + (void)url; + + buffer_flush(w->response.data); + w->response.data->contenttype = CT_APPLICATION_JSON; + rrd_stats_api_v1_charts(w->response.data); + return 200; +} + +int web_client_api_request_v1_chart(struct web_client *w, char *url) +{ + return web_client_api_request_single_chart(w, url, rrd_stats_api_v1_chart); +} + int web_client_api_request_v1_badge(struct web_client *w, char *url) { int ret = 400; buffer_flush(w->response.data); @@ -1405,7 +1415,7 @@ int web_client_api_request_v1_registry(struct web_client *w, char *url) } int web_client_api_request_v1(struct web_client *w, char *url) { - static uint32_t hash_data = 0, hash_chart = 0, hash_charts = 0, hash_registry = 0, hash_badge = 0, hash_alarms = 0, hash_alarm_log = 0; + static uint32_t hash_data = 0, hash_chart = 0, hash_charts = 0, hash_registry = 0, hash_badge = 0, hash_alarms = 0, hash_alarm_log = 0, hash_alarm_variables = 0; if(unlikely(hash_data == 0)) { hash_data = simple_hash("data"); @@ -1415,6 +1425,7 @@ int web_client_api_request_v1(struct web_client *w, char *url) { hash_badge = simple_hash("badge.svg"); hash_alarms = simple_hash("alarms"); hash_alarm_log = simple_hash("alarm_log"); + hash_alarm_variables = simple_hash("alarm_variables"); } // get the command @@ -1444,6 +1455,9 @@ int web_client_api_request_v1(struct web_client *w, char *url) { else if(hash == hash_alarm_log && !strcmp(tok, "alarm_log")) return web_client_api_request_v1_alarm_log(w, url); + else if(hash == hash_alarm_variables && !strcmp(tok, "alarm_variables")) + return web_client_api_request_v1_alarm_variables(w, url); + else { buffer_flush(w->response.data); buffer_sprintf(w->response.data, "Unsupported v1 API command: %s", tok); diff --git a/web/css/font-awesome.min.css b/web/css/font-awesome.min.css index 9b27f8ea..540440ce 100644 --- a/web/css/font-awesome.min.css +++ b/web/css/font-awesome.min.css @@ -1,4 +1,4 @@ /*! - * Font Awesome 4.6.3 by @davegandy - http://fontawesome.io - @fontawesome + * Font Awesome 4.7.0 by @davegandy - http://fontawesome.io - @fontawesome * License - http://fontawesome.io/license (Font: SIL OFL 1.1, CSS: MIT License) - */@font-face{font-family:'FontAwesome';src:url('../fonts/fontawesome-webfont.eot?v=4.6.3');src:url('../fonts/fontawesome-webfont.eot?#iefix&v=4.6.3') format('embedded-opentype'),url('../fonts/fontawesome-webfont.woff2?v=4.6.3') format('woff2'),url('../fonts/fontawesome-webfont.woff?v=4.6.3') format('woff'),url('../fonts/fontawesome-webfont.ttf?v=4.6.3') format('truetype'),url('../fonts/fontawesome-webfont.svg?v=4.6.3#fontawesomeregular') format('svg');font-weight:normal;font-style:normal}.fa{display:inline-block;font:normal normal normal 14px/1 FontAwesome;font-size:inherit;text-rendering:auto;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.fa-lg{font-size:1.33333333em;line-height:.75em;vertical-align:-15%}.fa-2x{font-size:2em}.fa-3x{font-size:3em}.fa-4x{font-size:4em}.fa-5x{font-size:5em}.fa-fw{width:1.28571429em;text-align:center}.fa-ul{padding-left:0;margin-left:2.14285714em;list-style-type:none}.fa-ul>li{position:relative}.fa-li{position:absolute;left:-2.14285714em;width:2.14285714em;top:.14285714em;text-align:center}.fa-li.fa-lg{left:-1.85714286em}.fa-border{padding:.2em .25em .15em;border:solid .08em #eee;border-radius:.1em}.fa-pull-left{float:left}.fa-pull-right{float:right}.fa.fa-pull-left{margin-right:.3em}.fa.fa-pull-right{margin-left:.3em}.pull-right{float:right}.pull-left{float:left}.fa.pull-left{margin-right:.3em}.fa.pull-right{margin-left:.3em}.fa-spin{-webkit-animation:fa-spin 2s infinite linear;animation:fa-spin 2s infinite linear}.fa-pulse{-webkit-animation:fa-spin 1s infinite steps(8);animation:fa-spin 1s infinite steps(8)}@-webkit-keyframes fa-spin{0%{-webkit-transform:rotate(0deg);transform:rotate(0deg)}100%{-webkit-transform:rotate(359deg);transform:rotate(359deg)}}@keyframes fa-spin{0%{-webkit-transform:rotate(0deg);transform:rotate(0deg)}100%{-webkit-transform:rotate(359deg);transform:rotate(359deg)}}.fa-rotate-90{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=1)";-webkit-transform:rotate(90deg);-ms-transform:rotate(90deg);transform:rotate(90deg)}.fa-rotate-180{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=2)";-webkit-transform:rotate(180deg);-ms-transform:rotate(180deg);transform:rotate(180deg)}.fa-rotate-270{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=3)";-webkit-transform:rotate(270deg);-ms-transform:rotate(270deg);transform:rotate(270deg)}.fa-flip-horizontal{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=0, mirror=1)";-webkit-transform:scale(-1, 1);-ms-transform:scale(-1, 1);transform:scale(-1, 1)}.fa-flip-vertical{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=2, mirror=1)";-webkit-transform:scale(1, -1);-ms-transform:scale(1, -1);transform:scale(1, -1)}:root .fa-rotate-90,:root .fa-rotate-180,:root .fa-rotate-270,:root .fa-flip-horizontal,:root .fa-flip-vertical{filter:none}.fa-stack{position:relative;display:inline-block;width:2em;height:2em;line-height:2em;vertical-align:middle}.fa-stack-1x,.fa-stack-2x{position:absolute;left:0;width:100%;text-align:center}.fa-stack-1x{line-height:inherit}.fa-stack-2x{font-size:2em}.fa-inverse{color:#fff}.fa-glass:before{content:"\f000"}.fa-music:before{content:"\f001"}.fa-search:before{content:"\f002"}.fa-envelope-o:before{content:"\f003"}.fa-heart:before{content:"\f004"}.fa-star:before{content:"\f005"}.fa-star-o:before{content:"\f006"}.fa-user:before{content:"\f007"}.fa-film:before{content:"\f008"}.fa-th-large:before{content:"\f009"}.fa-th:before{content:"\f00a"}.fa-th-list:before{content:"\f00b"}.fa-check:before{content:"\f00c"}.fa-remove:before,.fa-close:before,.fa-times:before{content:"\f00d"}.fa-search-plus:before{content:"\f00e"}.fa-search-minus:before{content:"\f010"}.fa-power-off:before{content:"\f011"}.fa-signal:before{content:"\f012"}.fa-gear:before,.fa-cog:before{content:"\f013"}.fa-trash-o:before{content:"\f014"}.fa-home:before{content:"\f015"}.fa-file-o:before{content:"\f016"}.fa-clock-o:before{content:"\f017"}.fa-road:before{content:"\f018"}.fa-download:before{content:"\f019"}.fa-arrow-circle-o-down:before{content:"\f01a"}.fa-arrow-circle-o-up:before{content:"\f01b"}.fa-inbox:before{content:"\f01c"}.fa-play-circle-o:before{content:"\f01d"}.fa-rotate-right:before,.fa-repeat:before{content:"\f01e"}.fa-refresh:before{content:"\f021"}.fa-list-alt:before{content:"\f022"}.fa-lock:before{content:"\f023"}.fa-flag:before{content:"\f024"}.fa-headphones:before{content:"\f025"}.fa-volume-off:before{content:"\f026"}.fa-volume-down:before{content:"\f027"}.fa-volume-up:before{content:"\f028"}.fa-qrcode:before{content:"\f029"}.fa-barcode:before{content:"\f02a"}.fa-tag:before{content:"\f02b"}.fa-tags:before{content:"\f02c"}.fa-book:before{content:"\f02d"}.fa-bookmark:before{content:"\f02e"}.fa-print:before{content:"\f02f"}.fa-camera:before{content:"\f030"}.fa-font:before{content:"\f031"}.fa-bold:before{content:"\f032"}.fa-italic:before{content:"\f033"}.fa-text-height:before{content:"\f034"}.fa-text-width:before{content:"\f035"}.fa-align-left:before{content:"\f036"}.fa-align-center:before{content:"\f037"}.fa-align-right:before{content:"\f038"}.fa-align-justify:before{content:"\f039"}.fa-list:before{content:"\f03a"}.fa-dedent:before,.fa-outdent:before{content:"\f03b"}.fa-indent:before{content:"\f03c"}.fa-video-camera:before{content:"\f03d"}.fa-photo:before,.fa-image:before,.fa-picture-o:before{content:"\f03e"}.fa-pencil:before{content:"\f040"}.fa-map-marker:before{content:"\f041"}.fa-adjust:before{content:"\f042"}.fa-tint:before{content:"\f043"}.fa-edit:before,.fa-pencil-square-o:before{content:"\f044"}.fa-share-square-o:before{content:"\f045"}.fa-check-square-o:before{content:"\f046"}.fa-arrows:before{content:"\f047"}.fa-step-backward:before{content:"\f048"}.fa-fast-backward:before{content:"\f049"}.fa-backward:before{content:"\f04a"}.fa-play:before{content:"\f04b"}.fa-pause:before{content:"\f04c"}.fa-stop:before{content:"\f04d"}.fa-forward:before{content:"\f04e"}.fa-fast-forward:before{content:"\f050"}.fa-step-forward:before{content:"\f051"}.fa-eject:before{content:"\f052"}.fa-chevron-left:before{content:"\f053"}.fa-chevron-right:before{content:"\f054"}.fa-plus-circle:before{content:"\f055"}.fa-minus-circle:before{content:"\f056"}.fa-times-circle:before{content:"\f057"}.fa-check-circle:before{content:"\f058"}.fa-question-circle:before{content:"\f059"}.fa-info-circle:before{content:"\f05a"}.fa-crosshairs:before{content:"\f05b"}.fa-times-circle-o:before{content:"\f05c"}.fa-check-circle-o:before{content:"\f05d"}.fa-ban:before{content:"\f05e"}.fa-arrow-left:before{content:"\f060"}.fa-arrow-right:before{content:"\f061"}.fa-arrow-up:before{content:"\f062"}.fa-arrow-down:before{content:"\f063"}.fa-mail-forward:before,.fa-share:before{content:"\f064"}.fa-expand:before{content:"\f065"}.fa-compress:before{content:"\f066"}.fa-plus:before{content:"\f067"}.fa-minus:before{content:"\f068"}.fa-asterisk:before{content:"\f069"}.fa-exclamation-circle:before{content:"\f06a"}.fa-gift:before{content:"\f06b"}.fa-leaf:before{content:"\f06c"}.fa-fire:before{content:"\f06d"}.fa-eye:before{content:"\f06e"}.fa-eye-slash:before{content:"\f070"}.fa-warning:before,.fa-exclamation-triangle:before{content:"\f071"}.fa-plane:before{content:"\f072"}.fa-calendar:before{content:"\f073"}.fa-random:before{content:"\f074"}.fa-comment:before{content:"\f075"}.fa-magnet:before{content:"\f076"}.fa-chevron-up:before{content:"\f077"}.fa-chevron-down:before{content:"\f078"}.fa-retweet:before{content:"\f079"}.fa-shopping-cart:before{content:"\f07a"}.fa-folder:before{content:"\f07b"}.fa-folder-open:before{content:"\f07c"}.fa-arrows-v:before{content:"\f07d"}.fa-arrows-h:before{content:"\f07e"}.fa-bar-chart-o:before,.fa-bar-chart:before{content:"\f080"}.fa-twitter-square:before{content:"\f081"}.fa-facebook-square:before{content:"\f082"}.fa-camera-retro:before{content:"\f083"}.fa-key:before{content:"\f084"}.fa-gears:before,.fa-cogs:before{content:"\f085"}.fa-comments:before{content:"\f086"}.fa-thumbs-o-up:before{content:"\f087"}.fa-thumbs-o-down:before{content:"\f088"}.fa-star-half:before{content:"\f089"}.fa-heart-o:before{content:"\f08a"}.fa-sign-out:before{content:"\f08b"}.fa-linkedin-square:before{content:"\f08c"}.fa-thumb-tack:before{content:"\f08d"}.fa-external-link:before{content:"\f08e"}.fa-sign-in:before{content:"\f090"}.fa-trophy:before{content:"\f091"}.fa-github-square:before{content:"\f092"}.fa-upload:before{content:"\f093"}.fa-lemon-o:before{content:"\f094"}.fa-phone:before{content:"\f095"}.fa-square-o:before{content:"\f096"}.fa-bookmark-o:before{content:"\f097"}.fa-phone-square:before{content:"\f098"}.fa-twitter:before{content:"\f099"}.fa-facebook-f:before,.fa-facebook:before{content:"\f09a"}.fa-github:before{content:"\f09b"}.fa-unlock:before{content:"\f09c"}.fa-credit-card:before{content:"\f09d"}.fa-feed:before,.fa-rss:before{content:"\f09e"}.fa-hdd-o:before{content:"\f0a0"}.fa-bullhorn:before{content:"\f0a1"}.fa-bell:before{content:"\f0f3"}.fa-certificate:before{content:"\f0a3"}.fa-hand-o-right:before{content:"\f0a4"}.fa-hand-o-left:before{content:"\f0a5"}.fa-hand-o-up:before{content:"\f0a6"}.fa-hand-o-down:before{content:"\f0a7"}.fa-arrow-circle-left:before{content:"\f0a8"}.fa-arrow-circle-right:before{content:"\f0a9"}.fa-arrow-circle-up:before{content:"\f0aa"}.fa-arrow-circle-down:before{content:"\f0ab"}.fa-globe:before{content:"\f0ac"}.fa-wrench:before{content:"\f0ad"}.fa-tasks:before{content:"\f0ae"}.fa-filter:before{content:"\f0b0"}.fa-briefcase:before{content:"\f0b1"}.fa-arrows-alt:before{content:"\f0b2"}.fa-group:before,.fa-users:before{content:"\f0c0"}.fa-chain:before,.fa-link:before{content:"\f0c1"}.fa-cloud:before{content:"\f0c2"}.fa-flask:before{content:"\f0c3"}.fa-cut:before,.fa-scissors:before{content:"\f0c4"}.fa-copy:before,.fa-files-o:before{content:"\f0c5"}.fa-paperclip:before{content:"\f0c6"}.fa-save:before,.fa-floppy-o:before{content:"\f0c7"}.fa-square:before{content:"\f0c8"}.fa-navicon:before,.fa-reorder:before,.fa-bars:before{content:"\f0c9"}.fa-list-ul:before{content:"\f0ca"}.fa-list-ol:before{content:"\f0cb"}.fa-strikethrough:before{content:"\f0cc"}.fa-underline:before{content:"\f0cd"}.fa-table:before{content:"\f0ce"}.fa-magic:before{content:"\f0d0"}.fa-truck:before{content:"\f0d1"}.fa-pinterest:before{content:"\f0d2"}.fa-pinterest-square:before{content:"\f0d3"}.fa-google-plus-square:before{content:"\f0d4"}.fa-google-plus:before{content:"\f0d5"}.fa-money:before{content:"\f0d6"}.fa-caret-down:before{content:"\f0d7"}.fa-caret-up:before{content:"\f0d8"}.fa-caret-left:before{content:"\f0d9"}.fa-caret-right:before{content:"\f0da"}.fa-columns:before{content:"\f0db"}.fa-unsorted:before,.fa-sort:before{content:"\f0dc"}.fa-sort-down:before,.fa-sort-desc:before{content:"\f0dd"}.fa-sort-up:before,.fa-sort-asc:before{content:"\f0de"}.fa-envelope:before{content:"\f0e0"}.fa-linkedin:before{content:"\f0e1"}.fa-rotate-left:before,.fa-undo:before{content:"\f0e2"}.fa-legal:before,.fa-gavel:before{content:"\f0e3"}.fa-dashboard:before,.fa-tachometer:before{content:"\f0e4"}.fa-comment-o:before{content:"\f0e5"}.fa-comments-o:before{content:"\f0e6"}.fa-flash:before,.fa-bolt:before{content:"\f0e7"}.fa-sitemap:before{content:"\f0e8"}.fa-umbrella:before{content:"\f0e9"}.fa-paste:before,.fa-clipboard:before{content:"\f0ea"}.fa-lightbulb-o:before{content:"\f0eb"}.fa-exchange:before{content:"\f0ec"}.fa-cloud-download:before{content:"\f0ed"}.fa-cloud-upload:before{content:"\f0ee"}.fa-user-md:before{content:"\f0f0"}.fa-stethoscope:before{content:"\f0f1"}.fa-suitcase:before{content:"\f0f2"}.fa-bell-o:before{content:"\f0a2"}.fa-coffee:before{content:"\f0f4"}.fa-cutlery:before{content:"\f0f5"}.fa-file-text-o:before{content:"\f0f6"}.fa-building-o:before{content:"\f0f7"}.fa-hospital-o:before{content:"\f0f8"}.fa-ambulance:before{content:"\f0f9"}.fa-medkit:before{content:"\f0fa"}.fa-fighter-jet:before{content:"\f0fb"}.fa-beer:before{content:"\f0fc"}.fa-h-square:before{content:"\f0fd"}.fa-plus-square:before{content:"\f0fe"}.fa-angle-double-left:before{content:"\f100"}.fa-angle-double-right:before{content:"\f101"}.fa-angle-double-up:before{content:"\f102"}.fa-angle-double-down:before{content:"\f103"}.fa-angle-left:before{content:"\f104"}.fa-angle-right:before{content:"\f105"}.fa-angle-up:before{content:"\f106"}.fa-angle-down:before{content:"\f107"}.fa-desktop:before{content:"\f108"}.fa-laptop:before{content:"\f109"}.fa-tablet:before{content:"\f10a"}.fa-mobile-phone:before,.fa-mobile:before{content:"\f10b"}.fa-circle-o:before{content:"\f10c"}.fa-quote-left:before{content:"\f10d"}.fa-quote-right:before{content:"\f10e"}.fa-spinner:before{content:"\f110"}.fa-circle:before{content:"\f111"}.fa-mail-reply:before,.fa-reply:before{content:"\f112"}.fa-github-alt:before{content:"\f113"}.fa-folder-o:before{content:"\f114"}.fa-folder-open-o:before{content:"\f115"}.fa-smile-o:before{content:"\f118"}.fa-frown-o:before{content:"\f119"}.fa-meh-o:before{content:"\f11a"}.fa-gamepad:before{content:"\f11b"}.fa-keyboard-o:before{content:"\f11c"}.fa-flag-o:before{content:"\f11d"}.fa-flag-checkered:before{content:"\f11e"}.fa-terminal:before{content:"\f120"}.fa-code:before{content:"\f121"}.fa-mail-reply-all:before,.fa-reply-all:before{content:"\f122"}.fa-star-half-empty:before,.fa-star-half-full:before,.fa-star-half-o:before{content:"\f123"}.fa-location-arrow:before{content:"\f124"}.fa-crop:before{content:"\f125"}.fa-code-fork:before{content:"\f126"}.fa-unlink:before,.fa-chain-broken:before{content:"\f127"}.fa-question:before{content:"\f128"}.fa-info:before{content:"\f129"}.fa-exclamation:before{content:"\f12a"}.fa-superscript:before{content:"\f12b"}.fa-subscript:before{content:"\f12c"}.fa-eraser:before{content:"\f12d"}.fa-puzzle-piece:before{content:"\f12e"}.fa-microphone:before{content:"\f130"}.fa-microphone-slash:before{content:"\f131"}.fa-shield:before{content:"\f132"}.fa-calendar-o:before{content:"\f133"}.fa-fire-extinguisher:before{content:"\f134"}.fa-rocket:before{content:"\f135"}.fa-maxcdn:before{content:"\f136"}.fa-chevron-circle-left:before{content:"\f137"}.fa-chevron-circle-right:before{content:"\f138"}.fa-chevron-circle-up:before{content:"\f139"}.fa-chevron-circle-down:before{content:"\f13a"}.fa-html5:before{content:"\f13b"}.fa-css3:before{content:"\f13c"}.fa-anchor:before{content:"\f13d"}.fa-unlock-alt:before{content:"\f13e"}.fa-bullseye:before{content:"\f140"}.fa-ellipsis-h:before{content:"\f141"}.fa-ellipsis-v:before{content:"\f142"}.fa-rss-square:before{content:"\f143"}.fa-play-circle:before{content:"\f144"}.fa-ticket:before{content:"\f145"}.fa-minus-square:before{content:"\f146"}.fa-minus-square-o:before{content:"\f147"}.fa-level-up:before{content:"\f148"}.fa-level-down:before{content:"\f149"}.fa-check-square:before{content:"\f14a"}.fa-pencil-square:before{content:"\f14b"}.fa-external-link-square:before{content:"\f14c"}.fa-share-square:before{content:"\f14d"}.fa-compass:before{content:"\f14e"}.fa-toggle-down:before,.fa-caret-square-o-down:before{content:"\f150"}.fa-toggle-up:before,.fa-caret-square-o-up:before{content:"\f151"}.fa-toggle-right:before,.fa-caret-square-o-right:before{content:"\f152"}.fa-euro:before,.fa-eur:before{content:"\f153"}.fa-gbp:before{content:"\f154"}.fa-dollar:before,.fa-usd:before{content:"\f155"}.fa-rupee:before,.fa-inr:before{content:"\f156"}.fa-cny:before,.fa-rmb:before,.fa-yen:before,.fa-jpy:before{content:"\f157"}.fa-ruble:before,.fa-rouble:before,.fa-rub:before{content:"\f158"}.fa-won:before,.fa-krw:before{content:"\f159"}.fa-bitcoin:before,.fa-btc:before{content:"\f15a"}.fa-file:before{content:"\f15b"}.fa-file-text:before{content:"\f15c"}.fa-sort-alpha-asc:before{content:"\f15d"}.fa-sort-alpha-desc:before{content:"\f15e"}.fa-sort-amount-asc:before{content:"\f160"}.fa-sort-amount-desc:before{content:"\f161"}.fa-sort-numeric-asc:before{content:"\f162"}.fa-sort-numeric-desc:before{content:"\f163"}.fa-thumbs-up:before{content:"\f164"}.fa-thumbs-down:before{content:"\f165"}.fa-youtube-square:before{content:"\f166"}.fa-youtube:before{content:"\f167"}.fa-xing:before{content:"\f168"}.fa-xing-square:before{content:"\f169"}.fa-youtube-play:before{content:"\f16a"}.fa-dropbox:before{content:"\f16b"}.fa-stack-overflow:before{content:"\f16c"}.fa-instagram:before{content:"\f16d"}.fa-flickr:before{content:"\f16e"}.fa-adn:before{content:"\f170"}.fa-bitbucket:before{content:"\f171"}.fa-bitbucket-square:before{content:"\f172"}.fa-tumblr:before{content:"\f173"}.fa-tumblr-square:before{content:"\f174"}.fa-long-arrow-down:before{content:"\f175"}.fa-long-arrow-up:before{content:"\f176"}.fa-long-arrow-left:before{content:"\f177"}.fa-long-arrow-right:before{content:"\f178"}.fa-apple:before{content:"\f179"}.fa-windows:before{content:"\f17a"}.fa-android:before{content:"\f17b"}.fa-linux:before{content:"\f17c"}.fa-dribbble:before{content:"\f17d"}.fa-skype:before{content:"\f17e"}.fa-foursquare:before{content:"\f180"}.fa-trello:before{content:"\f181"}.fa-female:before{content:"\f182"}.fa-male:before{content:"\f183"}.fa-gittip:before,.fa-gratipay:before{content:"\f184"}.fa-sun-o:before{content:"\f185"}.fa-moon-o:before{content:"\f186"}.fa-archive:before{content:"\f187"}.fa-bug:before{content:"\f188"}.fa-vk:before{content:"\f189"}.fa-weibo:before{content:"\f18a"}.fa-renren:before{content:"\f18b"}.fa-pagelines:before{content:"\f18c"}.fa-stack-exchange:before{content:"\f18d"}.fa-arrow-circle-o-right:before{content:"\f18e"}.fa-arrow-circle-o-left:before{content:"\f190"}.fa-toggle-left:before,.fa-caret-square-o-left:before{content:"\f191"}.fa-dot-circle-o:before{content:"\f192"}.fa-wheelchair:before{content:"\f193"}.fa-vimeo-square:before{content:"\f194"}.fa-turkish-lira:before,.fa-try:before{content:"\f195"}.fa-plus-square-o:before{content:"\f196"}.fa-space-shuttle:before{content:"\f197"}.fa-slack:before{content:"\f198"}.fa-envelope-square:before{content:"\f199"}.fa-wordpress:before{content:"\f19a"}.fa-openid:before{content:"\f19b"}.fa-institution:before,.fa-bank:before,.fa-university:before{content:"\f19c"}.fa-mortar-board:before,.fa-graduation-cap:before{content:"\f19d"}.fa-yahoo:before{content:"\f19e"}.fa-google:before{content:"\f1a0"}.fa-reddit:before{content:"\f1a1"}.fa-reddit-square:before{content:"\f1a2"}.fa-stumbleupon-circle:before{content:"\f1a3"}.fa-stumbleupon:before{content:"\f1a4"}.fa-delicious:before{content:"\f1a5"}.fa-digg:before{content:"\f1a6"}.fa-pied-piper-pp:before{content:"\f1a7"}.fa-pied-piper-alt:before{content:"\f1a8"}.fa-drupal:before{content:"\f1a9"}.fa-joomla:before{content:"\f1aa"}.fa-language:before{content:"\f1ab"}.fa-fax:before{content:"\f1ac"}.fa-building:before{content:"\f1ad"}.fa-child:before{content:"\f1ae"}.fa-paw:before{content:"\f1b0"}.fa-spoon:before{content:"\f1b1"}.fa-cube:before{content:"\f1b2"}.fa-cubes:before{content:"\f1b3"}.fa-behance:before{content:"\f1b4"}.fa-behance-square:before{content:"\f1b5"}.fa-steam:before{content:"\f1b6"}.fa-steam-square:before{content:"\f1b7"}.fa-recycle:before{content:"\f1b8"}.fa-automobile:before,.fa-car:before{content:"\f1b9"}.fa-cab:before,.fa-taxi:before{content:"\f1ba"}.fa-tree:before{content:"\f1bb"}.fa-spotify:before{content:"\f1bc"}.fa-deviantart:before{content:"\f1bd"}.fa-soundcloud:before{content:"\f1be"}.fa-database:before{content:"\f1c0"}.fa-file-pdf-o:before{content:"\f1c1"}.fa-file-word-o:before{content:"\f1c2"}.fa-file-excel-o:before{content:"\f1c3"}.fa-file-powerpoint-o:before{content:"\f1c4"}.fa-file-photo-o:before,.fa-file-picture-o:before,.fa-file-image-o:before{content:"\f1c5"}.fa-file-zip-o:before,.fa-file-archive-o:before{content:"\f1c6"}.fa-file-sound-o:before,.fa-file-audio-o:before{content:"\f1c7"}.fa-file-movie-o:before,.fa-file-video-o:before{content:"\f1c8"}.fa-file-code-o:before{content:"\f1c9"}.fa-vine:before{content:"\f1ca"}.fa-codepen:before{content:"\f1cb"}.fa-jsfiddle:before{content:"\f1cc"}.fa-life-bouy:before,.fa-life-buoy:before,.fa-life-saver:before,.fa-support:before,.fa-life-ring:before{content:"\f1cd"}.fa-circle-o-notch:before{content:"\f1ce"}.fa-ra:before,.fa-resistance:before,.fa-rebel:before{content:"\f1d0"}.fa-ge:before,.fa-empire:before{content:"\f1d1"}.fa-git-square:before{content:"\f1d2"}.fa-git:before{content:"\f1d3"}.fa-y-combinator-square:before,.fa-yc-square:before,.fa-hacker-news:before{content:"\f1d4"}.fa-tencent-weibo:before{content:"\f1d5"}.fa-qq:before{content:"\f1d6"}.fa-wechat:before,.fa-weixin:before{content:"\f1d7"}.fa-send:before,.fa-paper-plane:before{content:"\f1d8"}.fa-send-o:before,.fa-paper-plane-o:before{content:"\f1d9"}.fa-history:before{content:"\f1da"}.fa-circle-thin:before{content:"\f1db"}.fa-header:before{content:"\f1dc"}.fa-paragraph:before{content:"\f1dd"}.fa-sliders:before{content:"\f1de"}.fa-share-alt:before{content:"\f1e0"}.fa-share-alt-square:before{content:"\f1e1"}.fa-bomb:before{content:"\f1e2"}.fa-soccer-ball-o:before,.fa-futbol-o:before{content:"\f1e3"}.fa-tty:before{content:"\f1e4"}.fa-binoculars:before{content:"\f1e5"}.fa-plug:before{content:"\f1e6"}.fa-slideshare:before{content:"\f1e7"}.fa-twitch:before{content:"\f1e8"}.fa-yelp:before{content:"\f1e9"}.fa-newspaper-o:before{content:"\f1ea"}.fa-wifi:before{content:"\f1eb"}.fa-calculator:before{content:"\f1ec"}.fa-paypal:before{content:"\f1ed"}.fa-google-wallet:before{content:"\f1ee"}.fa-cc-visa:before{content:"\f1f0"}.fa-cc-mastercard:before{content:"\f1f1"}.fa-cc-discover:before{content:"\f1f2"}.fa-cc-amex:before{content:"\f1f3"}.fa-cc-paypal:before{content:"\f1f4"}.fa-cc-stripe:before{content:"\f1f5"}.fa-bell-slash:before{content:"\f1f6"}.fa-bell-slash-o:before{content:"\f1f7"}.fa-trash:before{content:"\f1f8"}.fa-copyright:before{content:"\f1f9"}.fa-at:before{content:"\f1fa"}.fa-eyedropper:before{content:"\f1fb"}.fa-paint-brush:before{content:"\f1fc"}.fa-birthday-cake:before{content:"\f1fd"}.fa-area-chart:before{content:"\f1fe"}.fa-pie-chart:before{content:"\f200"}.fa-line-chart:before{content:"\f201"}.fa-lastfm:before{content:"\f202"}.fa-lastfm-square:before{content:"\f203"}.fa-toggle-off:before{content:"\f204"}.fa-toggle-on:before{content:"\f205"}.fa-bicycle:before{content:"\f206"}.fa-bus:before{content:"\f207"}.fa-ioxhost:before{content:"\f208"}.fa-angellist:before{content:"\f209"}.fa-cc:before{content:"\f20a"}.fa-shekel:before,.fa-sheqel:before,.fa-ils:before{content:"\f20b"}.fa-meanpath:before{content:"\f20c"}.fa-buysellads:before{content:"\f20d"}.fa-connectdevelop:before{content:"\f20e"}.fa-dashcube:before{content:"\f210"}.fa-forumbee:before{content:"\f211"}.fa-leanpub:before{content:"\f212"}.fa-sellsy:before{content:"\f213"}.fa-shirtsinbulk:before{content:"\f214"}.fa-simplybuilt:before{content:"\f215"}.fa-skyatlas:before{content:"\f216"}.fa-cart-plus:before{content:"\f217"}.fa-cart-arrow-down:before{content:"\f218"}.fa-diamond:before{content:"\f219"}.fa-ship:before{content:"\f21a"}.fa-user-secret:before{content:"\f21b"}.fa-motorcycle:before{content:"\f21c"}.fa-street-view:before{content:"\f21d"}.fa-heartbeat:before{content:"\f21e"}.fa-venus:before{content:"\f221"}.fa-mars:before{content:"\f222"}.fa-mercury:before{content:"\f223"}.fa-intersex:before,.fa-transgender:before{content:"\f224"}.fa-transgender-alt:before{content:"\f225"}.fa-venus-double:before{content:"\f226"}.fa-mars-double:before{content:"\f227"}.fa-venus-mars:before{content:"\f228"}.fa-mars-stroke:before{content:"\f229"}.fa-mars-stroke-v:before{content:"\f22a"}.fa-mars-stroke-h:before{content:"\f22b"}.fa-neuter:before{content:"\f22c"}.fa-genderless:before{content:"\f22d"}.fa-facebook-official:before{content:"\f230"}.fa-pinterest-p:before{content:"\f231"}.fa-whatsapp:before{content:"\f232"}.fa-server:before{content:"\f233"}.fa-user-plus:before{content:"\f234"}.fa-user-times:before{content:"\f235"}.fa-hotel:before,.fa-bed:before{content:"\f236"}.fa-viacoin:before{content:"\f237"}.fa-train:before{content:"\f238"}.fa-subway:before{content:"\f239"}.fa-medium:before{content:"\f23a"}.fa-yc:before,.fa-y-combinator:before{content:"\f23b"}.fa-optin-monster:before{content:"\f23c"}.fa-opencart:before{content:"\f23d"}.fa-expeditedssl:before{content:"\f23e"}.fa-battery-4:before,.fa-battery-full:before{content:"\f240"}.fa-battery-3:before,.fa-battery-three-quarters:before{content:"\f241"}.fa-battery-2:before,.fa-battery-half:before{content:"\f242"}.fa-battery-1:before,.fa-battery-quarter:before{content:"\f243"}.fa-battery-0:before,.fa-battery-empty:before{content:"\f244"}.fa-mouse-pointer:before{content:"\f245"}.fa-i-cursor:before{content:"\f246"}.fa-object-group:before{content:"\f247"}.fa-object-ungroup:before{content:"\f248"}.fa-sticky-note:before{content:"\f249"}.fa-sticky-note-o:before{content:"\f24a"}.fa-cc-jcb:before{content:"\f24b"}.fa-cc-diners-club:before{content:"\f24c"}.fa-clone:before{content:"\f24d"}.fa-balance-scale:before{content:"\f24e"}.fa-hourglass-o:before{content:"\f250"}.fa-hourglass-1:before,.fa-hourglass-start:before{content:"\f251"}.fa-hourglass-2:before,.fa-hourglass-half:before{content:"\f252"}.fa-hourglass-3:before,.fa-hourglass-end:before{content:"\f253"}.fa-hourglass:before{content:"\f254"}.fa-hand-grab-o:before,.fa-hand-rock-o:before{content:"\f255"}.fa-hand-stop-o:before,.fa-hand-paper-o:before{content:"\f256"}.fa-hand-scissors-o:before{content:"\f257"}.fa-hand-lizard-o:before{content:"\f258"}.fa-hand-spock-o:before{content:"\f259"}.fa-hand-pointer-o:before{content:"\f25a"}.fa-hand-peace-o:before{content:"\f25b"}.fa-trademark:before{content:"\f25c"}.fa-registered:before{content:"\f25d"}.fa-creative-commons:before{content:"\f25e"}.fa-gg:before{content:"\f260"}.fa-gg-circle:before{content:"\f261"}.fa-tripadvisor:before{content:"\f262"}.fa-odnoklassniki:before{content:"\f263"}.fa-odnoklassniki-square:before{content:"\f264"}.fa-get-pocket:before{content:"\f265"}.fa-wikipedia-w:before{content:"\f266"}.fa-safari:before{content:"\f267"}.fa-chrome:before{content:"\f268"}.fa-firefox:before{content:"\f269"}.fa-opera:before{content:"\f26a"}.fa-internet-explorer:before{content:"\f26b"}.fa-tv:before,.fa-television:before{content:"\f26c"}.fa-contao:before{content:"\f26d"}.fa-500px:before{content:"\f26e"}.fa-amazon:before{content:"\f270"}.fa-calendar-plus-o:before{content:"\f271"}.fa-calendar-minus-o:before{content:"\f272"}.fa-calendar-times-o:before{content:"\f273"}.fa-calendar-check-o:before{content:"\f274"}.fa-industry:before{content:"\f275"}.fa-map-pin:before{content:"\f276"}.fa-map-signs:before{content:"\f277"}.fa-map-o:before{content:"\f278"}.fa-map:before{content:"\f279"}.fa-commenting:before{content:"\f27a"}.fa-commenting-o:before{content:"\f27b"}.fa-houzz:before{content:"\f27c"}.fa-vimeo:before{content:"\f27d"}.fa-black-tie:before{content:"\f27e"}.fa-fonticons:before{content:"\f280"}.fa-reddit-alien:before{content:"\f281"}.fa-edge:before{content:"\f282"}.fa-credit-card-alt:before{content:"\f283"}.fa-codiepie:before{content:"\f284"}.fa-modx:before{content:"\f285"}.fa-fort-awesome:before{content:"\f286"}.fa-usb:before{content:"\f287"}.fa-product-hunt:before{content:"\f288"}.fa-mixcloud:before{content:"\f289"}.fa-scribd:before{content:"\f28a"}.fa-pause-circle:before{content:"\f28b"}.fa-pause-circle-o:before{content:"\f28c"}.fa-stop-circle:before{content:"\f28d"}.fa-stop-circle-o:before{content:"\f28e"}.fa-shopping-bag:before{content:"\f290"}.fa-shopping-basket:before{content:"\f291"}.fa-hashtag:before{content:"\f292"}.fa-bluetooth:before{content:"\f293"}.fa-bluetooth-b:before{content:"\f294"}.fa-percent:before{content:"\f295"}.fa-gitlab:before{content:"\f296"}.fa-wpbeginner:before{content:"\f297"}.fa-wpforms:before{content:"\f298"}.fa-envira:before{content:"\f299"}.fa-universal-access:before{content:"\f29a"}.fa-wheelchair-alt:before{content:"\f29b"}.fa-question-circle-o:before{content:"\f29c"}.fa-blind:before{content:"\f29d"}.fa-audio-description:before{content:"\f29e"}.fa-volume-control-phone:before{content:"\f2a0"}.fa-braille:before{content:"\f2a1"}.fa-assistive-listening-systems:before{content:"\f2a2"}.fa-asl-interpreting:before,.fa-american-sign-language-interpreting:before{content:"\f2a3"}.fa-deafness:before,.fa-hard-of-hearing:before,.fa-deaf:before{content:"\f2a4"}.fa-glide:before{content:"\f2a5"}.fa-glide-g:before{content:"\f2a6"}.fa-signing:before,.fa-sign-language:before{content:"\f2a7"}.fa-low-vision:before{content:"\f2a8"}.fa-viadeo:before{content:"\f2a9"}.fa-viadeo-square:before{content:"\f2aa"}.fa-snapchat:before{content:"\f2ab"}.fa-snapchat-ghost:before{content:"\f2ac"}.fa-snapchat-square:before{content:"\f2ad"}.fa-pied-piper:before{content:"\f2ae"}.fa-first-order:before{content:"\f2b0"}.fa-yoast:before{content:"\f2b1"}.fa-themeisle:before{content:"\f2b2"}.fa-google-plus-circle:before,.fa-google-plus-official:before{content:"\f2b3"}.fa-fa:before,.fa-font-awesome:before{content:"\f2b4"}.sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0, 0, 0, 0);border:0}.sr-only-focusable:active,.sr-only-focusable:focus{position:static;width:auto;height:auto;margin:0;overflow:visible;clip:auto} + */@font-face{font-family:'FontAwesome';src:url('../fonts/fontawesome-webfont.eot?v=4.7.0');src:url('../fonts/fontawesome-webfont.eot?#iefix&v=4.7.0') format('embedded-opentype'),url('../fonts/fontawesome-webfont.woff2?v=4.7.0') format('woff2'),url('../fonts/fontawesome-webfont.woff?v=4.7.0') format('woff'),url('../fonts/fontawesome-webfont.ttf?v=4.7.0') format('truetype'),url('../fonts/fontawesome-webfont.svg?v=4.7.0#fontawesomeregular') format('svg');font-weight:normal;font-style:normal}.fa{display:inline-block;font:normal normal normal 14px/1 FontAwesome;font-size:inherit;text-rendering:auto;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.fa-lg{font-size:1.33333333em;line-height:.75em;vertical-align:-15%}.fa-2x{font-size:2em}.fa-3x{font-size:3em}.fa-4x{font-size:4em}.fa-5x{font-size:5em}.fa-fw{width:1.28571429em;text-align:center}.fa-ul{padding-left:0;margin-left:2.14285714em;list-style-type:none}.fa-ul>li{position:relative}.fa-li{position:absolute;left:-2.14285714em;width:2.14285714em;top:.14285714em;text-align:center}.fa-li.fa-lg{left:-1.85714286em}.fa-border{padding:.2em .25em .15em;border:solid .08em #eee;border-radius:.1em}.fa-pull-left{float:left}.fa-pull-right{float:right}.fa.fa-pull-left{margin-right:.3em}.fa.fa-pull-right{margin-left:.3em}.pull-right{float:right}.pull-left{float:left}.fa.pull-left{margin-right:.3em}.fa.pull-right{margin-left:.3em}.fa-spin{-webkit-animation:fa-spin 2s infinite linear;animation:fa-spin 2s infinite linear}.fa-pulse{-webkit-animation:fa-spin 1s infinite steps(8);animation:fa-spin 1s infinite steps(8)}@-webkit-keyframes fa-spin{0%{-webkit-transform:rotate(0deg);transform:rotate(0deg)}100%{-webkit-transform:rotate(359deg);transform:rotate(359deg)}}@keyframes fa-spin{0%{-webkit-transform:rotate(0deg);transform:rotate(0deg)}100%{-webkit-transform:rotate(359deg);transform:rotate(359deg)}}.fa-rotate-90{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=1)";-webkit-transform:rotate(90deg);-ms-transform:rotate(90deg);transform:rotate(90deg)}.fa-rotate-180{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=2)";-webkit-transform:rotate(180deg);-ms-transform:rotate(180deg);transform:rotate(180deg)}.fa-rotate-270{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=3)";-webkit-transform:rotate(270deg);-ms-transform:rotate(270deg);transform:rotate(270deg)}.fa-flip-horizontal{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=0, mirror=1)";-webkit-transform:scale(-1, 1);-ms-transform:scale(-1, 1);transform:scale(-1, 1)}.fa-flip-vertical{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=2, mirror=1)";-webkit-transform:scale(1, -1);-ms-transform:scale(1, -1);transform:scale(1, -1)}:root .fa-rotate-90,:root .fa-rotate-180,:root .fa-rotate-270,:root .fa-flip-horizontal,:root .fa-flip-vertical{filter:none}.fa-stack{position:relative;display:inline-block;width:2em;height:2em;line-height:2em;vertical-align:middle}.fa-stack-1x,.fa-stack-2x{position:absolute;left:0;width:100%;text-align:center}.fa-stack-1x{line-height:inherit}.fa-stack-2x{font-size:2em}.fa-inverse{color:#fff}.fa-glass:before{content:"\f000"}.fa-music:before{content:"\f001"}.fa-search:before{content:"\f002"}.fa-envelope-o:before{content:"\f003"}.fa-heart:before{content:"\f004"}.fa-star:before{content:"\f005"}.fa-star-o:before{content:"\f006"}.fa-user:before{content:"\f007"}.fa-film:before{content:"\f008"}.fa-th-large:before{content:"\f009"}.fa-th:before{content:"\f00a"}.fa-th-list:before{content:"\f00b"}.fa-check:before{content:"\f00c"}.fa-remove:before,.fa-close:before,.fa-times:before{content:"\f00d"}.fa-search-plus:before{content:"\f00e"}.fa-search-minus:before{content:"\f010"}.fa-power-off:before{content:"\f011"}.fa-signal:before{content:"\f012"}.fa-gear:before,.fa-cog:before{content:"\f013"}.fa-trash-o:before{content:"\f014"}.fa-home:before{content:"\f015"}.fa-file-o:before{content:"\f016"}.fa-clock-o:before{content:"\f017"}.fa-road:before{content:"\f018"}.fa-download:before{content:"\f019"}.fa-arrow-circle-o-down:before{content:"\f01a"}.fa-arrow-circle-o-up:before{content:"\f01b"}.fa-inbox:before{content:"\f01c"}.fa-play-circle-o:before{content:"\f01d"}.fa-rotate-right:before,.fa-repeat:before{content:"\f01e"}.fa-refresh:before{content:"\f021"}.fa-list-alt:before{content:"\f022"}.fa-lock:before{content:"\f023"}.fa-flag:before{content:"\f024"}.fa-headphones:before{content:"\f025"}.fa-volume-off:before{content:"\f026"}.fa-volume-down:before{content:"\f027"}.fa-volume-up:before{content:"\f028"}.fa-qrcode:before{content:"\f029"}.fa-barcode:before{content:"\f02a"}.fa-tag:before{content:"\f02b"}.fa-tags:before{content:"\f02c"}.fa-book:before{content:"\f02d"}.fa-bookmark:before{content:"\f02e"}.fa-print:before{content:"\f02f"}.fa-camera:before{content:"\f030"}.fa-font:before{content:"\f031"}.fa-bold:before{content:"\f032"}.fa-italic:before{content:"\f033"}.fa-text-height:before{content:"\f034"}.fa-text-width:before{content:"\f035"}.fa-align-left:before{content:"\f036"}.fa-align-center:before{content:"\f037"}.fa-align-right:before{content:"\f038"}.fa-align-justify:before{content:"\f039"}.fa-list:before{content:"\f03a"}.fa-dedent:before,.fa-outdent:before{content:"\f03b"}.fa-indent:before{content:"\f03c"}.fa-video-camera:before{content:"\f03d"}.fa-photo:before,.fa-image:before,.fa-picture-o:before{content:"\f03e"}.fa-pencil:before{content:"\f040"}.fa-map-marker:before{content:"\f041"}.fa-adjust:before{content:"\f042"}.fa-tint:before{content:"\f043"}.fa-edit:before,.fa-pencil-square-o:before{content:"\f044"}.fa-share-square-o:before{content:"\f045"}.fa-check-square-o:before{content:"\f046"}.fa-arrows:before{content:"\f047"}.fa-step-backward:before{content:"\f048"}.fa-fast-backward:before{content:"\f049"}.fa-backward:before{content:"\f04a"}.fa-play:before{content:"\f04b"}.fa-pause:before{content:"\f04c"}.fa-stop:before{content:"\f04d"}.fa-forward:before{content:"\f04e"}.fa-fast-forward:before{content:"\f050"}.fa-step-forward:before{content:"\f051"}.fa-eject:before{content:"\f052"}.fa-chevron-left:before{content:"\f053"}.fa-chevron-right:before{content:"\f054"}.fa-plus-circle:before{content:"\f055"}.fa-minus-circle:before{content:"\f056"}.fa-times-circle:before{content:"\f057"}.fa-check-circle:before{content:"\f058"}.fa-question-circle:before{content:"\f059"}.fa-info-circle:before{content:"\f05a"}.fa-crosshairs:before{content:"\f05b"}.fa-times-circle-o:before{content:"\f05c"}.fa-check-circle-o:before{content:"\f05d"}.fa-ban:before{content:"\f05e"}.fa-arrow-left:before{content:"\f060"}.fa-arrow-right:before{content:"\f061"}.fa-arrow-up:before{content:"\f062"}.fa-arrow-down:before{content:"\f063"}.fa-mail-forward:before,.fa-share:before{content:"\f064"}.fa-expand:before{content:"\f065"}.fa-compress:before{content:"\f066"}.fa-plus:before{content:"\f067"}.fa-minus:before{content:"\f068"}.fa-asterisk:before{content:"\f069"}.fa-exclamation-circle:before{content:"\f06a"}.fa-gift:before{content:"\f06b"}.fa-leaf:before{content:"\f06c"}.fa-fire:before{content:"\f06d"}.fa-eye:before{content:"\f06e"}.fa-eye-slash:before{content:"\f070"}.fa-warning:before,.fa-exclamation-triangle:before{content:"\f071"}.fa-plane:before{content:"\f072"}.fa-calendar:before{content:"\f073"}.fa-random:before{content:"\f074"}.fa-comment:before{content:"\f075"}.fa-magnet:before{content:"\f076"}.fa-chevron-up:before{content:"\f077"}.fa-chevron-down:before{content:"\f078"}.fa-retweet:before{content:"\f079"}.fa-shopping-cart:before{content:"\f07a"}.fa-folder:before{content:"\f07b"}.fa-folder-open:before{content:"\f07c"}.fa-arrows-v:before{content:"\f07d"}.fa-arrows-h:before{content:"\f07e"}.fa-bar-chart-o:before,.fa-bar-chart:before{content:"\f080"}.fa-twitter-square:before{content:"\f081"}.fa-facebook-square:before{content:"\f082"}.fa-camera-retro:before{content:"\f083"}.fa-key:before{content:"\f084"}.fa-gears:before,.fa-cogs:before{content:"\f085"}.fa-comments:before{content:"\f086"}.fa-thumbs-o-up:before{content:"\f087"}.fa-thumbs-o-down:before{content:"\f088"}.fa-star-half:before{content:"\f089"}.fa-heart-o:before{content:"\f08a"}.fa-sign-out:before{content:"\f08b"}.fa-linkedin-square:before{content:"\f08c"}.fa-thumb-tack:before{content:"\f08d"}.fa-external-link:before{content:"\f08e"}.fa-sign-in:before{content:"\f090"}.fa-trophy:before{content:"\f091"}.fa-github-square:before{content:"\f092"}.fa-upload:before{content:"\f093"}.fa-lemon-o:before{content:"\f094"}.fa-phone:before{content:"\f095"}.fa-square-o:before{content:"\f096"}.fa-bookmark-o:before{content:"\f097"}.fa-phone-square:before{content:"\f098"}.fa-twitter:before{content:"\f099"}.fa-facebook-f:before,.fa-facebook:before{content:"\f09a"}.fa-github:before{content:"\f09b"}.fa-unlock:before{content:"\f09c"}.fa-credit-card:before{content:"\f09d"}.fa-feed:before,.fa-rss:before{content:"\f09e"}.fa-hdd-o:before{content:"\f0a0"}.fa-bullhorn:before{content:"\f0a1"}.fa-bell:before{content:"\f0f3"}.fa-certificate:before{content:"\f0a3"}.fa-hand-o-right:before{content:"\f0a4"}.fa-hand-o-left:before{content:"\f0a5"}.fa-hand-o-up:before{content:"\f0a6"}.fa-hand-o-down:before{content:"\f0a7"}.fa-arrow-circle-left:before{content:"\f0a8"}.fa-arrow-circle-right:before{content:"\f0a9"}.fa-arrow-circle-up:before{content:"\f0aa"}.fa-arrow-circle-down:before{content:"\f0ab"}.fa-globe:before{content:"\f0ac"}.fa-wrench:before{content:"\f0ad"}.fa-tasks:before{content:"\f0ae"}.fa-filter:before{content:"\f0b0"}.fa-briefcase:before{content:"\f0b1"}.fa-arrows-alt:before{content:"\f0b2"}.fa-group:before,.fa-users:before{content:"\f0c0"}.fa-chain:before,.fa-link:before{content:"\f0c1"}.fa-cloud:before{content:"\f0c2"}.fa-flask:before{content:"\f0c3"}.fa-cut:before,.fa-scissors:before{content:"\f0c4"}.fa-copy:before,.fa-files-o:before{content:"\f0c5"}.fa-paperclip:before{content:"\f0c6"}.fa-save:before,.fa-floppy-o:before{content:"\f0c7"}.fa-square:before{content:"\f0c8"}.fa-navicon:before,.fa-reorder:before,.fa-bars:before{content:"\f0c9"}.fa-list-ul:before{content:"\f0ca"}.fa-list-ol:before{content:"\f0cb"}.fa-strikethrough:before{content:"\f0cc"}.fa-underline:before{content:"\f0cd"}.fa-table:before{content:"\f0ce"}.fa-magic:before{content:"\f0d0"}.fa-truck:before{content:"\f0d1"}.fa-pinterest:before{content:"\f0d2"}.fa-pinterest-square:before{content:"\f0d3"}.fa-google-plus-square:before{content:"\f0d4"}.fa-google-plus:before{content:"\f0d5"}.fa-money:before{content:"\f0d6"}.fa-caret-down:before{content:"\f0d7"}.fa-caret-up:before{content:"\f0d8"}.fa-caret-left:before{content:"\f0d9"}.fa-caret-right:before{content:"\f0da"}.fa-columns:before{content:"\f0db"}.fa-unsorted:before,.fa-sort:before{content:"\f0dc"}.fa-sort-down:before,.fa-sort-desc:before{content:"\f0dd"}.fa-sort-up:before,.fa-sort-asc:before{content:"\f0de"}.fa-envelope:before{content:"\f0e0"}.fa-linkedin:before{content:"\f0e1"}.fa-rotate-left:before,.fa-undo:before{content:"\f0e2"}.fa-legal:before,.fa-gavel:before{content:"\f0e3"}.fa-dashboard:before,.fa-tachometer:before{content:"\f0e4"}.fa-comment-o:before{content:"\f0e5"}.fa-comments-o:before{content:"\f0e6"}.fa-flash:before,.fa-bolt:before{content:"\f0e7"}.fa-sitemap:before{content:"\f0e8"}.fa-umbrella:before{content:"\f0e9"}.fa-paste:before,.fa-clipboard:before{content:"\f0ea"}.fa-lightbulb-o:before{content:"\f0eb"}.fa-exchange:before{content:"\f0ec"}.fa-cloud-download:before{content:"\f0ed"}.fa-cloud-upload:before{content:"\f0ee"}.fa-user-md:before{content:"\f0f0"}.fa-stethoscope:before{content:"\f0f1"}.fa-suitcase:before{content:"\f0f2"}.fa-bell-o:before{content:"\f0a2"}.fa-coffee:before{content:"\f0f4"}.fa-cutlery:before{content:"\f0f5"}.fa-file-text-o:before{content:"\f0f6"}.fa-building-o:before{content:"\f0f7"}.fa-hospital-o:before{content:"\f0f8"}.fa-ambulance:before{content:"\f0f9"}.fa-medkit:before{content:"\f0fa"}.fa-fighter-jet:before{content:"\f0fb"}.fa-beer:before{content:"\f0fc"}.fa-h-square:before{content:"\f0fd"}.fa-plus-square:before{content:"\f0fe"}.fa-angle-double-left:before{content:"\f100"}.fa-angle-double-right:before{content:"\f101"}.fa-angle-double-up:before{content:"\f102"}.fa-angle-double-down:before{content:"\f103"}.fa-angle-left:before{content:"\f104"}.fa-angle-right:before{content:"\f105"}.fa-angle-up:before{content:"\f106"}.fa-angle-down:before{content:"\f107"}.fa-desktop:before{content:"\f108"}.fa-laptop:before{content:"\f109"}.fa-tablet:before{content:"\f10a"}.fa-mobile-phone:before,.fa-mobile:before{content:"\f10b"}.fa-circle-o:before{content:"\f10c"}.fa-quote-left:before{content:"\f10d"}.fa-quote-right:before{content:"\f10e"}.fa-spinner:before{content:"\f110"}.fa-circle:before{content:"\f111"}.fa-mail-reply:before,.fa-reply:before{content:"\f112"}.fa-github-alt:before{content:"\f113"}.fa-folder-o:before{content:"\f114"}.fa-folder-open-o:before{content:"\f115"}.fa-smile-o:before{content:"\f118"}.fa-frown-o:before{content:"\f119"}.fa-meh-o:before{content:"\f11a"}.fa-gamepad:before{content:"\f11b"}.fa-keyboard-o:before{content:"\f11c"}.fa-flag-o:before{content:"\f11d"}.fa-flag-checkered:before{content:"\f11e"}.fa-terminal:before{content:"\f120"}.fa-code:before{content:"\f121"}.fa-mail-reply-all:before,.fa-reply-all:before{content:"\f122"}.fa-star-half-empty:before,.fa-star-half-full:before,.fa-star-half-o:before{content:"\f123"}.fa-location-arrow:before{content:"\f124"}.fa-crop:before{content:"\f125"}.fa-code-fork:before{content:"\f126"}.fa-unlink:before,.fa-chain-broken:before{content:"\f127"}.fa-question:before{content:"\f128"}.fa-info:before{content:"\f129"}.fa-exclamation:before{content:"\f12a"}.fa-superscript:before{content:"\f12b"}.fa-subscript:before{content:"\f12c"}.fa-eraser:before{content:"\f12d"}.fa-puzzle-piece:before{content:"\f12e"}.fa-microphone:before{content:"\f130"}.fa-microphone-slash:before{content:"\f131"}.fa-shield:before{content:"\f132"}.fa-calendar-o:before{content:"\f133"}.fa-fire-extinguisher:before{content:"\f134"}.fa-rocket:before{content:"\f135"}.fa-maxcdn:before{content:"\f136"}.fa-chevron-circle-left:before{content:"\f137"}.fa-chevron-circle-right:before{content:"\f138"}.fa-chevron-circle-up:before{content:"\f139"}.fa-chevron-circle-down:before{content:"\f13a"}.fa-html5:before{content:"\f13b"}.fa-css3:before{content:"\f13c"}.fa-anchor:before{content:"\f13d"}.fa-unlock-alt:before{content:"\f13e"}.fa-bullseye:before{content:"\f140"}.fa-ellipsis-h:before{content:"\f141"}.fa-ellipsis-v:before{content:"\f142"}.fa-rss-square:before{content:"\f143"}.fa-play-circle:before{content:"\f144"}.fa-ticket:before{content:"\f145"}.fa-minus-square:before{content:"\f146"}.fa-minus-square-o:before{content:"\f147"}.fa-level-up:before{content:"\f148"}.fa-level-down:before{content:"\f149"}.fa-check-square:before{content:"\f14a"}.fa-pencil-square:before{content:"\f14b"}.fa-external-link-square:before{content:"\f14c"}.fa-share-square:before{content:"\f14d"}.fa-compass:before{content:"\f14e"}.fa-toggle-down:before,.fa-caret-square-o-down:before{content:"\f150"}.fa-toggle-up:before,.fa-caret-square-o-up:before{content:"\f151"}.fa-toggle-right:before,.fa-caret-square-o-right:before{content:"\f152"}.fa-euro:before,.fa-eur:before{content:"\f153"}.fa-gbp:before{content:"\f154"}.fa-dollar:before,.fa-usd:before{content:"\f155"}.fa-rupee:before,.fa-inr:before{content:"\f156"}.fa-cny:before,.fa-rmb:before,.fa-yen:before,.fa-jpy:before{content:"\f157"}.fa-ruble:before,.fa-rouble:before,.fa-rub:before{content:"\f158"}.fa-won:before,.fa-krw:before{content:"\f159"}.fa-bitcoin:before,.fa-btc:before{content:"\f15a"}.fa-file:before{content:"\f15b"}.fa-file-text:before{content:"\f15c"}.fa-sort-alpha-asc:before{content:"\f15d"}.fa-sort-alpha-desc:before{content:"\f15e"}.fa-sort-amount-asc:before{content:"\f160"}.fa-sort-amount-desc:before{content:"\f161"}.fa-sort-numeric-asc:before{content:"\f162"}.fa-sort-numeric-desc:before{content:"\f163"}.fa-thumbs-up:before{content:"\f164"}.fa-thumbs-down:before{content:"\f165"}.fa-youtube-square:before{content:"\f166"}.fa-youtube:before{content:"\f167"}.fa-xing:before{content:"\f168"}.fa-xing-square:before{content:"\f169"}.fa-youtube-play:before{content:"\f16a"}.fa-dropbox:before{content:"\f16b"}.fa-stack-overflow:before{content:"\f16c"}.fa-instagram:before{content:"\f16d"}.fa-flickr:before{content:"\f16e"}.fa-adn:before{content:"\f170"}.fa-bitbucket:before{content:"\f171"}.fa-bitbucket-square:before{content:"\f172"}.fa-tumblr:before{content:"\f173"}.fa-tumblr-square:before{content:"\f174"}.fa-long-arrow-down:before{content:"\f175"}.fa-long-arrow-up:before{content:"\f176"}.fa-long-arrow-left:before{content:"\f177"}.fa-long-arrow-right:before{content:"\f178"}.fa-apple:before{content:"\f179"}.fa-windows:before{content:"\f17a"}.fa-android:before{content:"\f17b"}.fa-linux:before{content:"\f17c"}.fa-dribbble:before{content:"\f17d"}.fa-skype:before{content:"\f17e"}.fa-foursquare:before{content:"\f180"}.fa-trello:before{content:"\f181"}.fa-female:before{content:"\f182"}.fa-male:before{content:"\f183"}.fa-gittip:before,.fa-gratipay:before{content:"\f184"}.fa-sun-o:before{content:"\f185"}.fa-moon-o:before{content:"\f186"}.fa-archive:before{content:"\f187"}.fa-bug:before{content:"\f188"}.fa-vk:before{content:"\f189"}.fa-weibo:before{content:"\f18a"}.fa-renren:before{content:"\f18b"}.fa-pagelines:before{content:"\f18c"}.fa-stack-exchange:before{content:"\f18d"}.fa-arrow-circle-o-right:before{content:"\f18e"}.fa-arrow-circle-o-left:before{content:"\f190"}.fa-toggle-left:before,.fa-caret-square-o-left:before{content:"\f191"}.fa-dot-circle-o:before{content:"\f192"}.fa-wheelchair:before{content:"\f193"}.fa-vimeo-square:before{content:"\f194"}.fa-turkish-lira:before,.fa-try:before{content:"\f195"}.fa-plus-square-o:before{content:"\f196"}.fa-space-shuttle:before{content:"\f197"}.fa-slack:before{content:"\f198"}.fa-envelope-square:before{content:"\f199"}.fa-wordpress:before{content:"\f19a"}.fa-openid:before{content:"\f19b"}.fa-institution:before,.fa-bank:before,.fa-university:before{content:"\f19c"}.fa-mortar-board:before,.fa-graduation-cap:before{content:"\f19d"}.fa-yahoo:before{content:"\f19e"}.fa-google:before{content:"\f1a0"}.fa-reddit:before{content:"\f1a1"}.fa-reddit-square:before{content:"\f1a2"}.fa-stumbleupon-circle:before{content:"\f1a3"}.fa-stumbleupon:before{content:"\f1a4"}.fa-delicious:before{content:"\f1a5"}.fa-digg:before{content:"\f1a6"}.fa-pied-piper-pp:before{content:"\f1a7"}.fa-pied-piper-alt:before{content:"\f1a8"}.fa-drupal:before{content:"\f1a9"}.fa-joomla:before{content:"\f1aa"}.fa-language:before{content:"\f1ab"}.fa-fax:before{content:"\f1ac"}.fa-building:before{content:"\f1ad"}.fa-child:before{content:"\f1ae"}.fa-paw:before{content:"\f1b0"}.fa-spoon:before{content:"\f1b1"}.fa-cube:before{content:"\f1b2"}.fa-cubes:before{content:"\f1b3"}.fa-behance:before{content:"\f1b4"}.fa-behance-square:before{content:"\f1b5"}.fa-steam:before{content:"\f1b6"}.fa-steam-square:before{content:"\f1b7"}.fa-recycle:before{content:"\f1b8"}.fa-automobile:before,.fa-car:before{content:"\f1b9"}.fa-cab:before,.fa-taxi:before{content:"\f1ba"}.fa-tree:before{content:"\f1bb"}.fa-spotify:before{content:"\f1bc"}.fa-deviantart:before{content:"\f1bd"}.fa-soundcloud:before{content:"\f1be"}.fa-database:before{content:"\f1c0"}.fa-file-pdf-o:before{content:"\f1c1"}.fa-file-word-o:before{content:"\f1c2"}.fa-file-excel-o:before{content:"\f1c3"}.fa-file-powerpoint-o:before{content:"\f1c4"}.fa-file-photo-o:before,.fa-file-picture-o:before,.fa-file-image-o:before{content:"\f1c5"}.fa-file-zip-o:before,.fa-file-archive-o:before{content:"\f1c6"}.fa-file-sound-o:before,.fa-file-audio-o:before{content:"\f1c7"}.fa-file-movie-o:before,.fa-file-video-o:before{content:"\f1c8"}.fa-file-code-o:before{content:"\f1c9"}.fa-vine:before{content:"\f1ca"}.fa-codepen:before{content:"\f1cb"}.fa-jsfiddle:before{content:"\f1cc"}.fa-life-bouy:before,.fa-life-buoy:before,.fa-life-saver:before,.fa-support:before,.fa-life-ring:before{content:"\f1cd"}.fa-circle-o-notch:before{content:"\f1ce"}.fa-ra:before,.fa-resistance:before,.fa-rebel:before{content:"\f1d0"}.fa-ge:before,.fa-empire:before{content:"\f1d1"}.fa-git-square:before{content:"\f1d2"}.fa-git:before{content:"\f1d3"}.fa-y-combinator-square:before,.fa-yc-square:before,.fa-hacker-news:before{content:"\f1d4"}.fa-tencent-weibo:before{content:"\f1d5"}.fa-qq:before{content:"\f1d6"}.fa-wechat:before,.fa-weixin:before{content:"\f1d7"}.fa-send:before,.fa-paper-plane:before{content:"\f1d8"}.fa-send-o:before,.fa-paper-plane-o:before{content:"\f1d9"}.fa-history:before{content:"\f1da"}.fa-circle-thin:before{content:"\f1db"}.fa-header:before{content:"\f1dc"}.fa-paragraph:before{content:"\f1dd"}.fa-sliders:before{content:"\f1de"}.fa-share-alt:before{content:"\f1e0"}.fa-share-alt-square:before{content:"\f1e1"}.fa-bomb:before{content:"\f1e2"}.fa-soccer-ball-o:before,.fa-futbol-o:before{content:"\f1e3"}.fa-tty:before{content:"\f1e4"}.fa-binoculars:before{content:"\f1e5"}.fa-plug:before{content:"\f1e6"}.fa-slideshare:before{content:"\f1e7"}.fa-twitch:before{content:"\f1e8"}.fa-yelp:before{content:"\f1e9"}.fa-newspaper-o:before{content:"\f1ea"}.fa-wifi:before{content:"\f1eb"}.fa-calculator:before{content:"\f1ec"}.fa-paypal:before{content:"\f1ed"}.fa-google-wallet:before{content:"\f1ee"}.fa-cc-visa:before{content:"\f1f0"}.fa-cc-mastercard:before{content:"\f1f1"}.fa-cc-discover:before{content:"\f1f2"}.fa-cc-amex:before{content:"\f1f3"}.fa-cc-paypal:before{content:"\f1f4"}.fa-cc-stripe:before{content:"\f1f5"}.fa-bell-slash:before{content:"\f1f6"}.fa-bell-slash-o:before{content:"\f1f7"}.fa-trash:before{content:"\f1f8"}.fa-copyright:before{content:"\f1f9"}.fa-at:before{content:"\f1fa"}.fa-eyedropper:before{content:"\f1fb"}.fa-paint-brush:before{content:"\f1fc"}.fa-birthday-cake:before{content:"\f1fd"}.fa-area-chart:before{content:"\f1fe"}.fa-pie-chart:before{content:"\f200"}.fa-line-chart:before{content:"\f201"}.fa-lastfm:before{content:"\f202"}.fa-lastfm-square:before{content:"\f203"}.fa-toggle-off:before{content:"\f204"}.fa-toggle-on:before{content:"\f205"}.fa-bicycle:before{content:"\f206"}.fa-bus:before{content:"\f207"}.fa-ioxhost:before{content:"\f208"}.fa-angellist:before{content:"\f209"}.fa-cc:before{content:"\f20a"}.fa-shekel:before,.fa-sheqel:before,.fa-ils:before{content:"\f20b"}.fa-meanpath:before{content:"\f20c"}.fa-buysellads:before{content:"\f20d"}.fa-connectdevelop:before{content:"\f20e"}.fa-dashcube:before{content:"\f210"}.fa-forumbee:before{content:"\f211"}.fa-leanpub:before{content:"\f212"}.fa-sellsy:before{content:"\f213"}.fa-shirtsinbulk:before{content:"\f214"}.fa-simplybuilt:before{content:"\f215"}.fa-skyatlas:before{content:"\f216"}.fa-cart-plus:before{content:"\f217"}.fa-cart-arrow-down:before{content:"\f218"}.fa-diamond:before{content:"\f219"}.fa-ship:before{content:"\f21a"}.fa-user-secret:before{content:"\f21b"}.fa-motorcycle:before{content:"\f21c"}.fa-street-view:before{content:"\f21d"}.fa-heartbeat:before{content:"\f21e"}.fa-venus:before{content:"\f221"}.fa-mars:before{content:"\f222"}.fa-mercury:before{content:"\f223"}.fa-intersex:before,.fa-transgender:before{content:"\f224"}.fa-transgender-alt:before{content:"\f225"}.fa-venus-double:before{content:"\f226"}.fa-mars-double:before{content:"\f227"}.fa-venus-mars:before{content:"\f228"}.fa-mars-stroke:before{content:"\f229"}.fa-mars-stroke-v:before{content:"\f22a"}.fa-mars-stroke-h:before{content:"\f22b"}.fa-neuter:before{content:"\f22c"}.fa-genderless:before{content:"\f22d"}.fa-facebook-official:before{content:"\f230"}.fa-pinterest-p:before{content:"\f231"}.fa-whatsapp:before{content:"\f232"}.fa-server:before{content:"\f233"}.fa-user-plus:before{content:"\f234"}.fa-user-times:before{content:"\f235"}.fa-hotel:before,.fa-bed:before{content:"\f236"}.fa-viacoin:before{content:"\f237"}.fa-train:before{content:"\f238"}.fa-subway:before{content:"\f239"}.fa-medium:before{content:"\f23a"}.fa-yc:before,.fa-y-combinator:before{content:"\f23b"}.fa-optin-monster:before{content:"\f23c"}.fa-opencart:before{content:"\f23d"}.fa-expeditedssl:before{content:"\f23e"}.fa-battery-4:before,.fa-battery:before,.fa-battery-full:before{content:"\f240"}.fa-battery-3:before,.fa-battery-three-quarters:before{content:"\f241"}.fa-battery-2:before,.fa-battery-half:before{content:"\f242"}.fa-battery-1:before,.fa-battery-quarter:before{content:"\f243"}.fa-battery-0:before,.fa-battery-empty:before{content:"\f244"}.fa-mouse-pointer:before{content:"\f245"}.fa-i-cursor:before{content:"\f246"}.fa-object-group:before{content:"\f247"}.fa-object-ungroup:before{content:"\f248"}.fa-sticky-note:before{content:"\f249"}.fa-sticky-note-o:before{content:"\f24a"}.fa-cc-jcb:before{content:"\f24b"}.fa-cc-diners-club:before{content:"\f24c"}.fa-clone:before{content:"\f24d"}.fa-balance-scale:before{content:"\f24e"}.fa-hourglass-o:before{content:"\f250"}.fa-hourglass-1:before,.fa-hourglass-start:before{content:"\f251"}.fa-hourglass-2:before,.fa-hourglass-half:before{content:"\f252"}.fa-hourglass-3:before,.fa-hourglass-end:before{content:"\f253"}.fa-hourglass:before{content:"\f254"}.fa-hand-grab-o:before,.fa-hand-rock-o:before{content:"\f255"}.fa-hand-stop-o:before,.fa-hand-paper-o:before{content:"\f256"}.fa-hand-scissors-o:before{content:"\f257"}.fa-hand-lizard-o:before{content:"\f258"}.fa-hand-spock-o:before{content:"\f259"}.fa-hand-pointer-o:before{content:"\f25a"}.fa-hand-peace-o:before{content:"\f25b"}.fa-trademark:before{content:"\f25c"}.fa-registered:before{content:"\f25d"}.fa-creative-commons:before{content:"\f25e"}.fa-gg:before{content:"\f260"}.fa-gg-circle:before{content:"\f261"}.fa-tripadvisor:before{content:"\f262"}.fa-odnoklassniki:before{content:"\f263"}.fa-odnoklassniki-square:before{content:"\f264"}.fa-get-pocket:before{content:"\f265"}.fa-wikipedia-w:before{content:"\f266"}.fa-safari:before{content:"\f267"}.fa-chrome:before{content:"\f268"}.fa-firefox:before{content:"\f269"}.fa-opera:before{content:"\f26a"}.fa-internet-explorer:before{content:"\f26b"}.fa-tv:before,.fa-television:before{content:"\f26c"}.fa-contao:before{content:"\f26d"}.fa-500px:before{content:"\f26e"}.fa-amazon:before{content:"\f270"}.fa-calendar-plus-o:before{content:"\f271"}.fa-calendar-minus-o:before{content:"\f272"}.fa-calendar-times-o:before{content:"\f273"}.fa-calendar-check-o:before{content:"\f274"}.fa-industry:before{content:"\f275"}.fa-map-pin:before{content:"\f276"}.fa-map-signs:before{content:"\f277"}.fa-map-o:before{content:"\f278"}.fa-map:before{content:"\f279"}.fa-commenting:before{content:"\f27a"}.fa-commenting-o:before{content:"\f27b"}.fa-houzz:before{content:"\f27c"}.fa-vimeo:before{content:"\f27d"}.fa-black-tie:before{content:"\f27e"}.fa-fonticons:before{content:"\f280"}.fa-reddit-alien:before{content:"\f281"}.fa-edge:before{content:"\f282"}.fa-credit-card-alt:before{content:"\f283"}.fa-codiepie:before{content:"\f284"}.fa-modx:before{content:"\f285"}.fa-fort-awesome:before{content:"\f286"}.fa-usb:before{content:"\f287"}.fa-product-hunt:before{content:"\f288"}.fa-mixcloud:before{content:"\f289"}.fa-scribd:before{content:"\f28a"}.fa-pause-circle:before{content:"\f28b"}.fa-pause-circle-o:before{content:"\f28c"}.fa-stop-circle:before{content:"\f28d"}.fa-stop-circle-o:before{content:"\f28e"}.fa-shopping-bag:before{content:"\f290"}.fa-shopping-basket:before{content:"\f291"}.fa-hashtag:before{content:"\f292"}.fa-bluetooth:before{content:"\f293"}.fa-bluetooth-b:before{content:"\f294"}.fa-percent:before{content:"\f295"}.fa-gitlab:before{content:"\f296"}.fa-wpbeginner:before{content:"\f297"}.fa-wpforms:before{content:"\f298"}.fa-envira:before{content:"\f299"}.fa-universal-access:before{content:"\f29a"}.fa-wheelchair-alt:before{content:"\f29b"}.fa-question-circle-o:before{content:"\f29c"}.fa-blind:before{content:"\f29d"}.fa-audio-description:before{content:"\f29e"}.fa-volume-control-phone:before{content:"\f2a0"}.fa-braille:before{content:"\f2a1"}.fa-assistive-listening-systems:before{content:"\f2a2"}.fa-asl-interpreting:before,.fa-american-sign-language-interpreting:before{content:"\f2a3"}.fa-deafness:before,.fa-hard-of-hearing:before,.fa-deaf:before{content:"\f2a4"}.fa-glide:before{content:"\f2a5"}.fa-glide-g:before{content:"\f2a6"}.fa-signing:before,.fa-sign-language:before{content:"\f2a7"}.fa-low-vision:before{content:"\f2a8"}.fa-viadeo:before{content:"\f2a9"}.fa-viadeo-square:before{content:"\f2aa"}.fa-snapchat:before{content:"\f2ab"}.fa-snapchat-ghost:before{content:"\f2ac"}.fa-snapchat-square:before{content:"\f2ad"}.fa-pied-piper:before{content:"\f2ae"}.fa-first-order:before{content:"\f2b0"}.fa-yoast:before{content:"\f2b1"}.fa-themeisle:before{content:"\f2b2"}.fa-google-plus-circle:before,.fa-google-plus-official:before{content:"\f2b3"}.fa-fa:before,.fa-font-awesome:before{content:"\f2b4"}.fa-handshake-o:before{content:"\f2b5"}.fa-envelope-open:before{content:"\f2b6"}.fa-envelope-open-o:before{content:"\f2b7"}.fa-linode:before{content:"\f2b8"}.fa-address-book:before{content:"\f2b9"}.fa-address-book-o:before{content:"\f2ba"}.fa-vcard:before,.fa-address-card:before{content:"\f2bb"}.fa-vcard-o:before,.fa-address-card-o:before{content:"\f2bc"}.fa-user-circle:before{content:"\f2bd"}.fa-user-circle-o:before{content:"\f2be"}.fa-user-o:before{content:"\f2c0"}.fa-id-badge:before{content:"\f2c1"}.fa-drivers-license:before,.fa-id-card:before{content:"\f2c2"}.fa-drivers-license-o:before,.fa-id-card-o:before{content:"\f2c3"}.fa-quora:before{content:"\f2c4"}.fa-free-code-camp:before{content:"\f2c5"}.fa-telegram:before{content:"\f2c6"}.fa-thermometer-4:before,.fa-thermometer:before,.fa-thermometer-full:before{content:"\f2c7"}.fa-thermometer-3:before,.fa-thermometer-three-quarters:before{content:"\f2c8"}.fa-thermometer-2:before,.fa-thermometer-half:before{content:"\f2c9"}.fa-thermometer-1:before,.fa-thermometer-quarter:before{content:"\f2ca"}.fa-thermometer-0:before,.fa-thermometer-empty:before{content:"\f2cb"}.fa-shower:before{content:"\f2cc"}.fa-bathtub:before,.fa-s15:before,.fa-bath:before{content:"\f2cd"}.fa-podcast:before{content:"\f2ce"}.fa-window-maximize:before{content:"\f2d0"}.fa-window-minimize:before{content:"\f2d1"}.fa-window-restore:before{content:"\f2d2"}.fa-times-rectangle:before,.fa-window-close:before{content:"\f2d3"}.fa-times-rectangle-o:before,.fa-window-close-o:before{content:"\f2d4"}.fa-bandcamp:before{content:"\f2d5"}.fa-grav:before{content:"\f2d6"}.fa-etsy:before{content:"\f2d7"}.fa-imdb:before{content:"\f2d8"}.fa-ravelry:before{content:"\f2d9"}.fa-eercast:before{content:"\f2da"}.fa-microchip:before{content:"\f2db"}.fa-snowflake-o:before{content:"\f2dc"}.fa-superpowers:before{content:"\f2dd"}.fa-wpexplorer:before{content:"\f2de"}.fa-meetup:before{content:"\f2e0"}.sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0, 0, 0, 0);border:0}.sr-only-focusable:active,.sr-only-focusable:focus{position:static;width:auto;height:auto;margin:0;overflow:visible;clip:auto} diff --git a/web/dashboard.html b/web/dashboard.html index 37909407..90bcdadb 100644 --- a/web/dashboard.html +++ b/web/dashboard.html @@ -652,4 +652,4 @@ So, to avoid flashing the charts, we destroy and re-create the charts on each up - + diff --git a/web/dashboard.js b/web/dashboard.js index 4b812e09..c47c5c0c 100644 --- a/web/dashboard.js +++ b/web/dashboard.js @@ -146,8 +146,8 @@ dashboard_css: NETDATA.serverDefault + 'dashboard.slate.css?v20161002-1', background: '#272b30', foreground: '#C8C8C8', - grid: '#35393e', - axis: '#35393e', + grid: '#283236', + axis: '#283236', /* colors: [ '#55bb33', '#ff2222', '#0099C6', '#faa11b', '#adbce0', '#DDDD00', '#4178ba', '#f58122', '#a5cc39', '#f58667', '#f5ef89', '#cf93c0', '#a5d18a', '#b8539d', '#3954a3', '#c8a9cf', '#c7de8a', '#fad20a', @@ -660,6 +660,119 @@ NETDATA.errorLast.datetime = 0; }; + // ---------------------------------------------------------------------------------------------------------------- + // commonMin & commonMax + + NETDATA.commonMin = { + keys: {}, + latest: {}, + + get: function(state) { + if(typeof state.__commonMin === 'undefined') { + // get the commonMin setting + var self = $(state.element); + state.__commonMin = self.data('common-min') || null; + } + + var min = state.data.min; + var name = state.__commonMin; + + if(name === null) { + // we don't need commonMin + //state.log('no need for commonMin'); + return min; + } + + var t = this.keys[name]; + if(typeof t === 'undefined') { + // add our commonMin + this.keys[name] = {}; + t = this.keys[name]; + } + + var uuid = state.uuid; + if(typeof t[uuid] !== 'undefined') { + if(t[uuid] === min) { + //state.log('commonMin ' + state.__commonMin + ' not changed: ' + this.latest[name]); + return this.latest[name]; + } + else if(min < this.latest[name]) { + //state.log('commonMin ' + state.__commonMin + ' increased: ' + min); + t[uuid] = min; + this.latest[name] = min; + return min; + } + } + + // add our min + t[uuid] = min; + + // find the common min + var m = min; + for(var i in t) + if(t[i] < m) m = t[i]; + + //state.log('commonMin ' + state.__commonMin + ' updated: ' + m); + this.latest[name] = m; + return m; + } + }; + + NETDATA.commonMax = { + keys: {}, + latest: {}, + + get: function(state) { + if(typeof state.__commonMax === 'undefined') { + // get the commonMax setting + var self = $(state.element); + state.__commonMax = self.data('common-max') || null; + } + + var max = state.data.max; + var name = state.__commonMax; + + if(name === null) { + // we don't need commonMax + //state.log('no need for commonMax'); + return max; + } + + var t = this.keys[name]; + if(typeof t === 'undefined') { + // add our commonMax + this.keys[name] = {}; + t = this.keys[name]; + } + + var uuid = state.uuid; + if(typeof t[uuid] !== 'undefined') { + if(t[uuid] === max) { + //state.log('commonMax ' + state.__commonMax + ' not changed: ' + this.latest[name]); + return this.latest[name]; + } + else if(max > this.latest[name]) { + //state.log('commonMax ' + state.__commonMax + ' increased: ' + max); + t[uuid] = max; + this.latest[name] = max; + return max; + } + } + + // add our max + t[uuid] = max; + + // find the common max + var m = max; + for(var i in t) + if(t[i] > m) m = t[i]; + + //state.log('commonMax ' + state.__commonMax + ' updated: ' + m); + this.latest[name] = m; + return m; + } + }; + // ---------------------------------------------------------------------------------------------------------------- // Chart Registry @@ -1166,6 +1279,16 @@ this.view_after = 0; this.view_before = 0; + this.value_decimal_detail = -1; + { + var d = self.data('decimal-digits'); + if(typeof d === 'number') { + this.value_decimal_detail = 1; + while(d-- > 0) + this.value_decimal_detail *= 10; + } + } + this.auto = { name: 'auto', autorefresh: true, @@ -2052,6 +2175,9 @@ if(value === null || value === 'undefined') return '-'; if(typeof value !== 'number') return value; + if(this.value_decimal_detail !== -1) + return (Math.round(value * this.value_decimal_detail) / this.value_decimal_detail).toLocaleString(); + var abs = Math.abs(value); if(abs >= 1000) return (Math.round(value)).toLocaleString(); if(abs >= 100 ) return (Math.round(value * 10) / 10).toLocaleString(); @@ -3890,25 +4016,33 @@ state.log('dygraphChartUpdate() forced zoom update'); options.dateWindow = (state.requested_padding !== null)?[ state.view_after, state.view_before ]:null; - options.valueRange = state.dygraph_options.valueRange; options.isZoomedIgnoreProgrammaticZoom = true; state.dygraph_force_zoom = false; } else if(state.current.name !== 'auto') { if(NETDATA.options.debug.dygraph === true || state.debug === true) state.log('dygraphChartUpdate() loose update'); - - options.valueRange = state.dygraph_options.valueRange; } else { if(NETDATA.options.debug.dygraph === true || state.debug === true) state.log('dygraphChartUpdate() strict update'); options.dateWindow = (state.requested_padding !== null)?[ state.view_after, state.view_before ]:null; - options.valueRange = state.dygraph_options.valueRange; options.isZoomedIgnoreProgrammaticZoom = true; } + options.valueRange = state.dygraph_options.valueRange; + + var oldMax = null, oldMin = null; + if(state.__commonMin !== null) { + state.data.min = state.dygraph_instance.axes_[0].extremeRange[0]; + oldMin = options.valueRange[0] = NETDATA.commonMin.get(state); + } + if(state.__commonMax !== null) { + state.data.max = state.dygraph_instance.axes_[0].extremeRange[1]; + oldMax = options.valueRange[1] = NETDATA.commonMax.get(state); + } + if(state.dygraph_smooth_eligible === true) { if((NETDATA.options.current.smooth_plot === true && state.dygraph_options.plotter !== smoothPlotter) || (NETDATA.options.current.smooth_plot === false && state.dygraph_options.plotter === smoothPlotter)) { @@ -3919,6 +4053,23 @@ dygraph.updateOptions(options); + var redraw = false; + if(oldMin !== null && oldMin > state.dygraph_instance.axes_[0].extremeRange[0]) { + state.data.min = state.dygraph_instance.axes_[0].extremeRange[0]; + options.valueRange[0] = NETDATA.commonMin.get(state); + redraw = true; + } + if(oldMax !== null && oldMax < state.dygraph_instance.axes_[0].extremeRange[1]) { + state.data.max = state.dygraph_instance.axes_[0].extremeRange[1]; + options.valueRange[1] = NETDATA.commonMax.get(state); + redraw = true; + } + + if(redraw === true) { + // state.log('forcing redraw to adapt to common- min/max'); + dygraph.updateOptions(options); + } + state.dygraph_last_rendered = new Date().getTime(); return true; }; @@ -3953,7 +4104,7 @@ title: self.data('dygraph-title') || state.title, titleHeight: self.data('dygraph-titleheight') || 19, - legend: self.data('dygraph-legend') || 'always', // 'onmouseover', + legend: self.data('dygraph-legend') || 'always', // we need this to get selection events labels: data.result.labels, labelsDiv: self.data('dygraph-labelsdiv') || state.element_legend_childs.hidden, labelsDivStyles: self.data('dygraph-labelsdivstyles') || { 'fontSize':'1px' }, @@ -3969,7 +4120,7 @@ xRangePad: self.data('dygraph-xrangepad') || 0, yRangePad: self.data('dygraph-yrangepad') || 1, - valueRange: self.data('dygraph-valuerange') || null, + valueRange: self.data('dygraph-valuerange') || [ null, null ], ylabel: state.units, yLabelWidth: self.data('dygraph-ylabelwidth') || 12, @@ -4006,11 +4157,11 @@ drawAxis: self.data('dygraph-drawaxis') || true, axisLabelFontSize: self.data('dygraph-axislabelfontsize') || 10, axisLineColor: self.data('dygraph-axislinecolor') || NETDATA.themes.current.axis, - axisLineWidth: self.data('dygraph-axislinewidth') || 0.3, + axisLineWidth: self.data('dygraph-axislinewidth') || 1.0, drawGrid: self.data('dygraph-drawgrid') || true, gridLinePattern: self.data('dygraph-gridlinepattern') || null, - gridLineWidth: self.data('dygraph-gridlinewidth') || 0.4, + gridLineWidth: self.data('dygraph-gridlinewidth') || 1.0, gridLineColor: self.data('dygraph-gridlinecolor') || NETDATA.themes.current.grid, maxNumberWidth: self.data('dygraph-maxnumberwidth') || 8, @@ -4171,6 +4322,7 @@ state.globalSelectionSyncStop(); state.globalSelectionSyncDelay(); state.setMode('pan'); + context.is2DPan = false; Dygraph.movePan(event, dygraph, context); } else if(context.isZooming) { @@ -4283,7 +4435,7 @@ normal_def = event.wheelDelta / 40; else // firefox - normal_def = event.deltaY * -2; + normal_def = event.deltaY * -1.2; var normal = (event.detail) ? event.detail * -1 : normal_def; var percentage = normal / 50; @@ -4409,6 +4561,17 @@ state.dygraph_force_zoom = false; state.dygraph_user_action = false; state.dygraph_last_rendered = new Date().getTime(); + + if(typeof state.dygraph_instance.axes_[0].extremeRange !== 'undefined') { + state.__commonMin = self.data('common-min') || null; + state.__commonMax = self.data('common-max') || null; + } + else { + state.log('incompatible version of dygraphs detected'); + state.__commonMin = null; + state.__commonMax = null; + } + return true; }; @@ -4909,7 +5072,7 @@ } var value = state.data.result[state.data.result.length - 1 - slot]; - var max = (state.easyPieChartMax === null)?state.data.max:state.easyPieChartMax; + var max = (state.easyPieChartMax === null)?NETDATA.commonMax.get(state):state.easyPieChartMax; var pcent = NETDATA.percentFromValueMax(value, max); state.easyPieChartEvent.value = value; @@ -4938,7 +5101,7 @@ } else { value = data.result[0]; - max = (state.easyPieChartMax === null)?data.max:state.easyPieChartMax; + max = (state.easyPieChartMax === null)?NETDATA.commonMax.get(state):state.easyPieChartMax; pcent = NETDATA.percentFromValueMax(value, max); } @@ -4956,7 +5119,7 @@ var adjust = self.data('easypiechart-adjust') || null; if(max === null) { - max = data.max; + max = NETDATA.commonMax.get(state); state.easyPieChartMax = null; } else @@ -5178,7 +5341,7 @@ } var value = state.data.result[state.data.result.length - 1 - slot]; - var max = (state.gaugeMax === null)?state.data.max:state.gaugeMax; + var max = (state.gaugeMax === null)?NETDATA.commonMax.get(state):state.gaugeMax; var min = 0; state.gaugeEvent.value = value; @@ -5210,7 +5373,7 @@ else { value = data.result[0]; min = 0; - max = (state.gaugeMax === null)?data.max:state.gaugeMax; + max = (state.gaugeMax === null)?NETDATA.commonMax.get(state):state.gaugeMax; if(value > max) max = value; NETDATA.gaugeSetLabels(state, value, min, max); } @@ -5233,7 +5396,7 @@ var generateGradient = self.data('gauge-generate-gradient') || false; if(max === null) { - max = data.max; + max = NETDATA.commonMax.get(state); state.gaugeMax = null; } else @@ -5631,7 +5794,7 @@ } }, { - url: NETDATA.serverDefault + 'css/font-awesome.min.css?v4.6.3', + url: NETDATA.serverDefault + 'css/font-awesome.min.css?v4.7.0', isAlreadyLoaded: function() { return false; } }, { diff --git a/web/dashboard_info.js b/web/dashboard_info.js index 49459322..180055ab 100644 --- a/web/dashboard_info.js +++ b/web/dashboard_info.js @@ -1,744 +1,789 @@ - -var netdataDashboard = window.netdataDashboard || {}; - -// menu -// information about the main menus - -netdataDashboard.menu = { - 'system': { - title: 'System Overview', - icon: '', - info: 'Overview of the key system metrics.' - }, - - 'ap': { - title: 'Access Points', - icon: '', - info: undefined - }, - - 'tc': { - title: 'Quality of Service', - icon: '', - info: 'Netdata collects and visualizes tc class utilization using its tc-helper plugin. If you also use FireQOS for setting up QoS, netdata automatically collects interface and class names. If your QoS configuration includes overheads calculation, the values shown here will include these overheads (the total bandwidth for the same interface as reported in the Network Interfaces section, will be lower than the total bandwidth reported here). Also, data collection may have a slight time difference compared to the interface (QoS data collection is implemented with a BASH script, so a shift in data collection of a few milliseconds should be justified).' - }, - - 'net': { - title: 'Network Interfaces', - icon: '', - info: 'Per network interface statistics collected from /proc/net/dev.' - }, - - 'ipv4': { - title: 'IPv4 Networking', - icon: '', - info: undefined - }, - - 'ipv6': { - title: 'IPv6 Networking', - icon: '', - info: undefined - }, - - 'ipvs': { - title: 'IP Virtual Server', - icon: '', - info: undefined - }, - - 'netfilter': { - title: 'Firewall (netfilter)', - icon: '', - info: undefined - }, - - 'cpu': { - title: 'CPUs', - icon: '', - info: undefined - }, - - 'mem': { - title: 'Memory', - icon: '', - info: undefined - }, - - 'disk': { - title: 'Disks', - icon: '', - info: 'Charts with performance information for all the system disks. Special care has been given to present disk performance metrics in a way compatible with iostat -x. netdata by default prevents rendering performance charts for individual partitions and unmounted virtual disks. Disabled charts can still be enabled by altering the relative settings in the netdata configuration file.' - }, - - 'sensors': { - title: 'Sensors', - icon: '', - info: undefined - }, - - 'nfsd': { - title: 'NFS Server', - icon: '', - info: undefined - }, - - 'nfs': { - title: 'NFS Client', - icon: '', - info: undefined - }, - - 'apps': { - title: 'Applications', - icon: '', - info: 'Per application statistics are collected using netdata\'s apps.plugin. This plugin walks through the entire /proc filesystem and aggregates statistics for applications of interest, defined in /etc/netdata/apps_groups.conf (the default is here). The plugin internally builds a process tree (much like ps fax does), and groups processes together (evaluating both child and parent processes) so that the result is always a chart with a predefined set of dimensions (of course, only application groups found running are reported). The reported values are compatible with top, although the netdata plugin counts also the resources of exited children (unlike top which shows only the resources of the currently running processes). So for processes like shell scripts, the reported values include the resources used by the commands these scripts run within each timeframe.', - height: 1.5 - }, - - 'users': { - title: 'Users', - icon: '', - info: 'Per user statistics are collected using netdata\'s apps.plugin. This plugin walks through the entire /proc filesystem and aggregates statistics per user. The reported values are compatible with top, although the netdata plugin counts also the resources of exited children (unlike top which shows only the resources of the currently running processes). So for processes like shell scripts, the reported values include the resources used by the commands these scripts run within each timeframe.', - height: 1.5 - }, - - 'groups': { - title: 'User Groups', - icon: '', - info: 'Per user group statistics are collected using netdata\'s apps.plugin. This plugin walks through the entire /proc filesystem and aggregates statistics per user group. The reported values are compatible with top, although the netdata plugin counts also the resources of exited children (unlike top which shows only the resources of the currently running processes). So for processes like shell scripts, the reported values include the resources used by the commands these scripts run within each timeframe.', - height: 1.5 - }, - - 'netdata': { - title: 'Netdata Monitoring', - icon: '', - info: undefined - }, - - 'example': { - title: 'Example Charts', - info: undefined - }, - - 'cgroup': { - title: '', - icon: '', - info: undefined - }, - - 'cgqemu': { - title: '', - icon: '', - info: undefined - }, - - 'memcached': { - title: 'memcached', - icon: '', - info: undefined - }, - - 'mysql': { - title: 'MySQL', - icon: '', - info: undefined - }, - - 'redis': { - title: 'Redis', - icon: '', - info: undefined - }, - - 'retroshare': { - title: 'RetroShare', - icon: '', - info: undefined - }, - - 'ipfs': { - title: 'IPFS', - icon: '', - info: undefined - }, - - 'phpfpm': { - title: 'PHP-FPM', - icon: '', - info: undefined, - }, - - 'postfix': { - title: 'postfix', - icon: '', - info: undefined, - }, - - 'nginx': { - title: 'nginx', - icon: '', - info: undefined, - }, - - 'apache': { - title: 'Apache', - icon: '', - info: undefined, - }, - - 'named': { - title: 'named', - icon: '', - info: undefined - }, - - 'squid': { - title: 'squid', - icon: '', - info: undefined - }, - - 'nut': { - title: 'UPS', - icon: '', - info: undefined - }, - - 'apcupsd': { - title: 'UPS', - icon: '', - info: undefined - }, - - 'smawebbox': { - title: 'Solar Power', - icon: '', - info: undefined - }, - - 'snmp': { - title: 'SNMP', - icon: '', - info: undefined - } -}; - -// submenu -// information about the submenus -netdataDashboard.submenu = { - 'mem.ksm': { - title: 'Memory Deduper', - info: 'Kernel Same-page Merging (KSM) performance monitoring, read from several files in /sys/kernel/mm/ksm/. KSM is a memory-saving de-duplication feature in the Linux kernel (since version 2.6.32). The KSM daemon ksmd periodically scans those areas of user memory which have been registered with it, looking for pages of identical content which can be replaced by a single write-protected page (which is automatically copied if a process later wants to update its content). KSM was originally developed for use with KVM (where it was known as Kernel Shared Memory), to fit more virtual machines into physical memory, by sharing the data common between them. But it can be useful to any application which generates many instances of the same data.' - }, - - 'ipv4.ecn': { - info: 'Explicit Congestion Notification (ECN) is a TCP extension that allows end-to-end notification of network congestion without dropping packets. ECN is an optional feature that may be used between two ECN-enabled endpoints when the underlying network infrastructure also supports it.' - }, - - 'netfilter.conntrack': { - title: 'Connection Tracker', - info: 'Netfilter Connection Tracker performance monitoring, read from /proc/net/stat/nf_conntrack. The connection tracker keeps track of all connections of the machine, inbound and outbound. It works by keeping a database with all open connections, tracking network and address translation and connection expectations.' - }, - - 'netfilter.nfacct': { - title: 'Bandwidth Accounting', - info: 'The following information is read using the nfacct.plugin.' - }, - - 'netfilter.synproxy': { - title: 'DDoS Protection', - info: 'DDoS Protection performance monitoring read from /proc/net/stat/synproxy. SYNPROXY is a TCP SYN packets proxy. It is used to protect any TCP server (like a web server) from SYN floods and similar DDoS attacks. It is a netfilter module, in the Linux kernel (since version 3.12). It is optimized to handle millions of packets per second utilizing all CPUs available without any concurrency locking between the connections. It can be used for any kind of TCP traffic (even encrypted), since it does not interfere with the content itself.' - }, - - 'system.softnet_stat': { - title: 'softnet', - info: 'Statistics for CPUs SoftIRQs related to network receive work, read from /proc/net/softnet_stat. Break down per CPU core can be found at CPU / softnet statistics. processed states the number of packets processed, dropped is the number packets dropped because the network device backlog was full (to fix them use sysctl to increase net.core.netdev_max_backlog), squeezed is the number of packets dropped because the network device budget ran out (to fix them use sysctl to increase net.core.netdev_budget). More information about identifying and troubleshooting network driver related issues can be found at Red Hat Enterprise Linux Network Performance Tuning Guide.' - }, - - 'cpu.softnet_stat': { - title: 'softnet', - info: 'Statistics for per CPUs core SoftIRQs related to network receive work, read from /proc/net/softnet_stat. Total for all CPU cores can be found at System / softnet statistics. processed states the number of packets processed, dropped is the number packets dropped because the network device backlog was full (to fix them use sysctl to increase net.core.netdev_max_backlog), squeezed is the number of packets dropped because the network device budget ran out (to fix them use sysctl to increase net.core.netdev_budget). More information about identifying and troubleshooting network driver related issues can be found at Red Hat Enterprise Linux Network Performance Tuning Guide.' - } -}; - -// chart -// information works on the context of a chart -// Its purpose is to set: -// -// info: the text above the charts -// heads: the representation of the chart at the top the subsection (second level menu) -// mainheads: the representation of the chart at the top of the section (first level menu) -// colors: the dimension colors of the chart (the default colors are appended) -// height: the ratio of the chart height relative to the default -// -netdataDashboard.context = { - 'system.cpu': { - info: 'Total CPU utilization (all cores). 100% here means there is no CPU idle time at all. You can get per core usage at the CPUs section and per application usage at the Applications Monitoring section.
Keep an eye on iowait ' + sparkline('system.cpu', 'iowait', '%') + '. If it is constantly high, your disks are a bottleneck and they slow your system down.
Another important metric worth monitoring, is softirq ' + sparkline('system.cpu', 'softirq', '%') + '. A constantly high percentage of softirq may indicate network drivers issues.' - }, - - 'system.load': { - info: 'Current system load, i.e. the number of processes using CPU or waiting for system resources (usually CPU and disk). The 3 metrics refer to 1, 5 and 15 minute averages. Linux calculates this once every 5 seconds. Netdata reads them from /proc/loadavg. For more information check this wikipedia article', - height: 0.7 - }, - - 'system.io': { - info: 'Total Disk I/O, for all disks, read from /proc/vmstat. You can get detailed information about each disk at the Disks section and per application Disk usage at the Applications Monitoring section.' - }, - - 'system.swapio': { - info: 'Total Swap I/O, read from /proc/vmstat. (netdata measures both in and out. If either of them is not shown in the chart, it is because it is zero - you can change the page settings to always render all the available dimensions on all charts).' - }, - - 'system.pgfaults': { - info: 'Total page faults, read from /proc/vmstat. Major page faults indicates that the system is using its swap. You can find which applications use the swap at the Applications Monitoring section.' - }, - - 'system.entropy': { - colors: '#CC22AA', - info: 'Entropy, read from /proc/sys/kernel/random/entropy_avail, is like a pool of random numbers (/dev/random) that are mainly used in cryptography. It is advised that the pool remains always above 200. If the pool of entropy gets empty, you risk your security to be predictable and you should install a user-space random numbers generating daemon, like haveged or rng-tools (i.e. rngd), to keep the pool in healthy levels.' - }, - - 'system.forks': { - colors: '#5555DD', - info: 'The number of new processes created per second, read from /proc/stat.' - }, - - 'system.intr': { - colors: '#DD5555', - info: 'Total number of CPU interrupts, read from /proc/stat. Check system.interrupts that gives more detail about each interrupt and also the CPUs section where interrupts are analyzed per CPU core.' - }, - - 'system.interrupts': { - info: 'CPU interrupts in detail, read from /proc/interrupts. At the CPUs section, interrupts are analyzed per CPU core.' - }, - - 'system.softirqs': { - info: 'CPU softirqs in detail, read from /proc/softirqs. At the CPUs section, softirqs are analyzed per CPU core.' - }, - - 'system.processes': { - info: 'System processes, read from /proc/stat. Running are the processes in the CPU. Blocked are processes that are willing to enter the CPU, but they cannot, e.g. because they wait for disk activity.' - }, - - 'system.active_processes': { - info: 'All system processes, read from /proc/loadavg.' - }, - - 'system.ctxt': { - info: 'Context Switches, read from /proc/stat, is the switching of the CPU from one process, task or thread to another. If there are many processes or threads willing to execute and very few CPU cores available to handle them, the system is making more context switching to balance the CPU resources among them. The whole process is computationally intensive. The more the context switches, the slower the system gets.' - }, - - 'system.idlejitter': { - colors: '#5555AA', - info: 'Idle jitter is calculated by netdata. A thread is spawned that requests to sleep for a few microseconds. When the system wakes it up, it measures how many microseconds have passed. The difference between the requested and the actual duration of the sleep, is the idle jitter. This number is useful in real-time environments, where CPU jitter can affect the quality of the service (like VoIP media gateways).' - }, - - 'system.ipv4': { - info: 'Total IPv4 Traffic, read from /proc/net/netstat.' - }, - - 'system.ipv6': { - info: 'Total IPv6 Traffic, read from /proc/net/snmp6.' - }, - - 'system.ram': { - info: 'System memory, read from /proc/meminfo.' - }, - - 'system.swap': { - info: 'System swap memory, read from /proc/meminfo.' - }, - - // ------------------------------------------------------------------------ - // MEMORY - - 'mem.ksm_savings': { - heads: [ - netdataDashboard.gaugeChart('Saved', '12%', 'savings', '#0099CC') - ] - }, - - 'mem.ksm_ratios': { - heads: [ - function(id) { - return '
'; - } - ] - }, - - 'mem.committed': { - colors: NETDATA.colors[3] - }, - - // ------------------------------------------------------------------------ - // network interfaces - - 'net.drops': { - info: 'Packets that have been dropped at the network interface level. These are the same counters reported by ifconfig as RX dropped (inbound) and TX dropped (outbound). inbound packets can be dropped at the network interface level due to softnet backlog overflow, bad / unintented VLAN tags, unknown or unregistered protocols, IPv6 frames when the server is not configured for IPv6. Check this document for more information.' - }, - - // ------------------------------------------------------------------------ - // IPv4 - - 'ipv4.tcpmemorypressures': { - info: 'Number of times a socket was put in memory pressure due to a non fatal memory allocation failure (the kernel attempts to work around this situation by reducing the send buffers, etc).' - }, - - 'ipv4.tcpconnaborts': { - info: 'TCP connection aborts. baddata (TCPAbortOnData) happens while the connection is on FIN_WAIT1 and the kernel receives a packet with a sequence number beyond the last one for this connection - the kernel responds with RST (closes the connection). userclosed (TCPAbortOnClose) happens when the kernel receives data on an already closed connection and responds with RST. nomemory (TCPAbortOnMemory happens when there are too many orphaned sockets (not attached to an fd) and the kernel has to drop a connection - sometimes it will send an RST, sometimes it won\'t. timeout (TCPAbortOnTimeout) happens when a connection times out. linger (TCPAbortOnLinger) happens when the kernel killed a socket that was already closed by the application and lingered around for long enough. failed (TCPAbortFailed) happens when the kernel attempted to send an RST but failed because there was no memory available.' - }, - - // ------------------------------------------------------------------------ - // APPS - - 'apps.cpu': { - height: 2.0 - }, - - 'apps.mem': { - info: 'Real memory (RAM) used by applications. This does not include shared memory.' - }, - - 'apps.vmem': { - info: 'Virtual memory allocated by applications. Please check this article for more information.' - }, - - 'apps.preads': { - height: 2.0 - }, - - 'apps.pwrites': { - height: 2.0 - }, - - // ------------------------------------------------------------------------ - // USERS - - 'users.cpu': { - height: 2.0 - }, - - 'users.mem': { - info: 'Real memory (RAM) used per user. This does not include shared memory.' - }, - - 'users.vmem': { - info: 'Virtual memory allocated per user. Please check this article for more information.' - }, - - 'users.preads': { - height: 2.0 - }, - - 'users.pwrites': { - height: 2.0 - }, - - // ------------------------------------------------------------------------ - // GROUPS - - 'groups.cpu': { - height: 2.0 - }, - - 'groups.mem': { - info: 'Real memory (RAM) used per user group. This does not include shared memory.' - }, - - 'groups.vmem': { - info: 'Virtual memory allocated per user group. Please check this article for more information.' - }, - - 'groups.preads': { - height: 2.0 - }, - - 'groups.pwrites': { - height: 2.0 - }, - - // ------------------------------------------------------------------------ - // NETWORK QoS - - 'tc.qos': { - heads: [ - function(id) { - if(id.match(/.*-ifb$/)) - return netdataDashboard.gaugeChart('Inbound', '12%', '', '#5555AA'); - else - return netdataDashboard.gaugeChart('Outbound', '12%', '', '#AA9900'); - } - ] - }, - - // ------------------------------------------------------------------------ - // NETWORK INTERFACES - - 'net.net': { - heads: [ - netdataDashboard.gaugeChart('Received', '12%', 'received'), - netdataDashboard.gaugeChart('Sent', '12%', 'sent') - ] - }, - - // ------------------------------------------------------------------------ - // NETFILTER - - 'netfilter.sockets': { - colors: '#88AA00', - heads: [ - netdataDashboard.gaugeChart('Active Connections', '12%', '', '#88AA00') - ] - }, - - 'netfilter.new': { - heads: [ - netdataDashboard.gaugeChart('New Connections', '12%', 'new', '#5555AA') - ] - }, - - // ------------------------------------------------------------------------ - // DISKS - - 'disk.util': { - colors: '#FF5588', - heads: [ - netdataDashboard.gaugeChart('Utilization', '12%', '', '#FF5588') - ], - info: 'Disk Utilization measures the amount of time the disk was busy with something. This is not related to its performance. 100% means that the Linux kernel always had an outstanding operation on the disk. Keep in mind that depending on the underlying technology of the disk, 100% here may or may not be an indication of congestion.' - }, - - 'disk.backlog': { - colors: '#0099CC', - info: 'Backlog is an indication of the duration of pending disk operations. On every I/O event the Linux kernel is multiplying the time spent doing I/O since the last update of this field with the number of pending operations. While not accurate, this metric can provide an indication of the expected completion time of the operations in progress.' - }, - - 'disk.io': { - heads: [ - netdataDashboard.gaugeChart('Read', '12%', 'reads'), - netdataDashboard.gaugeChart('Write', '12%', 'writes') - ], - info: 'Amount of data transferred to and from disk.' - }, - - 'disk.ops': { - info: 'Completed disk I/O operations. Keep in mind the number of operations requested might be higher, since the Linux kernel is able to merge adjacent to each other (see merged operations chart).' - }, - - 'disk.qops': { - info: 'I/O operations currently in progress. This metric is a snapshot - it is not an average over the last interval.' - }, - - 'disk.iotime': { - height: 0.5, - info: 'The sum of the duration of all completed I/O operations. This number can exceed the interval if the disk is able to execute I/O operations in parallel.' - }, - 'disk.mops': { - height: 0.5, - info: 'The number of merged disk operations. The Linux kernel is able to merge adjacent I/O operations, for example two 4KB reads can become one 8KB read before given to disk.' - }, - 'disk.svctm': { - height: 0.5, - info: 'The average service time for completed I/O operations. This metric is calculated using the total busy time of the disk and the number of completed operations. If the disk is able to execute multiple parallel operations the reporting average service time will be misleading.' - }, - 'disk.avgsz': { - height: 0.5, - info: 'The average I/O operation size.' - }, - 'disk.await': { - height: 0.5, - info: 'The average time for I/O requests issued to the device to be served. This includes the time spent by the requests in queue and the time spent servicing them.' - }, - - 'disk.space': { - info: 'Disk space utilization. reserved for root is automatically reserved by the system to prevent the root user from getting out of space.' - }, - 'disk.inodes': { - info: 'inodes (or index nodes) are filesystem objects (e.g. files and directories). On many types of file system implementations, the maximum number of inodes is fixed at filesystem creation, limiting the maximum number of files the filesystem can hold. It is possible for a device to run out of inodes. When this happens, new files cannot be created on the device, even though there may be free space available.' - }, - - 'mysql.net': { - info: 'The amount of data sent to mysql clients (out) and received from mysql clients (in).' - }, - - // ------------------------------------------------------------------------ - // MYSQL - - 'mysql.queries': { - info: 'The number of statements executed by the server.
    ' + - '
  • queries counts the statements executed within stored SQL programs.
  • ' + - '
  • questions counts the statements sent to the mysql server by mysql clients.
  • ' + - '
  • slow queries counts the number of statements that took more than long_query_time seconds to be executed.' + - ' For more information about slow queries check the mysql slow query log.
  • ' + - '
' - }, - - 'mysql.handlers': { - info: 'Usage of the internal handlers of mysql. This chart provides very good insights of what the mysql server is actually doing.' + - ' (if the chart is not showing all these dimensions it is because they are zero - set Which dimensions to show? to All from the dashboard settings, to render even the zero values)
    ' + - '
  • commit, the number of internal COMMIT statements.
  • ' + - '
  • delete, the number of times that rows have been deleted from tables.
  • ' + - '
  • prepare, a counter for the prepare phase of two-phase commit operations.
  • ' + - '
  • read first, the number of times the first entry in an index was read. A high value suggests that the server is doing a lot of full index scans; e.g. SELECT col1 FROM foo, with col1 indexed.
  • ' + - '
  • read key, the number of requests to read a row based on a key. If this value is high, it is a good indication that your tables are properly indexed for your queries.
  • ' + - '
  • read next, the number of requests to read the next row in key order. This value is incremented if you are querying an index column with a range constraint or if you are doing an index scan.
  • ' + - '
  • read prev, the number of requests to read the previous row in key order. This read method is mainly used to optimize ORDER BY ... DESC.
  • ' + - '
  • read rnd, the number of requests to read a row based on a fixed position. A high value indicates you are doing a lot of queries that require sorting of the result. You probably have a lot of queries that require MySQL to scan entire tables or you have joins that do not use keys properly.
  • ' + - '
  • read rnd next, the number of requests to read the next row in the data file. This value is high if you are doing a lot of table scans. Generally this suggests that your tables are not properly indexed or that your queries are not written to take advantage of the indexes you have.
  • ' + - '
  • rollback, the number of requests for a storage engine to perform a rollback operation.
  • ' + - '
  • savepoint, the number of requests for a storage engine to place a savepoint.
  • ' + - '
  • savepoint rollback, the number of requests for a storage engine to roll back to a savepoint.
  • ' + - '
  • update, the number of requests to update a row in a table.
  • ' + - '
  • write, the number of requests to insert a row in a table.
  • ' + - '
' - }, - - 'mysql.table_locks': { - info: 'MySQL table locks counters:
    ' + - '
  • immediate, the number of times that a request for a table lock could be granted immediately.
  • ' + - '
  • waited, the number of times that a request for a table lock could not be granted immediately and a wait was needed. If this is high and you have performance problems, you should first optimize your queries, and then either split your table or tables or use replication.
  • ' + - '
' - }, - - // ------------------------------------------------------------------------ - // APACHE - - 'apache.connections': { - colors: NETDATA.colors[4], - mainheads: [ - netdataDashboard.gaugeChart('Connections', '12%', '', NETDATA.colors[4]) - ] - }, - - 'apache.requests': { - colors: NETDATA.colors[0], - mainheads: [ - netdataDashboard.gaugeChart('Requests', '12%', '', NETDATA.colors[0]) - ] - }, - - 'apache.net': { - colors: NETDATA.colors[3], - mainheads: [ - netdataDashboard.gaugeChart('Bandwidth', '12%', '', NETDATA.colors[3]) - ] - }, - - 'apache.workers': { - mainheads: [ - function(id) { - return '
'; - } - ] - }, - - 'apache.bytesperreq': { - colors: NETDATA.colors[3], - height: 0.5 - }, - - 'apache.reqpersec': { - colors: NETDATA.colors[4], - height: 0.5 - }, - - 'apache.bytespersec': { - colors: NETDATA.colors[6], - height: 0.5 - }, - - - // ------------------------------------------------------------------------ - // NGINX - - 'nginx.connections': { - colors: NETDATA.colors[4], - mainheads: [ - netdataDashboard.gaugeChart('Connections', '12%', '', NETDATA.colors[4]) - ] - }, - - 'nginx.requests': { - colors: NETDATA.colors[0], - mainheads: [ - netdataDashboard.gaugeChart('Requests', '12%', '', NETDATA.colors[0]) - ] - }, - - // ------------------------------------------------------------------------ - // NETDATA - - 'netdata.response_time': { - info: 'The netdata API response time measures the time netdata needed to serve requests. This time includes everything, from the reception of the first byte of a request, to the dispatch of the last byte of its reply, therefore it includes all network latencies involved (i.e. a client over a slow network will influence these metrics).' - }, - - // ------------------------------------------------------------------------ - // RETROSHARE - - 'retroshare.bandwidth': { - info: 'RetroShare inbound and outbound traffic.', - mainheads: [ - netdataDashboard.gaugeChart('Received', '12%', 'bandwidth_down_kb'), - netdataDashboard.gaugeChart('Sent', '12%', 'bandwidth_up_kb') - ] - }, - - 'retroshare.peers': { - info: 'Number of (connected) RetroShare friends.', - mainheads: [ - function(id) { - return '
'; - } - ] - }, - - 'retroshare.dht': { - info: 'Statistics about RetroShare\'s DHT. These values are estimated!' - }, - - // ------------------------------------------------------------------------ - // fping - - 'fping.loss': { - colors: NETDATA.colors[1], - height: 0.5 - }, - - 'fping.packets': { - height: 0.5 - } - -}; + +var netdataDashboard = window.netdataDashboard || {}; + +// menu +// information about the main menus + +netdataDashboard.menu = { + 'system': { + title: 'System Overview', + icon: '', + info: 'Overview of the key system metrics.' + }, + + 'ap': { + title: 'Access Points', + icon: '', + info: undefined + }, + + 'tc': { + title: 'Quality of Service', + icon: '', + info: 'Netdata collects and visualizes tc class utilization using its tc-helper plugin. If you also use FireQOS for setting up QoS, netdata automatically collects interface and class names. If your QoS configuration includes overheads calculation, the values shown here will include these overheads (the total bandwidth for the same interface as reported in the Network Interfaces section, will be lower than the total bandwidth reported here). Also, data collection may have a slight time difference compared to the interface (QoS data collection is implemented with a BASH script, so a shift in data collection of a few milliseconds should be justified).' + }, + + 'net': { + title: 'Network Interfaces', + icon: '', + info: 'Per network interface statistics collected from /proc/net/dev.' + }, + + 'ipv4': { + title: 'IPv4 Networking', + icon: '', + info: undefined + }, + + 'ipv6': { + title: 'IPv6 Networking', + icon: '', + info: undefined + }, + + 'ipvs': { + title: 'IP Virtual Server', + icon: '', + info: undefined + }, + + 'netfilter': { + title: 'Firewall (netfilter)', + icon: '', + info: undefined + }, + + 'cpu': { + title: 'CPUs', + icon: '', + info: undefined + }, + + 'mem': { + title: 'Memory', + icon: '', + info: undefined + }, + + 'disk': { + title: 'Disks', + icon: '', + info: 'Charts with performance information for all the system disks. Special care has been given to present disk performance metrics in a way compatible with iostat -x. netdata by default prevents rendering performance charts for individual partitions and unmounted virtual disks. Disabled charts can still be enabled by altering the relative settings in the netdata configuration file.' + }, + + 'sensors': { + title: 'Sensors', + icon: '', + info: undefined + }, + + 'nfsd': { + title: 'NFS Server', + icon: '', + info: undefined + }, + + 'nfs': { + title: 'NFS Client', + icon: '', + info: undefined + }, + + 'apps': { + title: 'Applications', + icon: '', + info: 'Per application statistics are collected using netdata\'s apps.plugin. This plugin walks through the entire /proc filesystem and aggregates statistics for applications of interest, defined in /etc/netdata/apps_groups.conf (the default is here). The plugin internally builds a process tree (much like ps fax does), and groups processes together (evaluating both child and parent processes) so that the result is always a chart with a predefined set of dimensions (of course, only application groups found running are reported). The reported values are compatible with top, although the netdata plugin counts also the resources of exited children (unlike top which shows only the resources of the currently running processes). So for processes like shell scripts, the reported values include the resources used by the commands these scripts run within each timeframe.', + height: 1.5 + }, + + 'users': { + title: 'Users', + icon: '', + info: 'Per user statistics are collected using netdata\'s apps.plugin. This plugin walks through the entire /proc filesystem and aggregates statistics per user. The reported values are compatible with top, although the netdata plugin counts also the resources of exited children (unlike top which shows only the resources of the currently running processes). So for processes like shell scripts, the reported values include the resources used by the commands these scripts run within each timeframe.', + height: 1.5 + }, + + 'groups': { + title: 'User Groups', + icon: '', + info: 'Per user group statistics are collected using netdata\'s apps.plugin. This plugin walks through the entire /proc filesystem and aggregates statistics per user group. The reported values are compatible with top, although the netdata plugin counts also the resources of exited children (unlike top which shows only the resources of the currently running processes). So for processes like shell scripts, the reported values include the resources used by the commands these scripts run within each timeframe.', + height: 1.5 + }, + + 'netdata': { + title: 'Netdata Monitoring', + icon: '', + info: undefined + }, + + 'example': { + title: 'Example Charts', + info: undefined + }, + + 'cgroup': { + title: '', + icon: '', + info: undefined + }, + + 'cgqemu': { + title: '', + icon: '', + info: undefined + }, + + 'fping': { + title: 'fping', + icon: '', + info: undefined + }, + + 'memcached': { + title: 'memcached', + icon: '', + info: undefined + }, + + 'mysql': { + title: 'MySQL', + icon: '', + info: undefined + }, + + 'postgres': { + title: 'Postgres', + icon: '', + info: undefined + }, + + 'redis': { + title: 'Redis', + icon: '', + info: undefined + }, + + 'retroshare': { + title: 'RetroShare', + icon: '', + info: undefined + }, + + 'ipfs': { + title: 'IPFS', + icon: '', + info: undefined + }, + + 'phpfpm': { + title: 'PHP-FPM', + icon: '', + info: undefined + }, + + 'postfix': { + title: 'postfix', + icon: '', + info: undefined + }, + + 'dovecot': { + title: 'Dovecot', + icon: '', + info: undefined + }, + + 'hddtemp': { + title: 'HDD Temp', + icon: '', + info: undefined + }, + + 'nginx': { + title: 'nginx', + icon: '', + info: undefined + }, + + 'apache': { + title: 'Apache', + icon: '', + info: undefined + }, + + 'named': { + title: 'named', + icon: '', + info: undefined + }, + + 'squid': { + title: 'squid', + icon: '', + info: undefined + }, + + 'nut': { + title: 'UPS', + icon: '', + info: undefined + }, + + 'apcupsd': { + title: 'UPS', + icon: '', + info: undefined + }, + + 'smawebbox': { + title: 'Solar Power', + icon: '', + info: undefined + }, + + 'snmp': { + title: 'SNMP', + icon: '', + info: undefined + } +}; + +// submenu +// information about the submenus +netdataDashboard.submenu = { + 'mem.ksm': { + title: 'Memory Deduper', + info: 'Kernel Same-page Merging (KSM) performance monitoring, read from several files in /sys/kernel/mm/ksm/. KSM is a memory-saving de-duplication feature in the Linux kernel (since version 2.6.32). The KSM daemon ksmd periodically scans those areas of user memory which have been registered with it, looking for pages of identical content which can be replaced by a single write-protected page (which is automatically copied if a process later wants to update its content). KSM was originally developed for use with KVM (where it was known as Kernel Shared Memory), to fit more virtual machines into physical memory, by sharing the data common between them. But it can be useful to any application which generates many instances of the same data.' + }, + + 'ipv4.ecn': { + info: 'Explicit Congestion Notification (ECN) is a TCP extension that allows end-to-end notification of network congestion without dropping packets. ECN is an optional feature that may be used between two ECN-enabled endpoints when the underlying network infrastructure also supports it.' + }, + + 'netfilter.conntrack': { + title: 'Connection Tracker', + info: 'Netfilter Connection Tracker performance monitoring, read from /proc/net/stat/nf_conntrack. The connection tracker keeps track of all connections of the machine, inbound and outbound. It works by keeping a database with all open connections, tracking network and address translation and connection expectations.' + }, + + 'netfilter.nfacct': { + title: 'Bandwidth Accounting', + info: 'The following information is read using the nfacct.plugin.' + }, + + 'netfilter.synproxy': { + title: 'DDoS Protection', + info: 'DDoS Protection performance monitoring read from /proc/net/stat/synproxy. SYNPROXY is a TCP SYN packets proxy. It is used to protect any TCP server (like a web server) from SYN floods and similar DDoS attacks. It is a netfilter module, in the Linux kernel (since version 3.12). It is optimized to handle millions of packets per second utilizing all CPUs available without any concurrency locking between the connections. It can be used for any kind of TCP traffic (even encrypted), since it does not interfere with the content itself.' + }, + + 'system.softnet_stat': { + title: 'softnet', + info: 'Statistics for CPUs SoftIRQs related to network receive work, read from /proc/net/softnet_stat. Break down per CPU core can be found at CPU / softnet statistics. processed states the number of packets processed, dropped is the number packets dropped because the network device backlog was full (to fix them use sysctl to increase net.core.netdev_max_backlog), squeezed is the number of packets dropped because the network device budget ran out (to fix them use sysctl to increase net.core.netdev_budget). More information about identifying and troubleshooting network driver related issues can be found at Red Hat Enterprise Linux Network Performance Tuning Guide.' + }, + + 'cpu.softnet_stat': { + title: 'softnet', + info: 'Statistics for per CPUs core SoftIRQs related to network receive work, read from /proc/net/softnet_stat. Total for all CPU cores can be found at System / softnet statistics. processed states the number of packets processed, dropped is the number packets dropped because the network device backlog was full (to fix them use sysctl to increase net.core.netdev_max_backlog), squeezed is the number of packets dropped because the network device budget ran out (to fix them use sysctl to increase net.core.netdev_budget). More information about identifying and troubleshooting network driver related issues can be found at Red Hat Enterprise Linux Network Performance Tuning Guide.' + } +}; + +// chart +// information works on the context of a chart +// Its purpose is to set: +// +// info: the text above the charts +// heads: the representation of the chart at the top the subsection (second level menu) +// mainheads: the representation of the chart at the top of the section (first level menu) +// colors: the dimension colors of the chart (the default colors are appended) +// height: the ratio of the chart height relative to the default +// +netdataDashboard.context = { + 'system.cpu': { + info: 'Total CPU utilization (all cores). 100% here means there is no CPU idle time at all. You can get per core usage at the CPUs section and per application usage at the Applications Monitoring section.
Keep an eye on iowait ' + sparkline('system.cpu', 'iowait', '%') + '. If it is constantly high, your disks are a bottleneck and they slow your system down.
Another important metric worth monitoring, is softirq ' + sparkline('system.cpu', 'softirq', '%') + '. A constantly high percentage of softirq may indicate network drivers issues.', + valueRange: "[0, 100]" + }, + + 'system.load': { + info: 'Current system load, i.e. the number of processes using CPU or waiting for system resources (usually CPU and disk). The 3 metrics refer to 1, 5 and 15 minute averages. Linux calculates this once every 5 seconds. Netdata reads them from /proc/loadavg. For more information check this wikipedia article', + height: 0.7 + }, + + 'system.io': { + info: 'Total Disk I/O, for all disks, read from /proc/vmstat. You can get detailed information about each disk at the Disks section and per application Disk usage at the Applications Monitoring section.' + }, + + 'system.swapio': { + info: 'Total Swap I/O, read from /proc/vmstat. (netdata measures both in and out. If either of them is not shown in the chart, it is because it is zero - you can change the page settings to always render all the available dimensions on all charts).' + }, + + 'system.pgfaults': { + info: 'Total page faults, read from /proc/vmstat. Major page faults indicates that the system is using its swap. You can find which applications use the swap at the Applications Monitoring section.' + }, + + 'system.entropy': { + colors: '#CC22AA', + info: 'Entropy, read from /proc/sys/kernel/random/entropy_avail, is like a pool of random numbers (/dev/random) that are mainly used in cryptography. It is advised that the pool remains always above 200. If the pool of entropy gets empty, you risk your security to be predictable and you should install a user-space random numbers generating daemon, like haveged or rng-tools (i.e. rngd), to keep the pool in healthy levels.' + }, + + 'system.forks': { + colors: '#5555DD', + info: 'The number of new processes created per second, read from /proc/stat.' + }, + + 'system.intr': { + colors: '#DD5555', + info: 'Total number of CPU interrupts, read from /proc/stat. Check system.interrupts that gives more detail about each interrupt and also the CPUs section where interrupts are analyzed per CPU core.' + }, + + 'system.interrupts': { + info: 'CPU interrupts in detail, read from /proc/interrupts. At the CPUs section, interrupts are analyzed per CPU core.' + }, + + 'system.softirqs': { + info: 'CPU softirqs in detail, read from /proc/softirqs. At the CPUs section, softirqs are analyzed per CPU core.' + }, + + 'system.processes': { + info: 'System processes, read from /proc/stat. Running are the processes in the CPU. Blocked are processes that are willing to enter the CPU, but they cannot, e.g. because they wait for disk activity.' + }, + + 'system.active_processes': { + info: 'All system processes, read from /proc/loadavg.' + }, + + 'system.ctxt': { + info: 'Context Switches, read from /proc/stat, is the switching of the CPU from one process, task or thread to another. If there are many processes or threads willing to execute and very few CPU cores available to handle them, the system is making more context switching to balance the CPU resources among them. The whole process is computationally intensive. The more the context switches, the slower the system gets.' + }, + + 'system.idlejitter': { + colors: '#5555AA', + info: 'Idle jitter is calculated by netdata. A thread is spawned that requests to sleep for a few microseconds. When the system wakes it up, it measures how many microseconds have passed. The difference between the requested and the actual duration of the sleep, is the idle jitter. This number is useful in real-time environments, where CPU jitter can affect the quality of the service (like VoIP media gateways).' + }, + + 'system.ipv4': { + info: 'Total IPv4 Traffic, read from /proc/net/netstat.' + }, + + 'system.ipv6': { + info: 'Total IPv6 Traffic, read from /proc/net/snmp6.' + }, + + 'system.ram': { + info: 'System memory, read from /proc/meminfo.' + }, + + 'system.swap': { + info: 'System swap memory, read from /proc/meminfo.' + }, + + // ------------------------------------------------------------------------ + // MEMORY + + 'mem.ksm_savings': { + heads: [ + netdataDashboard.gaugeChart('Saved', '12%', 'savings', '#0099CC') + ] + }, + + 'mem.ksm_ratios': { + heads: [ + function(id) { + return '
'; + } + ] + }, + + 'mem.committed': { + colors: NETDATA.colors[3] + }, + + 'mem.pgfaults': { + info: 'A page fault is a type of interrupt, called trap, raised by computer hardware when a running program accesses a memory page that is mapped into the virtual address space, but not actually loaded into main memory. If the page is loaded in memory at the time the fault is generated, but is not marked in the memory management unit as being loaded in memory, then it is called a minor or soft page fault. A major page fault is generated when the system needs to load the memory page from disk or swap memory. These values are read from /proc/vmstat.' + }, + + 'mem.committed': { + info: 'Committed Memory, read from /proc/meminfo, is the sum of all memory which has been allocated by processes.' + }, + + 'mem.writeback': { + info: 'Read from /proc/meminfo, Dirty is the amount of memory waiting to be written to disk. Writeback is how much memory is actively being written to disk.' + }, + + 'mem.kernel': { + info: 'Read from /proc/meminfo, This chart displays the total ammount of memory being used by the kernel. Slab is the amount of memory used by the kernel to cache data structures for its own use. KernelStack is the amount of memory allocated for each task done by the kernel. PageTables is the amount of memory decicated to the lowest level of page tables (A page table is used to turn a virtual address into a physical memory address). VmallocUsed is the amount of memory being used as virtual address space.' + }, + + 'mem.slab': { + info: 'Read from /proc/meminfo, reclaimable is the amount of memory which the kernel can reuse. unreclaimable can not be reused even when the kernel is lacking memory.' + }, + + // ------------------------------------------------------------------------ + // network interfaces + + 'net.drops': { + info: 'Packets that have been dropped at the network interface level. These are the same counters reported by ifconfig as RX dropped (inbound) and TX dropped (outbound). inbound packets can be dropped at the network interface level due to softnet backlog overflow, bad / unintented VLAN tags, unknown or unregistered protocols, IPv6 frames when the server is not configured for IPv6. Check this document for more information.' + }, + + // ------------------------------------------------------------------------ + // IPv4 + + 'ipv4.tcpmemorypressures': { + info: 'Number of times a socket was put in memory pressure due to a non fatal memory allocation failure (the kernel attempts to work around this situation by reducing the send buffers, etc).' + }, + + 'ipv4.tcpconnaborts': { + info: 'TCP connection aborts. baddata (TCPAbortOnData) happens while the connection is on FIN_WAIT1 and the kernel receives a packet with a sequence number beyond the last one for this connection - the kernel responds with RST (closes the connection). userclosed (TCPAbortOnClose) happens when the kernel receives data on an already closed connection and responds with RST. nomemory (TCPAbortOnMemory happens when there are too many orphaned sockets (not attached to an fd) and the kernel has to drop a connection - sometimes it will send an RST, sometimes it won\'t. timeout (TCPAbortOnTimeout) happens when a connection times out. linger (TCPAbortOnLinger) happens when the kernel killed a socket that was already closed by the application and lingered around for long enough. failed (TCPAbortFailed) happens when the kernel attempted to send an RST but failed because there was no memory available.' + }, + + // ------------------------------------------------------------------------ + // APPS + + 'apps.cpu': { + height: 2.0 + }, + + 'apps.mem': { + info: 'Real memory (RAM) used by applications. This does not include shared memory.' + }, + + 'apps.vmem': { + info: 'Virtual memory allocated by applications. Please check this article for more information.' + }, + + 'apps.preads': { + height: 2.0 + }, + + 'apps.pwrites': { + height: 2.0 + }, + + // ------------------------------------------------------------------------ + // USERS + + 'users.cpu': { + height: 2.0 + }, + + 'users.mem': { + info: 'Real memory (RAM) used per user. This does not include shared memory.' + }, + + 'users.vmem': { + info: 'Virtual memory allocated per user. Please check this article for more information.' + }, + + 'users.preads': { + height: 2.0 + }, + + 'users.pwrites': { + height: 2.0 + }, + + // ------------------------------------------------------------------------ + // GROUPS + + 'groups.cpu': { + height: 2.0 + }, + + 'groups.mem': { + info: 'Real memory (RAM) used per user group. This does not include shared memory.' + }, + + 'groups.vmem': { + info: 'Virtual memory allocated per user group. Please check this article for more information.' + }, + + 'groups.preads': { + height: 2.0 + }, + + 'groups.pwrites': { + height: 2.0 + }, + + // ------------------------------------------------------------------------ + // NETWORK QoS + + 'tc.qos': { + heads: [ + function(id) { + if(id.match(/.*-ifb$/)) + return netdataDashboard.gaugeChart('Inbound', '12%', '', '#5555AA'); + else + return netdataDashboard.gaugeChart('Outbound', '12%', '', '#AA9900'); + } + ] + }, + + // ------------------------------------------------------------------------ + // NETWORK INTERFACES + + 'net.net': { + heads: [ + netdataDashboard.gaugeChart('Received', '12%', 'received'), + netdataDashboard.gaugeChart('Sent', '12%', 'sent') + ] + }, + + // ------------------------------------------------------------------------ + // NETFILTER + + 'netfilter.sockets': { + colors: '#88AA00', + heads: [ + netdataDashboard.gaugeChart('Active Connections', '12%', '', '#88AA00') + ] + }, + + 'netfilter.new': { + heads: [ + netdataDashboard.gaugeChart('New Connections', '12%', 'new', '#5555AA') + ] + }, + + // ------------------------------------------------------------------------ + // DISKS + + 'disk.util': { + colors: '#FF5588', + heads: [ + netdataDashboard.gaugeChart('Utilization', '12%', '', '#FF5588') + ], + info: 'Disk Utilization measures the amount of time the disk was busy with something. This is not related to its performance. 100% means that the Linux kernel always had an outstanding operation on the disk. Keep in mind that depending on the underlying technology of the disk, 100% here may or may not be an indication of congestion.' + }, + + 'disk.backlog': { + colors: '#0099CC', + info: 'Backlog is an indication of the duration of pending disk operations. On every I/O event the Linux kernel is multiplying the time spent doing I/O since the last update of this field with the number of pending operations. While not accurate, this metric can provide an indication of the expected completion time of the operations in progress.' + }, + + 'disk.io': { + heads: [ + netdataDashboard.gaugeChart('Read', '12%', 'reads'), + netdataDashboard.gaugeChart('Write', '12%', 'writes') + ], + info: 'Amount of data transferred to and from disk.' + }, + + 'disk.ops': { + info: 'Completed disk I/O operations. Keep in mind the number of operations requested might be higher, since the Linux kernel is able to merge adjacent to each other (see merged operations chart).' + }, + + 'disk.qops': { + info: 'I/O operations currently in progress. This metric is a snapshot - it is not an average over the last interval.' + }, + + 'disk.iotime': { + height: 0.5, + info: 'The sum of the duration of all completed I/O operations. This number can exceed the interval if the disk is able to execute I/O operations in parallel.' + }, + 'disk.mops': { + height: 0.5, + info: 'The number of merged disk operations. The Linux kernel is able to merge adjacent I/O operations, for example two 4KB reads can become one 8KB read before given to disk.' + }, + 'disk.svctm': { + height: 0.5, + info: 'The average service time for completed I/O operations. This metric is calculated using the total busy time of the disk and the number of completed operations. If the disk is able to execute multiple parallel operations the reporting average service time will be misleading.' + }, + 'disk.avgsz': { + height: 0.5, + info: 'The average I/O operation size.' + }, + 'disk.await': { + height: 0.5, + info: 'The average time for I/O requests issued to the device to be served. This includes the time spent by the requests in queue and the time spent servicing them.' + }, + + 'disk.space': { + info: 'Disk space utilization. reserved for root is automatically reserved by the system to prevent the root user from getting out of space.' + }, + 'disk.inodes': { + info: 'inodes (or index nodes) are filesystem objects (e.g. files and directories). On many types of file system implementations, the maximum number of inodes is fixed at filesystem creation, limiting the maximum number of files the filesystem can hold. It is possible for a device to run out of inodes. When this happens, new files cannot be created on the device, even though there may be free space available.' + }, + + 'mysql.net': { + info: 'The amount of data sent to mysql clients (out) and received from mysql clients (in).' + }, + + // ------------------------------------------------------------------------ + // MYSQL + + 'mysql.queries': { + info: 'The number of statements executed by the server.
    ' + + '
  • queries counts the statements executed within stored SQL programs.
  • ' + + '
  • questions counts the statements sent to the mysql server by mysql clients.
  • ' + + '
  • slow queries counts the number of statements that took more than long_query_time seconds to be executed.' + + ' For more information about slow queries check the mysql slow query log.
  • ' + + '
' + }, + + 'mysql.handlers': { + info: 'Usage of the internal handlers of mysql. This chart provides very good insights of what the mysql server is actually doing.' + + ' (if the chart is not showing all these dimensions it is because they are zero - set Which dimensions to show? to All from the dashboard settings, to render even the zero values)
    ' + + '
  • commit, the number of internal COMMIT statements.
  • ' + + '
  • delete, the number of times that rows have been deleted from tables.
  • ' + + '
  • prepare, a counter for the prepare phase of two-phase commit operations.
  • ' + + '
  • read first, the number of times the first entry in an index was read. A high value suggests that the server is doing a lot of full index scans; e.g. SELECT col1 FROM foo, with col1 indexed.
  • ' + + '
  • read key, the number of requests to read a row based on a key. If this value is high, it is a good indication that your tables are properly indexed for your queries.
  • ' + + '
  • read next, the number of requests to read the next row in key order. This value is incremented if you are querying an index column with a range constraint or if you are doing an index scan.
  • ' + + '
  • read prev, the number of requests to read the previous row in key order. This read method is mainly used to optimize ORDER BY ... DESC.
  • ' + + '
  • read rnd, the number of requests to read a row based on a fixed position. A high value indicates you are doing a lot of queries that require sorting of the result. You probably have a lot of queries that require MySQL to scan entire tables or you have joins that do not use keys properly.
  • ' + + '
  • read rnd next, the number of requests to read the next row in the data file. This value is high if you are doing a lot of table scans. Generally this suggests that your tables are not properly indexed or that your queries are not written to take advantage of the indexes you have.
  • ' + + '
  • rollback, the number of requests for a storage engine to perform a rollback operation.
  • ' + + '
  • savepoint, the number of requests for a storage engine to place a savepoint.
  • ' + + '
  • savepoint rollback, the number of requests for a storage engine to roll back to a savepoint.
  • ' + + '
  • update, the number of requests to update a row in a table.
  • ' + + '
  • write, the number of requests to insert a row in a table.
  • ' + + '
' + }, + + 'mysql.table_locks': { + info: 'MySQL table locks counters:
    ' + + '
  • immediate, the number of times that a request for a table lock could be granted immediately.
  • ' + + '
  • waited, the number of times that a request for a table lock could not be granted immediately and a wait was needed. If this is high and you have performance problems, you should first optimize your queries, and then either split your table or tables or use replication.
  • ' + + '
' + }, + + // ------------------------------------------------------------------------ + // APACHE + + 'apache.connections': { + colors: NETDATA.colors[4], + mainheads: [ + netdataDashboard.gaugeChart('Connections', '12%', '', NETDATA.colors[4]) + ] + }, + + 'apache.requests': { + colors: NETDATA.colors[0], + mainheads: [ + netdataDashboard.gaugeChart('Requests', '12%', '', NETDATA.colors[0]) + ] + }, + + 'apache.net': { + colors: NETDATA.colors[3], + mainheads: [ + netdataDashboard.gaugeChart('Bandwidth', '12%', '', NETDATA.colors[3]) + ] + }, + + 'apache.workers': { + mainheads: [ + function(id) { + return '
'; + } + ] + }, + + 'apache.bytesperreq': { + colors: NETDATA.colors[3], + height: 0.5 + }, + + 'apache.reqpersec': { + colors: NETDATA.colors[4], + height: 0.5 + }, + + 'apache.bytespersec': { + colors: NETDATA.colors[6], + height: 0.5 + }, + + + // ------------------------------------------------------------------------ + // NGINX + + 'nginx.connections': { + colors: NETDATA.colors[4], + mainheads: [ + netdataDashboard.gaugeChart('Connections', '12%', '', NETDATA.colors[4]) + ] + }, + + 'nginx.requests': { + colors: NETDATA.colors[0], + mainheads: [ + netdataDashboard.gaugeChart('Requests', '12%', '', NETDATA.colors[0]) + ] + }, + + // ------------------------------------------------------------------------ + // NETDATA + + 'netdata.response_time': { + info: 'The netdata API response time measures the time netdata needed to serve requests. This time includes everything, from the reception of the first byte of a request, to the dispatch of the last byte of its reply, therefore it includes all network latencies involved (i.e. a client over a slow network will influence these metrics).' + }, + + // ------------------------------------------------------------------------ + // RETROSHARE + + 'retroshare.bandwidth': { + info: 'RetroShare inbound and outbound traffic.', + mainheads: [ + netdataDashboard.gaugeChart('Received', '12%', 'bandwidth_down_kb'), + netdataDashboard.gaugeChart('Sent', '12%', 'bandwidth_up_kb') + ] + }, + + 'retroshare.peers': { + info: 'Number of (connected) RetroShare friends.', + mainheads: [ + function(id) { + return '
'; + } + ] + }, + + 'retroshare.dht': { + info: 'Statistics about RetroShare\'s DHT. These values are estimated!' + }, + + // ------------------------------------------------------------------------ + // fping + + 'fping.quality': { + colors: NETDATA.colors[10], + height: 0.5 + }, + + 'fping.packets': { + height: 0.5 + } + +}; diff --git a/web/demo.html b/web/demo.html index 12b7241e..dc8c7818 100644 --- a/web/demo.html +++ b/web/demo.html @@ -20,7 +20,7 @@ - +
diff --git a/web/demo2.html b/web/demo2.html index 3903fb6e..a7795c5c 100644 --- a/web/demo2.html +++ b/web/demo2.html @@ -21,7 +21,7 @@ - +
diff --git a/web/demosites.html b/web/demosites.html index 3d053891..b515b82c 100644 --- a/web/demosites.html +++ b/web/demosites.html @@ -52,26 +52,30 @@ and that you have chown it to be owned by netdata:netdata --> - +