LICENSE.md \
COPYING \
autogen.sh \
- netdata-9999.ebuild \
tests/stress.sh \
$(NULL)
MAINTAINERCLEANFILES= $(srcdir)/Makefile.in
dist_charts_SCRIPTS = \
- airsearches.chart.sh \
ap.chart.sh \
apache.chart.sh \
cpu_apps.chart.sh \
cpufreq.chart.sh \
- crsproxy.chart.sh \
example.chart.sh \
exim.chart.sh \
hddtemp.chart.sh \
+++ /dev/null
-#!/bin/sh
-
-airsearches_url=
-airsearches_cmds=
-airsearches_update_every=15
-
-airsearches_get() {
- wget 2>/dev/null -O - "$airsearches_url" |\
- sed -e "s|<br />|\n|g" -e "s|: |=|g" -e "s| \+|_|g" -e "s/^/airsearches_/g" |\
- tr "[A-Z]\.\!@#\$%^&*()_+\-" "[a-z]_____________" |\
- egrep "^airsearches_[a-z0-9_]+=[0-9]+$"
-}
-
-airsearches_check() {
- # make sure we have all the commands we need
- require_cmd wget || return 1
-
- # make sure we are configured
- if [ -z "$airsearches_url" ]
- then
- echo >&2 "$PROGRAM_NAME: airsearches: not configured. Please set airsearches_url='url' in $confd/airsearches.conf"
- return 1
- fi
-
- # check once if the url works
- wget 2>/dev/null -O /dev/null "$airsearches_url"
- if [ ! $? -eq 0 ]
- then
- echo >&2 "$PROGRAM_NAME: airsearches: cannot fetch the url: $airsearches_url. Please set airsearches_url='url' in $confd/airsearches.conf"
- return 1
- fi
-
- # if the admin did not give any commands
- # find the available ones
- if [ -z "$airsearches_cmds" ]
- then
- airsearches_cmds="$(airsearches_get | cut -d '=' -f 1 | sed "s/^airsearches_//g" | sort -u)"
- echo
- fi
-
- # did we find any commands?
- if [ -z "$airsearches_cmds" ]
- then
- echo >&2 "$PROGRAM_NAME: airsearches: cannot find command list automatically. Please set airsearches_cmds='...' in $confd/airsearches.conf"
- return 1
- fi
-
- # ok we can do it
- return 0
-}
-
-airsearches_create() {
- [ -z "$airsearches_cmds" ] && return 1
-
- # create the charts
- local x=
- echo "CHART airsearches.affiliates '' 'Air Searches per affiliate' 'requests / min' airsearches '' stacked 20000 $airsearches_update_every"
- for x in $airsearches_cmds
- do
- echo "DIMENSION $x '' incremental 60 1"
- done
-
- return 0
-}
-
-airsearches_update() {
- # the first argument to this function is the microseconds since last update
- # pass this parameter to the BEGIN statement (see bellow).
-
- # do all the work to collect / calculate the values
- # for each dimension
- # remember: KEEP IT SIMPLE AND SHORT
-
- # get the values from airsearches
- eval "$(airsearches_get)"
-
- # write the result of the work.
- local x=
-
- echo "BEGIN airsearches.affiliates $1"
- for x in $airsearches_cmds
- do
- eval "v=\$airsearches_$x"
- echo "SET $x = $v"
- done
- echo "END"
-
- airsearches_dt=0
-
- return 0
-}
+++ /dev/null
-#!/bin/sh
-
-crsproxy_url=
-crsproxy_cmds=
-crsproxy_update_every=15
-
-crsproxy_get() {
- wget 2>/dev/null -O - "$crsproxy_url" |\
- sed \
- -e "s/ \+/ /g" \
- -e "s/\./_/g" \
- -e "s/ =/=/g" \
- -e "s/= /=/g" \
- -e "s/^/crsproxy_/g" |\
- egrep "^crsproxy_[a-zA-Z][a-zA-Z0-9_]*=[0-9]+$"
-}
-
-crsproxy_check() {
- # make sure we have all the commands we need
- require_cmd wget || return 1
-
- if [ -z "$crsproxy_url" ]
- then
- echo >&2 "$PROGRAM_NAME: crsproxy: not configured. Please set crsproxy_url='url' in $confd/crsproxy.conf"
- return 1
- fi
-
- # check once if the url works
- wget 2>/dev/null -O /dev/null "$crsproxy_url"
- if [ ! $? -eq 0 ]
- then
- echo >&2 "$PROGRAM_NAME: crsproxy: cannot fetch the url: $crsproxy_url. Please set crsproxy_url='url' in $confd/crsproxy.conf"
- return 1
- fi
-
- # if the user did not request specific commands
- # find the commands available
- if [ -z "$crsproxy_cmds" ]
- then
- crsproxy_cmds="$(crsproxy_get | cut -d '=' -f 1 | sed "s/^crsproxy_cmd_//g" | sort -u)"
- fi
-
- # if no commands are available
- if [ -z "$crsproxy_cmds" ]
- then
- echo >&2 "$PROGRAM_NAME: crsproxy: cannot find command list automatically. Please set crsproxy_cmds='...' in $confd/crsproxy.conf"
- return 1
- fi
- return 0
-}
-
-crsproxy_create() {
- # create the charts
- cat <<EOF
-CHART crsproxy.connected '' "CRS Proxy Connected Clients" "clients" crsproxy '' line 20000 $crsproxy_update_every
-DIMENSION web '' absolute 1 1
-DIMENSION native '' absolute 1 1
-DIMENSION virtual '' absolute 1 1
-CHART crsproxy.requests '' "CRS Proxy Requests Rate" "requests / min" crsproxy '' area 20001 $crsproxy_update_every
-DIMENSION web '' incremental 60 1
-DIMENSION native '' incremental -60 1
-CHART crsproxy.clients '' "CRS Proxy Clients Rate" "clients / min" crsproxy '' area 20010 $crsproxy_update_every
-DIMENSION web '' incremental 60 1
-DIMENSION native '' incremental -60 1
-DIMENSION virtual '' incremental 60 1
-CHART crsproxy.replies '' "CRS Replies Rate" "replies / min" crsproxy '' area 20020 $crsproxy_update_every
-DIMENSION ok '' incremental 60 1
-DIMENSION failed '' incremental -60 1
-CHART crsproxy.bconnections '' "Back-End Connections Rate" "connections / min" crsproxy '' area 20030 $crsproxy_update_every
-DIMENSION ok '' incremental 60 1
-DIMENSION failed '' incremental -60 1
-EOF
-
- local x=
- echo "CHART crsproxy.commands '' 'CRS Commands Requests' 'requests / min' crsproxy '' stacked 20100 $crsproxy_update_every"
- for x in $crsproxy_cmds
- do
- echo "DIMENSION $x '' incremental 60 $crsproxy_update_every"
- done
-
- echo "CHART crsproxy.commands_failed '' 'CRS Failed Commands' 'replies / min' crsproxy '' stacked 20110 $crsproxy_update_every"
- for x in $crsproxy_cmds
- do
- echo "DIMENSION $x '' incremental 60 $crsproxy_update_every"
- done
-
- return 0
-}
-
-
-crsproxy_update() {
- # the first argument to this function is the microseconds since last update
- # pass this parameter to the BEGIN statement (see bellow).
-
- # do all the work to collect / calculate the values
- # for each dimension
- # remember: KEEP IT SIMPLE AND SHORT
-
- # get the values from crsproxy
- eval "$(crsproxy_get)"
-
-
- # write the result of the work.
- cat <<VALUESEOF
-BEGIN crsproxy.connected $1
-SET web = $((crsproxy_web_clients_opened - crsproxy_web_clients_closed))
-SET native = $((crsproxy_crs_clients_opened - crsproxy_crs_clients_closed))
-SET virtual = $((crsproxy_virtual_clients_opened - crsproxy_virtual_clients_closed))
-END
-BEGIN crsproxy.requests $1
-SET web = $crsproxy_web_requests
-SET native = $crsproxy_native_requests
-END
-BEGIN crsproxy.clients $1
-SET web = $crsproxy_web_clients_opened
-SET native = $crsproxy_crs_clients_opened
-SET virtual = $crsproxy_virtual_clients_opened
-END
-BEGIN crsproxy.replies $1
-SET ok = $crsproxy_replies_success
-SET failed = $crsproxy_replies_error
-END
-BEGIN crsproxy.bconnections $1
-SET ok = $crsproxy_connections_nonblocking_established
-SET failed = $crsproxy_connections_nonblocking_failed
-END
-VALUESEOF
-
- local native_requests="_native_requests"
- local web_requests="_web_requests"
- local replies_error="_replies_error"
- local x=
-
- echo "BEGIN crsproxy.commands $1"
- for x in $crsproxy_cmds
- do
- eval "v=\$(( crsproxy_cmd_$x$native_requests + crsproxy_cmd_$x$web_requests ))"
- echo "SET $x = $v"
- done
- echo "END"
-
- echo "BEGIN crsproxy.commands_failed $1"
- for x in $crsproxy_cmds
- do
- eval "v=\$crsproxy_cmd_$x$replies_error"
- echo "SET $x = $v"
- done
- echo "END"
-
- return 0
-}
# *name* substring mode: will search for 'name' in the whole command line (/proc/PID/cmdline)
#
# If you enter even just one *name* (substring), apps.plugin will process
-# /proc/PID/cmdline for all processes, on every iteration.
+# /proc/PID/cmdline for all processes, just once (when they are first seen).
#
# To add process names with single quotes, enclose them in double quotes
# example: "process with this ' single quote"
# You can add any number of groups you like. Only the ones found running will
# affect the charts generated. However, producing charts with hundreds of
# dimensions may slow down your web browser.
+#
+# The order of the entries in this list is important: the first that matches
+# a process is used, so put important ones at the top. Processes not matched
+# by any row, will inherit it from their parents or children.
+#
+# The order also controls the order of the dimensions on the generated charts
+# (although applications started after apps.plugin is started, will be appended
+# to the existing list of dimensions the netdata daemon maintains).
+
+# -----------------------------------------------------------------------------
+# NETDATA processes accounting
+
+# netdata main process
+netdata: netdata
+
+# netdata known plugins
+# plugins not defined here will be accumulated in netdata, above
+apps.plugin: apps.plugin
+charts.d.plugin: *charts.d.plugin*
+node.d.plugin: *node.d.plugin*
+python.d.plugin: *python.d.plugin*
+tc-qos-helper: *tc-qos-helper.sh*
-compile: cc1 cc1plus as gcc* ld make automake autoconf git
-rsync: rsync
-media: mplayer vlc xine mediatomb omxplayer* kodi* xbmc* mediacenter eventlircd mpd minidlnad
-squid: squid* c-icap
-apache: apache* httpd
-mysql: mysql*
-asterisk: asterisk
-opensips: opensips* stund
-radius: radius*
+# -----------------------------------------------------------------------------
+# authentication/authorization related servers
+
+auth: radius* openldap* ldap*
fail2ban: fail2ban*
-mail: dovecot imapd pop3d
-postfix: master
-nginx: nginx
+
+# -----------------------------------------------------------------------------
+# web/ftp servers
+
+httpd: apache* httpd nginx* lighttpd
+proxy: squid* c-icap squidGuard varnish*
+php: php*
+ftpd: proftpd in.tftpd vsftpd
+uwsgi: uwsgi
+unicorn: *unicorn*
+
+# -----------------------------------------------------------------------------
+# database servers
+
+sql: mysqld* mariad* postgres*
+nosql: mongod redis*
+
+# -----------------------------------------------------------------------------
+# email servers
+
+email: dovecot imapd pop3d amavis* master zmstat* zmmailboxdmgr qmgr oqmgr
+
+# -----------------------------------------------------------------------------
+# networking and VPN servers
+
+ppp: ppp*
+vpn: openvpn pptp* cjdroute
+wifi: hostapd wpa_supplicant
+
+# -----------------------------------------------------------------------------
+# high availability and balancers
+
+camo: *camo*
+balancer: ipvs_* haproxy
+ha: corosync hs_logd ha_logd stonithd
+
+# -----------------------------------------------------------------------------
+# telephony
+
+pbx: asterisk safe_asterisk *vicidial*
+sip: opensips* stund
+murmur: murmurd
+vines: *vines*
+
+# -----------------------------------------------------------------------------
+# monitoring
+
+logs: ulogd* syslog* rsyslog* logrotate
+nms: snmpd vnstatd smokeping zabbix* monit munin* mon openhpid watchdog tailon nrpe
splunk: splunkd
-mongo: mongod
-redis: redis*
-lighttpd: lighttpd
-ftpd: proftpd in.tftpd
+
+# -----------------------------------------------------------------------------
+# file systems and file servers
+
samba: smbd nmbd winbindd
nfs: rpcbind rpc.* nfs*
+zfs: spl_* z_* txg_* zil_* arc_* l2arc*
+btrfs: btrfs*
+
+# -----------------------------------------------------------------------------
+# containers & virtual machines
+
+containers: lxc* docker*
+VMs: vbox* VBox* qemu*
+
+# -----------------------------------------------------------------------------
+# ssh servers and clients
+
ssh: ssh* scp
-X: X lightdm xdm pulseaudio gkrellm
-xfce: xfwm4 xfdesktop xfce* Thunar xfsettingsd
-gnome: gnome-* gdm gconfd-2
-named: named rncd
-clam: clam* *clam
-cups: cups*
-ntp: ntp*
-torrent: deluge* transmission*
-vbox: vbox* VBox*
-log: ulogd syslog* rsyslog* logrotate
-nms: snmpd vnstatd smokeping zabbix* monit munin* mon openhpid
-ppp: ppp* pptp*
-inetd: inetd xinetd
-openvpn: openvpn
-cjdns: cjdroute
-cron: cron atd
-ha: corosync hs_logd ha_logd stonithd
-ipvs: ipvs_*
+
+# -----------------------------------------------------------------------------
+# print servers and clients
+
+print: cups* lpd lpq
+
+# -----------------------------------------------------------------------------
+# time servers and clients
+
+time: ntp*
+
+# -----------------------------------------------------------------------------
+# dhcp servers and clients
+
+dhcp: *dhcp*
+
+# -----------------------------------------------------------------------------
+# name servers and clients
+
+named: named rncd dig
+
+# -----------------------------------------------------------------------------
+# installation / compilation / debugging
+
+build: cc1 cc1plus as gcc* ld make automake autoconf autoreconf git valgrind*
+
+# -----------------------------------------------------------------------------
+# antivirus
+
+antivirus: clam* *clam
+
+# -----------------------------------------------------------------------------
+# torrent clients
+
+torrents: *deluge* transmission* *SickBeard*
+
+# -----------------------------------------------------------------------------
+# backup servers and clients
+
+backup: rsync bacula*
+
+# -----------------------------------------------------------------------------
+# cron
+
+cron: cron atd anacron
+
+# -----------------------------------------------------------------------------
+# UPS
+
+ups: upsmon upsd */nut/*
+
+# -----------------------------------------------------------------------------
+# Kernel / System
+
+system: systemd* udisks* udevd* *udevd connmand ipv6_addrconf dbus-* inetd xinetd mdadm
kernel: kthreadd kauditd lockd khelper kdevtmpfs khungtaskd rpciod fsnotify_mark kthrotld iscsi_eh deferwq
-netdata: netdata
-crsproxy: crsproxy
-wifi: hostapd wpa_supplicant
-system: systemd* udisks* udevd connmand ipv6_addrconf dbus-*
ksmd: ksmd
-lxc: lxc*
-zfs-spl: spl_*
-zfs-posix: z_*
-zfs-txg: txg_* zil_*
-zfs-arc: arc_* l2arc*
-php: php*
-zimbra: zmstat* zmmailboxdmgr
+
+# -----------------------------------------------------------------------------
+# media players, servers, clients
+
+media: mplayer vlc xine mediatomb omxplayer* kodi* xbmc* mediacenter eventlircd mpd minidlnad mt-daapd avahi*
+
+# -----------------------------------------------------------------------------
+# X
+
+X: X lightdm xdm pulseaudio gkrellm xfwm4 xfdesktop xfce* Thunar xfsettingsd xfconfd gnome-* gdm gconfd-2 *gvfsd gvfsd* kdm slim
+
+# -----------------------------------------------------------------------------
+# other application servers
+
+crsproxy: crsproxy
+sidekiq: *sidekiq*
java: java
-bacula: bacula*
-amavis: amavis*
-varnish: varnish*
-haproxy: haproxy
+chat: irssi
+++ /dev/null
-# Copyright 1999-2016 Gentoo Foundation
-# Distributed under the terms of the GNU General Public License v2
-# $Id$
-
-EAPI=6
-
-inherit linux-info systemd user
-
-if [[ ${PV} == "9999" ]] ; then
- EGIT_REPO_URI="git://github.com/firehol/${PN}.git"
- inherit git-r3 autotools
- SRC_URI=""
- KEYWORDS=""
-else
- SRC_URI="http://firehol.org/download/${PN}/releases/v${PV}/${P}.tar.xz"
- KEYWORDS="~amd64 ~x86"
-fi
-
-
-DESCRIPTION="Linux real time system monitoring, done right!"
-HOMEPAGE="https://github.com/firehol/netdata http://netdata.firehol.org/"
-
-LICENSE="GPL-3+ MIT BSD"
-SLOT="0"
-IUSE="+compression nfacct nodejs"
-
-# most unconditional dependencies are for plugins.d/charts.d.plugin:
-RDEPEND="
- >=app-shells/bash-4:0
- net-misc/curl
- net-misc/wget
- virtual/awk
- compression? ( sys-libs/zlib )
- nfacct? (
- net-firewall/nfacct
- net-libs/libmnl
- )
- nodejs? (
- net-libs/nodejs
- )"
-
-DEPEND="${RDEPEND}
- virtual/pkgconfig"
-
-# check for Kernel-Samepage-Merging (CONFIG_KSM)
-CONFIG_CHECK="
- ~KSM
-"
-
-: ${NETDATA_USER:=netdata}
-: ${NETDATA_GROUP:=netdata}
-
-pkg_setup() {
- linux-info_pkg_setup
-
- enewgroup ${PN}
- enewuser ${PN} -1 -1 / ${PN}
-}
-
-src_prepare() {
- default
- [[ ${PV} == "9999" ]] && eautoreconf
-}
-
-src_configure() {
- econf \
- --localstatedir=/var \
- --with-user=${NETDATA_USER} \
- $(use_enable nfacct plugin-nfacct) \
- $(use_with compression zlib)
-}
-
-src_install() {
- default
-
- fowners ${NETDATA_USER}:${NETDATA_GROUP} /var/log/netdata
- fowners ${NETDATA_USER}:${NETDATA_GROUP} /var/cache/netdata
-
- chown -Rc ${NETDATA_USER}:${NETDATA_GROUP} "${ED}"/usr/share/${PN} || die
-
- cat >> "${T}"/${PN}-sysctl <<- EOF
- kernel.mm.ksm.run = 1
- kernel.mm.ksm.sleep_millisecs = 1000
- EOF
-
- dodoc "${T}"/${PN}-sysctl
-
- newinitd system/netdata-openrc ${PN}
- systemd_dounit system/netdata.service
-}
-
-pkg_postinst() {
- if [[ -e "/sys/kernel/mm/ksm/run" ]]; then
- elog "INFORMATION:"
- echo ""
- elog "I see you have kernel memory de-duper (called Kernel Same-page Merging,"
- elog "or KSM) available, but it is not currently enabled."
- echo ""
- elog "To enable it run:"
- echo ""
- elog "echo 1 >/sys/kernel/mm/ksm/run"
- elog "echo 1000 >/sys/kernel/mm/ksm/sleep_millisecs"
- echo ""
- elog "If you enable it, you will save 20-60% of netdata memory."
- else
- elog "INFORMATION:"
- echo ""
- elog "I see you do not have kernel memory de-duper (called Kernel Same-page"
- elog "Merging, or KSM) available."
- echo ""
- elog "To enable it, you need a kernel built with CONFIG_KSM=y"
- echo ""
- elog "If you can have it, you will save 20-60% of netdata memory."
- fi
-
-}
fi
echo >&2 "Stopping a possibly running netdata..."
- for p in \$(pidof netdata); do kill \$x; done
+ for p in \$(pidof netdata); do kill \$p; done
sleep 2
deletedir() {
exec_start_ms=$now_ms
$chart$charts_update $dt
ret=$?
-
+
# return the current time in ms in $now_ms
current_time_ms; exec_end_ms=$now_ms
else
charts_serial_failures[$chart]=$(( charts_serial_failures[$chart] + 1 ))
- if [ charts_serial_failures[$chart] -gt 10 ]
+ if [ ${charts_serial_failures[$chart]} -gt 10 ]
then
echo >&2 "$PROGRAM_NAME: chart '$chart' update() function reported failure ${charts_serial_failures[$chart]} times. Disabling it."
else
export PATH="${PATH}:/sbin:/usr/sbin:/usr/local/sbin"
+PROGRAM_FILE="$0"
+PROGRAM_NAME="$(basename $0)"
+PROGRAM_NAME="${PROGRAM_NAME/.plugin}"
+
+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)"
+fireqos_run_dir="/var/run/fireqos"
+qos_get_class_names_every=120
+qos_exit_every=3600
+
+# check if we have a valid number for interval
+t=${1}
+update_every=$((t))
+[ $((update_every)) -lt 1 ] && update_every=${NETDATA_UPDATE_EVERY}
+[ $((update_every)) -lt 1 ] && update_every=1
+
+# allow the user to override our defaults
+if [ -f "${config_dir}/tc-qos-helper.conf" ]
+ then
+ source "${config_dir}/tc-qos-helper.conf"
+fi
+
# default time function
now_ms=
current_time_ms() {
# if found and included, this file overwrites loopsleepms()
# with a high resolution timer function for precise looping.
-. "$NETDATA_PLUGINS_DIR/loopsleepms.sh.inc"
-
-# check if we have a valid number for interval
-t=$1
-sleep_time=$((t))
-[ $((sleep_time)) -lt 1 ] && $NETDATA_UPDATE_EVERY
-[ $((sleep_time)) -lt 1 ] && sleep_time=1
+. "${plugins_dir}/loopsleepms.sh.inc"
-tc_cmd="$(which tc)"
-if [ -z "$tc_cmd" ]
+if [ -z "${tc}" -o ! -x "${tc}" ]
then
- echo >&2 "tc: Cannot find a 'tc' command in this system."
+ echo >&2 "${PROGRAM_NAME}: Cannot find command 'tc' in this system."
exit 1
fi
}
show_tc() {
- local x="$1"
+ local x="${1}" interface_dev interface_classes interface_classes_monitor
- echo "BEGIN $x"
- $tc_cmd -s class show dev $x
+ echo "BEGIN ${x}"
+ ${tc} -s class show dev ${x}
# check FireQOS names for classes
- if [ ! -z "$fix_names" -a -f /var/run/fireqos/ifaces/$x ]
+ if [ ! -z "${fix_names}" -a -f "${fireqos_run_dir}/ifaces/${x}" ]
then
- name="$(cat /var/run/fireqos/ifaces/$x)"
- echo "SETDEVICENAME $name"
+ name="$(<"${fireqos_run_dir}/ifaces/${x}")"
+ echo "SETDEVICENAME ${name}"
+ interface_dev=
interface_classes=
interface_classes_monitor=
- . /var/run/fireqos/$name.conf
- for n in $interface_classes_monitor
+ source "${fireqos_run_dir}/${name}.conf"
+ for n in ${interface_classes_monitor}
do
- setclassname $(echo $n | tr '|' ' ')
+ setclassname ${n//|/ }
done
- echo "SETDEVICEGROUP $interface_dev"
+ [ ! -z "${interface_dev}" ] && echo "SETDEVICEGROUP ${interface_dev}"
fi
- echo "END $x"
+ echo "END ${x}"
}
all_devices() {
cat /proc/net/dev | grep ":" | cut -d ':' -f 1 | while read dev
do
- l=$($tc_cmd class show dev $dev | wc -l)
- [ $l -ne 0 ] && echo $dev
+ l=$(${tc} class show dev ${dev} | wc -l)
+ [ $l -ne 0 ] && echo ${dev}
done
}
# update devices and class names
# once every 2 minutes
-names_every=$((120 / sleep_time))
+names_every=$((qos_get_class_names_every / update_every))
# exit this script every hour
# it will be restarted automatically
-exit_after=$((3600 / sleep_time))
+exit_after=$((qos_exit_every / update_every))
c=0
gc=0
c=$((c + 1))
gc=$((gc + 1))
- if [ $c -le 1 -o $c -ge $names_every ]
+ if [ ${c} -le 1 -o ${c} -ge ${names_every} ]
then
c=1
fix_names="YES"
devices="$( all_devices )"
fi
- for d in $devices
+ for d in ${devices}
do
- show_tc $d
+ show_tc ${d}
done
- echo "WORKTIME $LOOPSLEEPMS_LASTWORK"
+ echo "WORKTIME ${LOOPSLEEPMS_LASTWORK}"
- loopsleepms $sleep_time
+ loopsleepms ${update_every}
- [ $gc -gt $exit_after ] && exit 0
+ [ ${gc} -gt ${exit_after} ] && exit 0
done
MAINTAINERCLEANFILES= $(srcdir)/Makefile.in
+CLEANFILES = \
+ python-modules-installer.sh \
+ $(NULL)
include $(top_srcdir)/build/subst.inc
-h|--help)
echo "${0} [--dir netdata-python.d-path] [--system]"
+ echo "Please make sure you have installed packages: python-pip (or python3-pip) python-dev libyaml-dev libmysqlclient-dev"
exit 0
;;
pv=3
pip="$(which pip3 2>/dev/null)"
else
- echo >&2 "Cannot detect python version"
+ echo >&2 "Cannot detect python version. Is python installed?"
exit 1
fi
[ -z "${pip}" ] && pip="$(which pip 2>/dev/null)"
if [ -z "${pip}" ]
then
- echo >& "pip command is required to install python v${pv} modules"
+ echo >&2 "pip command is required to install python v${pv} modules."
+ [ "${pv}" = "2" ] && echo >&2 "Please install python-pip."
+ [ "${pv}" = "3" ] && echo >&2 "Please install python3-pip."
exit 1
fi
installed=""
errors=0
pip_install() {
- local ret x
+ local ret x msg="${1}"
+ shift
echo >&2
echo >&2
ret=$?
fi
[ ${ret} -eq 0 ] && break
- echo >&2 "failed to install: ${x}"
+ echo >&2 "failed to install: ${x}. ${msg}"
done
if [ ${ret} -ne 0 ]
then
- echo >&2 "ERROR: could not install any of: ${*}"
+ echo >&2
+ echo >&2
+ echo >&2 "FAILED: could not install any of: ${*}. ${msg}"
+ echo >&2
+ echo >&2
errors=$(( errors + 1 ))
failed="${failed}|${*}"
else
+ echo >&2
+ echo >&2
echo >&2 "SUCCESS: we have: ${x}"
+ echo >&2
+ echo >&2
installed="${installed} ${x}"
fi
return ${ret}
if [ "${pv}" = "2" ]
then
- pip_install pyyaml yaml
- pip_install mysqlclient mysql-python pymysql
+ pip_install "is libyaml-dev and python-dev installed?" pyyaml
+ pip_install "is libmysqlclient-dev and python-dev installed?" mysqlclient mysql-python pymysql
else
- pip_install yaml pyyaml
- pip_install mysql-python mysqlclient pymysql
+ pip_install "is libyaml-dev and python-dev installed?" pyyaml
+ pip_install "is libmysqlclient-dev and python-dev installed?" mysql-python mysqlclient pymysql
fi
echo >&2
if [ ${errors} -ne 0 ]
then
echo >&2 "Failed to install ${errors} modules: ${failed}"
+ if [ ! -z "${target}" ]
+ then
+ echo >&2
+ echo >&2 "If you are getting errors during cleanup from pip, there is a known bug"
+ echo >&2 "in certain versions of pip that prevents installing packages local to an"
+ echo >&2 "application. To install them system-wide please run:"
+ echo >&2 "$0 --system"
+ fi
exit 1
else
echo >&2 "All done. We have: ${installed}"
-// TODO
-//
-// 1. disable RESET_OR_OVERFLOW check in charts
-
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#define MAX_NAME 100
#define MAX_CMDLINE 1024
-long processors = 1;
-long pid_max = 32768;
+int processors = 1;
+pid_t pid_max = 32768;
int debug = 0;
int update_every = 1;
unsigned long long file_counter = 0;
int proc_pid_cmdline_is_needed = 0;
-
+int include_exited_childs = 1;
char *host_prefix = "";
char *config_dir = CONFIG_DIR;
-#ifdef NETDATA_INTERNAL_CHECKS
-// ----------------------------------------------------------------------------
-// memory debugger
-// do not use in production systems - it mis-aligns allocated memory
-
-struct allocations {
- size_t allocations;
- size_t allocated;
- size_t allocated_max;
-} allocations = { 0, 0, 0 };
-
-#define MALLOC_MARK (uint32_t)(0x0BADCAFE)
-#define MALLOC_PREFIX (sizeof(uint32_t) * 2)
-#define MALLOC_SUFFIX (sizeof(uint32_t))
-#define MALLOC_OVERHEAD (MALLOC_PREFIX + MALLOC_SUFFIX)
-
-void *mark_allocation(void *allocated_ptr, size_t size_without_overheads) {
- uint32_t *real_ptr = (uint32_t *)allocated_ptr;
- real_ptr[0] = MALLOC_MARK;
- real_ptr[1] = (uint32_t) size_without_overheads;
-
- uint32_t *end_ptr = (uint32_t *)(allocated_ptr + MALLOC_PREFIX + size_without_overheads);
- end_ptr[0] = MALLOC_MARK;
-
- // fprintf(stderr, "MEMORY_POINTER: Allocated at %p, returning %p.\n", allocated_ptr, (void *)(allocated_ptr + MALLOC_PREFIX));
-
- return allocated_ptr + MALLOC_PREFIX;
-}
-
-void *check_allocation(const char *file, int line, const char *function, void *marked_ptr, size_t *size_without_overheads_ptr) {
- uint32_t *real_ptr = (uint32_t *)(marked_ptr - MALLOC_PREFIX);
-
- // fprintf(stderr, "MEMORY_POINTER: Checking pointer at %p, real %p for %s/%u@%s.\n", marked_ptr, (void *)(marked_ptr - MALLOC_PREFIX), function, line, file);
-
- if(real_ptr[0] != MALLOC_MARK) fatal("MEMORY: prefix MARK is not valid for %s/%d@%s.", function, line, file);
-
- size_t size = real_ptr[1];
-
- uint32_t *end_ptr = (uint32_t *)(marked_ptr + size);
- if(end_ptr[0] != MALLOC_MARK) fatal("MEMORY: suffix MARK of allocation with size %zu is not valid for %s/%d@%s.", size, function, line, file);
-
- if(size_without_overheads_ptr) *size_without_overheads_ptr = size;
-
- return real_ptr;
-}
-
-void *malloc_debug(const char *file, int line, const char *function, size_t size) {
- void *ptr = malloc(size + MALLOC_OVERHEAD);
- if(!ptr) fatal("MEMORY: Cannot allocate %zu bytes for %s/%d@%s.", size, function, line, file);
-
- allocations.allocated += size;
- allocations.allocations++;
-
- debug(D_MEMORY, "MEMORY: Allocated %zu bytes for %s/%d@%s."
- " Status: allocated %zu in %zu allocs."
- , size
- , function, line, file
- , allocations.allocated
- , allocations.allocations
- );
-
- if(allocations.allocated > allocations.allocated_max) {
- debug(D_MEMORY, "MEMORY: total allocation peak increased from %zu to %zu", allocations.allocated_max, allocations.allocated);
- allocations.allocated_max = allocations.allocated;
- }
-
- size_t csize;
- check_allocation(file, line, function, mark_allocation(ptr, size), &csize);
- if(size != csize) {
- fatal("Invalid size.");
- }
-
- return mark_allocation(ptr, size);
-}
-
-void *calloc_debug(const char *file, int line, const char *function, size_t nmemb, size_t size) {
- void *ptr = malloc_debug(file, line, function, (nmemb * size));
- bzero(ptr, nmemb * size);
- return ptr;
-}
-
-void free_debug(const char *file, int line, const char *function, void *ptr) {
- size_t size;
- void *real_ptr = check_allocation(file, line, function, ptr, &size);
-
- bzero(real_ptr, size + MALLOC_OVERHEAD);
-
- free(real_ptr);
- allocations.allocated -= size;
- allocations.allocations--;
-
- debug(D_MEMORY, "MEMORY: freed %zu bytes for %s/%d@%s."
- " Status: allocated %zu in %zu allocs."
- , size
- , function, line, file
- , allocations.allocated
- , allocations.allocations
- );
-}
-
-void *realloc_debug(const char *file, int line, const char *function, void *ptr, size_t size) {
- if(!ptr) return malloc_debug(file, line, function, size);
- if(!size) { free_debug(file, line, function, ptr); return NULL; }
-
- size_t old_size;
- void *real_ptr = check_allocation(file, line, function, ptr, &old_size);
-
- void *new_ptr = realloc(real_ptr, size + MALLOC_OVERHEAD);
- if(!new_ptr) fatal("MEMORY: Cannot allocate %zu bytes for %s/%d@%s.", size, function, line, file);
-
- allocations.allocated += size;
- allocations.allocated -= old_size;
-
- debug(D_MEMORY, "MEMORY: Re-allocated from %zu to %zu bytes for %s/%d@%s."
- " Status: allocated %zu in %zu allocs."
- , old_size, size
- , function, line, file
- , allocations.allocated
- , allocations.allocations
- );
-
- if(allocations.allocated > allocations.allocated_max) {
- debug(D_MEMORY, "MEMORY: total allocation peak increased from %zu to %zu", allocations.allocated_max, allocations.allocated);
- allocations.allocated_max = allocations.allocated;
- }
-
- return mark_allocation(new_ptr, size);
-}
-
-char *strdup_debug(const char *file, int line, const char *function, const char *ptr) {
- size_t size = 0;
- const char *s = ptr;
-
- while(*s++) size++;
- size++;
-
- char *p = malloc_debug(file, line, function, size);
- if(!p) fatal("Cannot allocate %zu bytes.", size);
-
- memcpy(p, ptr, size);
- return p;
-}
-
-#define malloc(size) malloc_debug(__FILE__, __LINE__, __FUNCTION__, (size))
-#define calloc(nmemb, size) calloc_debug(__FILE__, __LINE__, __FUNCTION__, (nmemb), (size))
-#define realloc(ptr, size) realloc_debug(__FILE__, __LINE__, __FUNCTION__, (ptr), (size))
-#define free(ptr) free_debug(__FILE__, __LINE__, __FUNCTION__, (ptr))
-
-#ifdef strdup
-#undef strdup
-#endif
-#define strdup(ptr) strdup_debug(__FILE__, __LINE__, __FUNCTION__, (ptr))
-
-#endif /* NETDATA_INTERNAL_CHECKS */
// ----------------------------------------------------------------------------
return processors;
}
-long get_system_pid_max(void) {
+pid_t get_system_pid_max(void) {
procfile *ff = NULL;
- long mpid = 32768;
+ pid_t mpid = 32768;
char filename[FILENAME_MAX + 1];
snprintfz(filename, FILENAME_MAX, "%s/proc/sys/kernel/pid_max", host_prefix);
return mpid;
}
- mpid = atol(procfile_lineword(ff, 0, 0));
+ mpid = (pid_t)atoi(procfile_lineword(ff, 0, 0));
if(!mpid) mpid = 32768;
procfile_close(ff);
unsigned long long num_threads;
unsigned long long rss;
- unsigned long long fix_minflt;
- unsigned long long fix_cminflt;
- unsigned long long fix_majflt;
- unsigned long long fix_cmajflt;
- unsigned long long fix_utime;
- unsigned long long fix_stime;
- unsigned long long fix_cutime;
- unsigned long long fix_cstime;
+ long long fix_minflt;
+ long long fix_cminflt;
+ long long fix_majflt;
+ long long fix_cmajflt;
+ long long fix_utime;
+ long long fix_stime;
+ long long fix_cutime;
+ long long fix_cstime;
unsigned long long statm_size;
unsigned long long statm_resident;
}
uint32_t hash = simple_hash(id);
- struct target *w;
+ struct target *w, *last = apps_groups_root_target;
for(w = apps_groups_root_target ; w ; w = w->next) {
if(w->idhash == hash && strncmp(nid, w->id, MAX_NAME) == 0)
return w;
+
+ last = w;
}
w = calloc(sizeof(struct target), 1);
w->debug = tdebug;
w->target = target;
- w->next = apps_groups_root_target;
- apps_groups_root_target = w;
+ // append it, to maintain the order in apps_groups.conf
+ if(last) last->next = w;
+ else apps_groups_root_target = w;
if(unlikely(debug))
fprintf(stderr, "apps.plugin: ADDING TARGET ID '%s', process name '%s' (%s), aggregated on target '%s', options: %s %s\n"
// we will subtract these values from the old
// target
unsigned long long last_minflt;
- unsigned long long last_cminflt;
unsigned long long last_majflt;
- unsigned long long last_cmajflt;
unsigned long long last_utime;
unsigned long long last_stime;
+
+ unsigned long long last_cminflt;
+ unsigned long long last_cmajflt;
unsigned long long last_cutime;
unsigned long long last_cstime;
+ unsigned long long last_fix_cminflt;
+ unsigned long long last_fix_cmajflt;
+ unsigned long long last_fix_cutime;
+ unsigned long long last_fix_cstime;
+
unsigned long long last_io_logical_bytes_read;
unsigned long long last_io_logical_bytes_written;
unsigned long long last_io_read_calls;
unsigned long long last_io_storage_bytes_written;
unsigned long long last_io_cancelled_write_bytes;
-#ifdef AGGREGATE_CHILDREN_TO_PARENTS
- unsigned long long old_utime;
- unsigned long long old_stime;
- unsigned long long old_minflt;
- unsigned long long old_majflt;
-
- unsigned long long old_cutime;
- unsigned long long old_cstime;
- unsigned long long old_cminflt;
- unsigned long long old_cmajflt;
-
- unsigned long long fix_cutime;
- unsigned long long fix_cstime;
unsigned long long fix_cminflt;
unsigned long long fix_cmajflt;
-
- unsigned long long diff_cutime;
- unsigned long long diff_cstime;
- unsigned long long diff_cminflt;
- unsigned long long diff_cmajflt;
-#endif /* AGGREGATE_CHILDREN_TO_PARENTS */
+ unsigned long long fix_cutime;
+ unsigned long long fix_cstime;
int *fds; // array of fds it uses
int fds_size; // the size of the fds array
{
if(!all_pids[pid]) return;
- if(debug) fprintf(stderr, "apps.plugin: process %d %s exited, deleting it.\n", pid, all_pids[pid]->comm);
+ if(unlikely(debug))
+ fprintf(stderr, "apps.plugin: process %d %s exited, deleting it.\n", pid, all_pids[pid]->comm);
if(root_of_pids == all_pids[pid]) root_of_pids = all_pids[pid]->next;
if(all_pids[pid]->next) all_pids[pid]->next->prev = all_pids[pid]->prev;
// p->guest_time = strtoull(procfile_lineword(ff, 0, 42+i), NULL, 10);
// p->cguest_time = strtoull(procfile_lineword(ff, 0, 43), NULL, 10);
- if(debug || (p->target && p->target->debug))
+ if(unlikely(debug || (p->target && p->target->debug)))
fprintf(stderr, "apps.plugin: READ PROC/PID/STAT: %s/proc/%d/stat, process: '%s' VALUES: utime=%llu, stime=%llu, cutime=%llu, cstime=%llu, minflt=%llu, majflt=%llu, cminflt=%llu, cmajflt=%llu, threads=%d\n", host_prefix, p->pid, p->comm, p->utime, p->stime, p->cutime, p->cstime, p->minflt, p->majflt, p->cminflt, p->cmajflt, p->num_threads);
// procfile_close(ff);
}
#endif /* NETDATA_INTERNAL_CHECKS */
- if(debug) fprintf(stderr, "apps.plugin: decreasing slot %d (count = %d).\n", id, all_files[id].count);
+ if(unlikely(debug))
+ fprintf(stderr, "apps.plugin: decreasing slot %d (count = %d).\n", id, all_files[id].count);
if(all_files[id].count > 0) {
all_files[id].count--;
if(!all_files[id].count) {
- if(debug) fprintf(stderr, "apps.plugin: >> slot %d is empty.\n", id);
+ if(unlikely(debug))
+ fprintf(stderr, "apps.plugin: >> slot %d is empty.\n", id);
+
file_descriptor_remove(&all_files[id]);
#ifdef NETDATA_INTERNAL_CHECKS
all_files[id].magic = 0x00000000;
static int last_pos = 0;
uint32_t hash = simple_hash(name);
- if(debug) fprintf(stderr, "apps.plugin: adding or finding name '%s' with hash %u\n", name, hash);
+ if(unlikely(debug))
+ fprintf(stderr, "apps.plugin: adding or finding name '%s' with hash %u\n", name, hash);
struct file_descriptor *fd = file_descriptor_find(name, hash);
if(fd) {
// found
- if(debug) fprintf(stderr, "apps.plugin: >> found on slot %d\n", fd->pos);
+ if(unlikely(debug))
+ fprintf(stderr, "apps.plugin: >> found on slot %d\n", fd->pos);
+
fd->count++;
return fd->pos;
}
int i;
// there is no empty slot
- if(debug) fprintf(stderr, "apps.plugin: extending fd array to %d entries\n", all_files_size + FILE_DESCRIPTORS_INCREASE_STEP);
+ if(unlikely(debug))
+ fprintf(stderr, "apps.plugin: extending fd array to %d entries\n", all_files_size + FILE_DESCRIPTORS_INCREASE_STEP);
+
all_files = realloc(all_files, (all_files_size + FILE_DESCRIPTORS_INCREASE_STEP) * sizeof(struct file_descriptor));
// if the address changed, we have to rebuild the index
// since all pointers are now invalid
if(old && old != (void *)all_files) {
- if(debug) fprintf(stderr, "apps.plugin: >> re-indexing.\n");
+ if(unlikely(debug))
+ fprintf(stderr, "apps.plugin: >> re-indexing.\n");
+
all_files_index.root = NULL;
for(i = 0; i < all_files_size; i++) {
if(!all_files[i].count) continue;
file_descriptor_add(&all_files[i]);
}
- if(debug) fprintf(stderr, "apps.plugin: >> re-indexing done.\n");
+
+ if(unlikely(debug))
+ fprintf(stderr, "apps.plugin: >> re-indexing done.\n");
}
for(i = all_files_size; i < (all_files_size + FILE_DESCRIPTORS_INCREASE_STEP); i++) {
all_files_size += FILE_DESCRIPTORS_INCREASE_STEP;
}
- if(debug) fprintf(stderr, "apps.plugin: >> searching for empty slot.\n");
+ if(unlikely(debug))
+ fprintf(stderr, "apps.plugin: >> searching for empty slot.\n");
// search for an empty slot
int i, c;
if(c == 0) continue;
if(!all_files[c].count) {
- if(debug) fprintf(stderr, "apps.plugin: >> Examining slot %d.\n", c);
+ if(unlikely(debug))
+ fprintf(stderr, "apps.plugin: >> Examining slot %d.\n", c);
#ifdef NETDATA_INTERNAL_CHECKS
if(all_files[c].magic == 0x0BADCAFE && all_files[c].name && file_descriptor_find(all_files[c].name, all_files[c].hash))
error("fd on position %d is not cleared properly. It still has %s in it.\n", c, all_files[c].name);
#endif /* NETDATA_INTERNAL_CHECKS */
- if(debug) fprintf(stderr, "apps.plugin: >> %s fd position %d for %s (last name: %s)\n", all_files[c].name?"re-using":"using", c, name, all_files[c].name);
+ if(unlikely(debug))
+ fprintf(stderr, "apps.plugin: >> %s fd position %d for %s (last name: %s)\n", all_files[c].name?"re-using":"using", c, name, all_files[c].name);
+
if(all_files[c].name) free((void *)all_files[c].name);
all_files[c].name = NULL;
last_pos = c;
fatal("We should find an empty slot, but there isn't any");
exit(1);
}
- if(debug) fprintf(stderr, "apps.plugin: >> updating slot %d.\n", c);
+
+ if(unlikely(debug))
+ fprintf(stderr, "apps.plugin: >> updating slot %d.\n", c);
all_files_len++;
else if(strcmp(name, "anon_inode:[timerfd]") == 0) type = FILETYPE_TIMERFD;
else if(strcmp(name, "anon_inode:[signalfd]") == 0) type = FILETYPE_SIGNALFD;
else if(strncmp(name, "anon_inode:", 11) == 0) {
- if(debug) fprintf(stderr, "apps.plugin: FIXME: unknown anonymous inode: %s\n", name);
+ if(unlikely(debug))
+ fprintf(stderr, "apps.plugin: FIXME: unknown anonymous inode: %s\n", name);
+
type = FILETYPE_OTHER;
}
else {
- if(debug) fprintf(stderr, "apps.plugin: FIXME: cannot understand linkname: %s\n", name);
+ if(unlikely(debug))
+ fprintf(stderr, "apps.plugin: FIXME: cannot understand linkname: %s\n", name);
+
type = FILETYPE_OTHER;
}
#endif /* NETDATA_INTERNAL_CHECKS */
file_descriptor_add(&all_files[c]);
- if(debug) fprintf(stderr, "apps.plugin: using fd position %d (name: %s)\n", c, all_files[c].name);
+ if(unlikely(debug))
+ fprintf(stderr, "apps.plugin: using fd position %d (name: %s)\n", c, all_files[c].name);
return c;
}
if(fdid < 0) continue;
if(fdid >= p->fds_size) {
// it is small, extend it
- if(debug) fprintf(stderr, "apps.plugin: extending fd memory slots for %s from %d to %d\n", p->comm, p->fds_size, fdid + 100);
+ if(unlikely(debug))
+ fprintf(stderr, "apps.plugin: extending fd memory slots for %s from %d to %d\n", p->comm, p->fds_size, fdid + 100);
+
p->fds = realloc(p->fds, (fdid + 100) * sizeof(int));
if(!p->fds) {
fatal("Cannot re-allocate fds for %s", p->comm);
all_pids_count = 0;
for(p = root_of_pids; p ; p = p->next) {
all_pids_count++;
- p->parent = NULL;
- p->updated = 0;
- p->children_count = 0;
- p->merged = 0;
- p->new_entry = 0;
-
- p->last_minflt = p->minflt;
- p->last_cminflt = p->cminflt;
- p->last_majflt = p->majflt;
- p->last_cmajflt = p->cmajflt;
- p->last_utime = p->utime;
- p->last_stime = p->stime;
- p->last_cutime = p->cutime;
- p->last_cstime = p->cstime;
-
- p->last_io_logical_bytes_read = p->io_logical_bytes_read;
+
+ p->parent = NULL;
+
+ p->updated = 0;
+ p->children_count = 0;
+ p->merged = 0;
+ p->new_entry = 0;
+
+ p->last_minflt = p->minflt;
+ p->last_majflt = p->majflt;
+ p->last_utime = p->utime;
+ p->last_stime = p->stime;
+
+ p->last_cminflt = p->cminflt;
+ p->last_cmajflt = p->cmajflt;
+ p->last_cutime = p->cutime;
+ p->last_cstime = p->cstime;
+
+ p->last_fix_cminflt = p->fix_cminflt;
+ p->last_fix_cmajflt = p->fix_cmajflt;
+ p->last_fix_cutime = p->fix_cutime;
+ p->last_fix_cstime = p->fix_cstime;
+
+ p->last_io_logical_bytes_read = p->io_logical_bytes_read;
p->last_io_logical_bytes_written = p->io_logical_bytes_written;
- p->last_io_read_calls = p->io_read_calls;
- p->last_io_write_calls = p->io_write_calls;
- p->last_io_storage_bytes_read = p->io_storage_bytes_read;
+ p->last_io_read_calls = p->io_read_calls;
+ p->last_io_write_calls = p->io_write_calls;
+ p->last_io_storage_bytes_read = p->io_storage_bytes_read;
p->last_io_storage_bytes_written = p->io_storage_bytes_written;
p->last_io_cancelled_write_bytes = p->io_cancelled_write_bytes;
}
pid_t pid = (pid_t) strtoul(file->d_name, &endptr, 10);
// make sure we read a valid number
- if(unlikely(pid <= 0 || pid > pid_max || endptr == file->d_name || *endptr != '\0'))
+ if(unlikely(endptr == file->d_name || *endptr != '\0'))
continue;
+ if(unlikely(pid <= 0 || pid > pid_max)) {
+ error("Invalid pid %d read (expected 1 to %d). Ignoring process.", pid, pid_max);
+ continue;
+ }
+
p = get_pid_entry(pid);
if(unlikely(!p)) continue;
// /proc/<pid>/stat
if(unlikely(read_proc_pid_stat(p))) {
- error("Cannot process %s/proc/%d/stat", host_prefix, pid);
-
+ error("Cannot process %s/proc/%d/stat", host_prefix, pid);
// there is no reason to proceed if we cannot get its status
continue;
}
// check its parent pid
if(unlikely(p->ppid < 0 || p->ppid > pid_max)) {
- error("Pid %d states invalid parent pid %d. Using 0.", pid, p->ppid);
-
+ error("Pid %d states invalid parent pid %d. Using 0.", pid, p->ppid);
p->ppid = 0;
}
- // --------------------------------------------------------------------
- // /proc/<pid>/cmdline
-
- if(proc_pid_cmdline_is_needed) {
- if(unlikely(read_proc_pid_cmdline(p))) {
- error("Cannot process %s/proc/%d/cmdline", host_prefix, pid);
- }
- }
-
// --------------------------------------------------------------------
// /proc/<pid>/statm
if(unlikely(read_proc_pid_statm(p))) {
- error("Cannot process %s/proc/%d/statm", host_prefix, pid);
-
+ error("Cannot process %s/proc/%d/statm", host_prefix, pid);
// there is no reason to proceed if we cannot get its memory status
continue;
}
// check if it is target
// we do this only once, the first time this pid is loaded
if(unlikely(p->new_entry)) {
- if(debug) fprintf(stderr, "apps.plugin: \tJust added %s\n", p->comm);
+ // /proc/<pid>/cmdline
+ if(proc_pid_cmdline_is_needed) {
+ if(unlikely(read_proc_pid_cmdline(p))) {
+ error("Cannot process %s/proc/%d/cmdline", host_prefix, pid);
+ }
+ }
+
+ if(unlikely(debug))
+ fprintf(stderr, "apps.plugin: \tJust added %d (%s)\n", pid, p->comm);
+
uint32_t hash = simple_hash(p->comm);
- size_t pclen = strlen(p->comm);
+ size_t pclen = strlen(p->comm);
struct target *w;
for(w = apps_groups_root_target; w ; w = w->next) {
if(debug || (p->target && p->target->debug))
fprintf(stderr, "apps.plugin: \t\t%s linked to target %s\n", p->comm, p->target->name);
+
+ break;
}
}
}
return 1;
}
-
-// ----------------------------------------------------------------------------
-
-#ifdef AGGREGATE_CHILDREN_TO_PARENTS
-// print a tree view of all processes
-int debug_childrens_aggregations(pid_t pid, int level) {
- struct pid_stat *p = NULL;
- char b[level+3];
- int i, ret = 0;
-
- for(i = 0; i < level; i++) b[i] = '\t';
- b[level] = '|';
- b[level+1] = '-';
- b[level+2] = '\0';
-
- for(p = root_of_pids; p ; p = p->next) {
- if(p->ppid == pid) {
- ret += debug_childrens_aggregations(p->pid, level+1);
- }
- }
-
- p = all_pids[pid];
- if(p) {
- if(!p->updated) ret += 1;
- if(ret) fprintf(stderr, "%s %s %d [%s, %s] c=%d u=%llu+%llu, s=%llu+%llu, cu=%llu+%llu, cs=%llu+%llu, n=%llu+%llu, j=%llu+%llu, cn=%llu+%llu, cj=%llu+%llu\n"
- , b, p->comm, p->pid, p->updated?"OK":"KILLED", p->target->name, p->children_count
- , p->utime, p->utime - p->old_utime
- , p->stime, p->stime - p->old_stime
- , p->cutime, p->cutime - p->old_cutime
- , p->cstime, p->cstime - p->old_cstime
- , p->minflt, p->minflt - p->old_minflt
- , p->majflt, p->majflt - p->old_majflt
- , p->cminflt, p->cminflt - p->old_cminflt
- , p->cmajflt, p->cmajflt - p->old_cmajflt
- );
- }
-
- return ret;
-}
-#endif /* AGGREGATE_CHILDREN_TO_PARENTS */
-
-
-
// ----------------------------------------------------------------------------
// update statistics on the targets
// check: update_apps_groups_statistics()
void link_all_processes_to_their_parents(void) {
+ struct pid_stat *init = all_pids[1];
struct pid_stat *p = NULL;
// link all children to their parents
for(p = root_of_pids; p ; p = p->next) {
// for each process found running
- if(p->ppid > 0
- && p->ppid <= pid_max
- && all_pids[p->ppid]
- ) {
- // for valid processes
+ if(likely(p->new_entry && p->updated)) {
+ // the first time we see an entry
+ // we remove the exited children figures
+ // to avoid spikes
+ p->fix_cminflt = p->cminflt;
+ p->fix_cmajflt = p->cmajflt;
+ p->fix_cutime = p->cutime;
+ p->fix_cstime = p->cstime;
+ }
+
+ if(likely(p->ppid > 0 && all_pids[p->ppid])) {
+ // valid parent processes
- if(debug || (p->target && p->target->debug))
- fprintf(stderr, "apps.plugin: \tparent of %d (%s) is %d (%s)\n", p->pid, p->comm, p->ppid, all_pids[p->ppid]->comm);
+ struct pid_stat *pp;
- p->parent = all_pids[p->ppid];
+ p->parent = pp = all_pids[p->ppid];
p->parent->children_count++;
- }
- else if(p->ppid != 0)
- error("pid %d %s states parent %d, but the later does not exist.", p->pid, p->comm, p->ppid);
- }
-}
-#ifdef AGGREGATE_CHILDREN_TO_PARENTS
-void aggregate_children_to_parents(void) {
- struct pid_stat *p = NULL;
+ if(unlikely(debug || (p->target && p->target->debug)))
+ fprintf(stderr, "apps.plugin: \tchild %d (%s, %s) has parent %d (%s, %s). Parent: utime=%llu, stime=%llu, minflt=%llu, majflt=%llu, cutime=%llu, cstime=%llu, cminflt=%llu, cmajflt=%llu, fix_cutime=%llu, fix_cstime=%llu, fix_cminflt=%llu, fix_cmajflt=%llu\n", p->pid, p->comm, p->updated?"running":"exited", pp->pid, pp->comm, pp->updated?"running":"exited", pp->utime, pp->stime, pp->minflt, pp->majflt, pp->cutime, pp->cstime, pp->cminflt, pp->cmajflt, pp->fix_cutime, pp->fix_cstime, pp->fix_cminflt, pp->fix_cmajflt);
- // for each killed process, remove its values from the parents
- // sums (we had already added them in a previous loop)
- for(p = root_of_pids; p ; p = p->next) {
- if(p->updated) continue;
-
- if(debug) fprintf(stderr, "apps.plugin: UNMERGING %d %s\n", p->pid, p->comm);
-
- unsigned long long diff_utime = p->utime + p->cutime + p->fix_cutime;
- unsigned long long diff_stime = p->stime + p->cstime + p->fix_cstime;
- unsigned long long diff_minflt = p->minflt + p->cminflt + p->fix_cminflt;
- unsigned long long diff_majflt = p->majflt + p->cmajflt + p->fix_cmajflt;
-
- struct pid_stat *t = p;
- while((t = t->parent)) {
- if(!t->updated) continue;
-
- unsigned long long x;
- if(diff_utime && t->diff_cutime) {
- x = (t->diff_cutime < diff_utime)?t->diff_cutime:diff_utime;
- diff_utime -= x;
- t->diff_cutime -= x;
- t->fix_cutime += x;
- if(debug) fprintf(stderr, "apps.plugin: \t cutime %llu from %d %s %s\n", x, t->pid, t->comm, t->target->name);
- }
- if(diff_stime && t->diff_cstime) {
- x = (t->diff_cstime < diff_stime)?t->diff_cstime:diff_stime;
- diff_stime -= x;
- t->diff_cstime -= x;
- t->fix_cstime += x;
- if(debug) fprintf(stderr, "apps.plugin: \t cstime %llu from %d %s %s\n", x, t->pid, t->comm, t->target->name);
- }
- if(diff_minflt && t->diff_cminflt) {
- x = (t->diff_cminflt < diff_minflt)?t->diff_cminflt:diff_minflt;
- diff_minflt -= x;
- t->diff_cminflt -= x;
- t->fix_cminflt += x;
- if(debug) fprintf(stderr, "apps.plugin: \t cminflt %llu from %d %s %s\n", x, t->pid, t->comm, t->target->name);
- }
- if(diff_majflt && t->diff_cmajflt) {
- x = (t->diff_cmajflt < diff_majflt)?t->diff_cmajflt:diff_majflt;
- diff_majflt -= x;
- t->diff_cmajflt -= x;
- t->fix_cmajflt += x;
- if(debug) fprintf(stderr, "apps.plugin: \t cmajflt %llu from %d %s %s\n", x, t->pid, t->comm, t->target->name);
+ if(unlikely(!p->updated)) {
+ // this process has exit
+
+ // find the first parent that has been updated
+ while(pp && !pp->updated) {
+ // we may have to forward link it to its parent
+ if(unlikely(!pp->parent && pp->ppid > 0 && all_pids[pp->ppid]))
+ pp->parent = all_pids[pp->ppid];
+
+ // check again for parent
+ pp = pp->parent;
+ }
+
+ if(likely(pp)) {
+ // this is an exited child with a parent
+ // remove the known time from the parent's data
+ pp->fix_cminflt += p->last_minflt + p->last_cminflt + p->last_fix_cminflt;
+ pp->fix_cmajflt += p->last_majflt + p->last_cmajflt + p->last_fix_cmajflt;
+ pp->fix_cutime += p->last_utime + p->last_cutime + p->last_fix_cutime;
+ pp->fix_cstime += p->last_stime + p->last_cstime + p->last_fix_cstime;
+
+ // The known exited children (the ones we track) may have
+ // contributed more than the value accumulated into the process
+ // by the kernel.
+ // This can happen if the parent process has not waited-for
+ // its children (check: man 2 times).
+ // In this case, the kernel adds these resources to init (pid 1).
+ //
+ // The following code, attempts to fix this.
+ // Without this code, the charts will have random spikes
+ // for example, when an SSH session ends (sshd forks a child
+ // to serve the session, but when this session ends, sshd
+ // does not wait-for its child, thus all the resources of the
+ // ssh session get added to init, resulting in a huge spike on
+ // the charts).
+
+ if(unlikely(pp->cminflt < pp->fix_cminflt)) {
+ if(likely(init && pp != init)) {
+ unsigned long long have = pp->fix_cminflt - pp->cminflt;
+ unsigned long long max = init->cminflt - init->fix_cminflt;
+ if(have > max) have = max;
+ init->fix_cminflt += have;
+ }
+ pp->fix_cminflt = pp->cminflt;
+ }
+ if(unlikely(pp->cmajflt < pp->fix_cmajflt)) {
+ if(likely(init && pp != init)) {
+ unsigned long long have = pp->fix_cmajflt - pp->cmajflt;
+ unsigned long long max = init->cmajflt - init->fix_cmajflt;
+ if(have > max) have = max;
+ init->fix_cmajflt += have;
+ }
+ pp->fix_cmajflt = pp->cmajflt;
+ }
+ if(unlikely(pp->cutime < pp->fix_cutime)) {
+ if(likely(init && pp != init)) {
+ unsigned long long have = pp->fix_cutime - pp->cutime;
+ unsigned long long max = init->cutime - init->fix_cutime;
+ if(have > max) have = max;
+ init->fix_cutime += have;
+ }
+ pp->fix_cutime = pp->cutime;
+ }
+ if(unlikely(pp->cstime < pp->fix_cstime)) {
+ if(likely(init && pp != init)) {
+ unsigned long long have = pp->fix_cstime - pp->cstime;
+ unsigned long long max = init->cstime - init->fix_cstime;
+ if(have > max) have = max;
+ init->fix_cstime += have;
+ }
+ pp->fix_cstime = pp->cstime;
+ }
+
+ if(unlikely(debug))
+ fprintf(stderr, "apps.plugin: \tupdating child metrics of %d (%s, %s) to its parent %d (%s, %s). Parent has now: utime=%llu, stime=%llu, minflt=%llu, majflt=%llu, cutime=%llu, cstime=%llu, cminflt=%llu, cmajflt=%llu, fix_cutime=%llu, fix_cstime=%llu, fix_cminflt=%llu, fix_cmajflt=%llu\n", p->pid, p->comm, p->updated?"running":"exited", pp->pid, pp->comm, pp->updated?"running":"exited", pp->utime, pp->stime, pp->minflt, pp->majflt, pp->cutime, pp->cstime, pp->cminflt, pp->cmajflt, pp->fix_cutime, pp->fix_cstime, pp->fix_cminflt, pp->fix_cmajflt);
+ }
}
}
-
- if(diff_utime) error("Cannot fix up utime %llu", diff_utime);
- if(diff_stime) error("Cannot fix up stime %llu", diff_stime);
- if(diff_minflt) error("Cannot fix up minflt %llu", diff_minflt);
- if(diff_majflt) error("Cannot fix up majflt %llu", diff_majflt);
+ else if(unlikely(p->ppid != 0))
+ error("pid %d %s states parent %d, but the later does not exist.", p->pid, p->comm, p->ppid);
}
}
-#endif /* AGGREGATE_CHILDREN_TO_PARENTS */
+
void cleanup_non_existing_pids(void) {
int c;
// children that do not have a target
// inherit their target from their parent
- int found = 1;
+ int found = 1, loops = 0;
while(found) {
+ if(unlikely(debug)) loops++;
found = 0;
for(p = root_of_pids; p ; p = p->next) {
// if this process does not have a target
// repeat, until nothing more can be done.
found = 1;
while(found) {
+ if(unlikely(debug)) loops++;
found = 0;
for(p = root_of_pids; p ; p = p->next) {
// if this process does not have any children
}
}
- if(debug)
+ if(unlikely(debug))
fprintf(stderr, "apps.plugin: merged %d processes\n", found);
}
all_pids[1]->target = apps_groups_default_target;
// give a default target on all top level processes
+ if(unlikely(debug)) loops++;
for(p = root_of_pids; p ; p = p->next) {
// if the process is not merged itself
// then is is a top level process
if(!p->merged && !p->target)
p->target = apps_groups_default_target;
-
-#ifdef AGGREGATE_CHILDREN_TO_PARENTS
- // by the way, update the diffs
- // will be used later for subtracting killed process times
- p->diff_cutime = p->utime - p->cutime;
- p->diff_cstime = p->stime - p->cstime;
- p->diff_cminflt = p->minflt - p->cminflt;
- p->diff_cmajflt = p->majflt - p->cmajflt;
-#endif /* AGGREGATE_CHILDREN_TO_PARENTS */
}
// give a target to all merged child processes
found = 1;
while(found) {
+ if(unlikely(debug)) loops++;
found = 0;
for(p = root_of_pids; p ; p = p->next) {
if(unlikely(!p->target && p->merged && p->parent && p->parent->target)) {
}
}
}
+
+ if(unlikely(debug))
+ fprintf(stderr, "apps.plugin: apply_apps_groups_targets_inheritance() made %d loops on the process tree\n", loops);
}
long zero_all_targets(struct target *root) {
}
if(likely(p->updated)) {
- w->cutime += p->cutime; // - p->fix_cutime;
- w->cstime += p->cstime; // - p->fix_cstime;
- w->cminflt += p->cminflt; // - p->fix_cminflt;
- w->cmajflt += p->cmajflt; // - p->fix_cmajflt;
+ if(unlikely(debug && (p->fix_cutime || p->fix_cstime || p->fix_cminflt || p->fix_cmajflt)))
+ fprintf(stderr, "apps.plugin: \tadding child counters of %d (%s) to target %s. Currents: cutime=%llu, cstime=%llu, cminflt=%llu, cmajflt=%llu, Fixes: cutime=%llu, cstime=%llu, cminflt=%llu, cmajflt=%llu\n", p->pid, p->comm, w->name, p->cutime, p->cstime, p->cminflt, p->cmajflt, p->fix_cutime, p->fix_cstime, p->fix_cminflt, p->fix_cmajflt);
+
+ w->cutime += p->cutime - p->fix_cutime;
+ w->cstime += p->cstime - p->fix_cstime;
+ w->cminflt += p->cminflt - p->fix_cminflt;
+ w->cmajflt += p->cmajflt - p->fix_cmajflt;
w->utime += p->utime; //+ (p->pid != 1)?(p->cutime - p->fix_cutime):0;
w->stime += p->stime; //+ (p->pid != 1)?(p->cstime - p->fix_cstime):0;
}
if(unlikely(debug || w->debug))
- fprintf(stderr, "apps.plugin: \tAggregating %s pid %d on %s utime=%llu, stime=%llu, cutime=%llu, cstime=%llu, minflt=%llu, majflt=%llu, cminflt=%llu, cmajflt=%llu\n", p->comm, p->pid, w->name, p->utime, p->stime, p->cutime, p->cstime, p->minflt, p->majflt, p->cminflt, p->cmajflt);
+ fprintf(stderr, "apps.plugin: \tAggregating %s pid %d on %s utime=%llu, stime=%llu, cutime=%llu, cstime=%llu, minflt=%llu, majflt=%llu, cminflt=%llu, cmajflt=%llu, fix_cutime=%llu, fix_cstime=%llu, fix_cminflt=%llu, fix_cmajflt=%llu\n", p->comm, p->pid, w->name, p->utime, p->stime, p->cutime, p->cstime, p->minflt, p->majflt, p->cminflt, p->cmajflt, p->fix_cutime, p->fix_cstime, p->fix_cminflt, p->fix_cmajflt);
/* if(p->utime - p->old_utime > 100) fprintf(stderr, "BIG CHANGE: %d %s utime increased by %llu from %llu to %llu\n", p->pid, p->comm, p->utime - p->old_utime, p->old_utime, p->utime);
if(p->cutime - p->old_cutime > 100) fprintf(stderr, "BIG CHANGE: %d %s cutime increased by %llu from %llu to %llu\n", p->pid, p->comm, p->cutime - p->old_cutime, p->old_cutime, p->cutime);
if(p->cminflt - p->old_cminflt > 15000) fprintf(stderr, "BIG CHANGE: %d %s cminflt increased by %llu from %llu to %llu\n", p->pid, p->comm, p->cminflt - p->old_cminflt, p->old_cminflt, p->cminflt);
if(p->cmajflt - p->old_cmajflt > 15000) fprintf(stderr, "BIG CHANGE: %d %s cmajflt increased by %llu from %llu to %llu\n", p->pid, p->comm, p->cmajflt - p->old_cmajflt, p->old_cmajflt, p->cmajflt);
*/
-#ifdef AGGREGATE_CHILDREN_TO_PARENTS
- p->old_utime = p->utime;
- p->old_cutime = p->cutime;
- p->old_stime = p->stime;
- p->old_cstime = p->cstime;
- p->old_minflt = p->minflt;
- p->old_majflt = p->majflt;
- p->old_cminflt = p->cminflt;
- p->old_cmajflt = p->cmajflt;
-#endif /* AGGREGATE_CHILDREN_TO_PARENTS */
if(o) {
// since the process switched target
// IMPORTANT
// We add/subtract the last/OLD values we added to the target
- w->fix_cutime -= p->last_cutime;
- w->fix_cstime -= p->last_cstime;
- w->fix_cminflt -= p->last_cminflt;
- w->fix_cmajflt -= p->last_cmajflt;
+ unsigned long long cutime = p->last_cutime - p->last_fix_cutime;
+ unsigned long long cstime = p->last_cstime - p->last_fix_cstime;
+ unsigned long long cminflt = p->last_cminflt - p->last_fix_cminflt;
+ unsigned long long cmajflt = p->last_cmajflt - p->last_fix_cmajflt;
+
+ w->fix_cutime -= cutime;
+ w->fix_cstime -= cstime;
+ w->fix_cminflt -= cminflt;
+ w->fix_cmajflt -= cmajflt;
- w->fix_utime -= p->last_utime;
- w->fix_stime -= p->last_stime;
+ w->fix_utime -= p->last_utime;
+ w->fix_stime -= p->last_stime;
w->fix_minflt -= p->last_minflt;
w->fix_majflt -= p->last_majflt;
-
- w->fix_io_logical_bytes_read -= p->last_io_logical_bytes_read;
+ w->fix_io_logical_bytes_read -= p->last_io_logical_bytes_read;
w->fix_io_logical_bytes_written -= p->last_io_logical_bytes_written;
- w->fix_io_read_calls -= p->last_io_read_calls;
- w->fix_io_write_calls -= p->last_io_write_calls;
- w->fix_io_storage_bytes_read -= p->last_io_storage_bytes_read;
+ w->fix_io_read_calls -= p->last_io_read_calls;
+ w->fix_io_write_calls -= p->last_io_write_calls;
+ w->fix_io_storage_bytes_read -= p->last_io_storage_bytes_read;
w->fix_io_storage_bytes_written -= p->last_io_storage_bytes_written;
w->fix_io_cancelled_write_bytes -= p->last_io_cancelled_write_bytes;
// ---
- o->fix_cutime += p->last_cutime;
- o->fix_cstime += p->last_cstime;
- o->fix_cminflt += p->last_cminflt;
- o->fix_cmajflt += p->last_cmajflt;
+ o->fix_cutime += cutime;
+ o->fix_cstime += cstime;
+ o->fix_cminflt += cminflt;
+ o->fix_cmajflt += cmajflt;
- o->fix_utime += p->last_utime;
- o->fix_stime += p->last_stime;
+ o->fix_utime += p->last_utime;
+ o->fix_stime += p->last_stime;
o->fix_minflt += p->last_minflt;
o->fix_majflt += p->last_majflt;
- o->fix_io_logical_bytes_read += p->last_io_logical_bytes_read;
+ o->fix_io_logical_bytes_read += p->last_io_logical_bytes_read;
o->fix_io_logical_bytes_written += p->last_io_logical_bytes_written;
- o->fix_io_read_calls += p->last_io_read_calls;
- o->fix_io_write_calls += p->last_io_write_calls;
- o->fix_io_storage_bytes_read += p->last_io_storage_bytes_read;
+ o->fix_io_read_calls += p->last_io_read_calls;
+ o->fix_io_write_calls += p->last_io_write_calls;
+ o->fix_io_storage_bytes_read += p->last_io_storage_bytes_read;
o->fix_io_storage_bytes_written += p->last_io_storage_bytes_written;
o->fix_io_cancelled_write_bytes += p->last_io_cancelled_write_bytes;
}
// since the process has exited, the user
// will see a drop in our charts, because the incremental
- // values of this process will not be there
+ // values of this process will not be there from now on
// add them to the fix_* values and they will be added to
// the reported values, so that the report goes steady
- w->fix_minflt += p->minflt;
- w->fix_majflt += p->majflt;
- w->fix_utime += p->utime;
- w->fix_stime += p->stime;
- w->fix_cminflt += p->cminflt;
- w->fix_cmajflt += p->cmajflt;
- w->fix_cutime += p->cutime;
- w->fix_cstime += p->cstime;
-
- w->fix_io_logical_bytes_read += p->io_logical_bytes_read;
- w->fix_io_logical_bytes_written += p->io_logical_bytes_written;
- w->fix_io_read_calls += p->io_read_calls;
- w->fix_io_write_calls += p->io_write_calls;
- w->fix_io_storage_bytes_read += p->io_storage_bytes_read;
- w->fix_io_storage_bytes_written += p->io_storage_bytes_written;
- w->fix_io_cancelled_write_bytes += p->io_cancelled_write_bytes;
+
+ w->fix_minflt += p->last_minflt;
+ w->fix_majflt += p->last_majflt;
+ w->fix_utime += p->last_utime;
+ w->fix_stime += p->last_stime;
+
+ w->fix_cminflt += (p->last_cminflt - p->last_fix_cminflt);
+ w->fix_cmajflt += (p->last_cmajflt - p->last_fix_cmajflt);
+ w->fix_cutime += (p->last_cutime - p->last_fix_cutime);
+ w->fix_cstime += (p->last_cstime - p->last_fix_cstime);
+
+ w->fix_io_logical_bytes_read += p->last_io_logical_bytes_read;
+ w->fix_io_logical_bytes_written += p->last_io_logical_bytes_written;
+ w->fix_io_read_calls += p->last_io_read_calls;
+ w->fix_io_write_calls += p->last_io_write_calls;
+ w->fix_io_storage_bytes_read += p->last_io_storage_bytes_read;
+ w->fix_io_storage_bytes_written += p->last_io_storage_bytes_written;
+ w->fix_io_cancelled_write_bytes += p->last_io_cancelled_write_bytes;
}
+ //if((long long)w->cutime + w->fix_cutime < 0)
+ // error("Negative total cutime (%llu - %lld) on target %s after adding process %d (%s, %s) with utime=%llu, stime=%llu, minflt=%llu, majflt=%llu, cutime=%llu, cstime=%llu, cminflt=%llu, cmajflt=%llu, fix_cutime=%llu, fix_cstime=%llu, fix_cminflt=%llu, fix_cmajflt=%llu\n",
+ // w->cutime, w->fix_cutime, w->name, p->pid, p->comm, p->updated?"running":"exited", p->utime, p->stime, p->minflt, p->majflt, p->cutime, p->cstime, p->cminflt, p->cmajflt, p->fix_cutime, p->fix_cstime, p->fix_cminflt, p->fix_cmajflt);
}
void count_targets_fds(struct target *root) {
link_all_processes_to_their_parents();
apply_apps_groups_targets_inheritance();
-#ifdef AGGREGATE_CHILDREN_TO_PARENTS
- aggregate_children_to_parents();
-#endif /* AGGREGATE_CHILDREN_TO_PARENTS */
-
zero_all_targets(users_root_target);
zero_all_targets(groups_root_target);
apps_groups_targets = zero_all_targets(apps_groups_root_target);
-#ifdef AGGREGATE_CHILDREN_TO_PARENTS
- if(debug)
- debug_childrens_aggregations(0, 1);
-#endif /* AGGREGATE_CHILDREN_TO_PARENTS */
-
// this has to be done, before the cleanup
struct pid_stat *p = NULL;
struct target *w = NULL, *o = NULL;
for (w = root; w ; w = w->next) {
if(w->target || (!w->processes && !w->exposed)) continue;
- fprintf(stdout, "SET %s = %llu\n", w->name, w->utime + w->stime + w->fix_utime + w->fix_stime);
+ fprintf(stdout, "SET %s = %llu\n", w->name, w->utime + w->stime + w->fix_utime + w->fix_stime + (include_exited_childs?(w->cutime + w->cstime + w->fix_cutime + w->fix_cstime):0));
}
fprintf(stdout, "END\n");
for (w = root; w ; w = w->next) {
if(w->target || (!w->processes && !w->exposed)) continue;
- fprintf(stdout, "SET %s = %llu\n", w->name, w->utime + w->fix_utime);
+ fprintf(stdout, "SET %s = %llu\n", w->name, w->utime + w->fix_utime + (include_exited_childs?(w->cutime + w->fix_cutime):0));
}
fprintf(stdout, "END\n");
for (w = root; w ; w = w->next) {
if(w->target || (!w->processes && !w->exposed)) continue;
- fprintf(stdout, "SET %s = %llu\n", w->name, w->stime + w->fix_stime);
+ fprintf(stdout, "SET %s = %llu\n", w->name, w->stime + w->fix_stime + (include_exited_childs?(w->cstime + w->fix_cstime):0));
}
fprintf(stdout, "END\n");
for (w = root; w ; w = w->next) {
if(w->target || (!w->processes && !w->exposed)) continue;
- fprintf(stdout, "SET %s = %llu\n", w->name, w->minflt + w->fix_minflt);
+ fprintf(stdout, "SET %s = %llu\n", w->name, w->minflt + w->fix_minflt + (include_exited_childs?(w->cminflt + w->fix_cminflt):0));
}
fprintf(stdout, "END\n");
for (w = root; w ; w = w->next) {
if(w->target || (!w->processes && !w->exposed)) continue;
- fprintf(stdout, "SET %s = %llu\n", w->name, w->majflt + w->fix_majflt);
+ fprintf(stdout, "SET %s = %llu\n", w->name, w->majflt + w->fix_majflt + (include_exited_childs?(w->cmajflt + w->fix_cmajflt):0));
}
fprintf(stdout, "END\n");
// we have something new to show
// update the charts
- fprintf(stdout, "CHART %s.cpu '' '%s CPU Time (%ld%% = %ld core%s)' 'cpu time %%' cpu %s.cpu stacked 20001 %d\n", type, title, (processors * 100), processors, (processors>1)?"s":"", type, update_every);
+ fprintf(stdout, "CHART %s.cpu '' '%s CPU Time (%d%% = %d core%s)' 'cpu time %%' cpu %s.cpu stacked 20001 %d\n", type, title, (processors * 100), processors, (processors>1)?"s":"", type, update_every);
for (w = root; w ; w = w->next) {
if(w->target || (!w->processes && !w->exposed)) continue;
fprintf(stdout, "DIMENSION %s '' absolute 1 1 noreset\n", w->name);
}
- fprintf(stdout, "CHART %s.cpu_user '' '%s CPU User Time (%ld%% = %ld core%s)' 'cpu time %%' cpu %s.cpu_user stacked 20020 %d\n", type, title, (processors * 100), processors, (processors>1)?"s":"", type, update_every);
+ fprintf(stdout, "CHART %s.cpu_user '' '%s CPU User Time (%d%% = %d core%s)' 'cpu time %%' cpu %s.cpu_user stacked 20020 %d\n", type, title, (processors * 100), processors, (processors>1)?"s":"", type, update_every);
for (w = root; w ; w = w->next) {
if(w->target || (!w->processes && !w->exposed)) continue;
- fprintf(stdout, "DIMENSION %s '' incremental 100 %ld noreset\n", w->name, hz * processors);
+ fprintf(stdout, "DIMENSION %s '' incremental 100 %u noreset\n", w->name, hz);
}
- fprintf(stdout, "CHART %s.cpu_system '' '%s CPU System Time (%ld%% = %ld core%s)' 'cpu time %%' cpu %s.cpu_system stacked 20021 %d\n", type, title, (processors * 100), processors, (processors>1)?"s":"", type, update_every);
+ fprintf(stdout, "CHART %s.cpu_system '' '%s CPU System Time (%d%% = %d core%s)' 'cpu time %%' cpu %s.cpu_system stacked 20021 %d\n", type, title, (processors * 100), processors, (processors>1)?"s":"", type, update_every);
for (w = root; w ; w = w->next) {
if(w->target || (!w->processes && !w->exposed)) continue;
- fprintf(stdout, "DIMENSION %s '' incremental 100 %ld noreset\n", w->name, hz * processors);
+ fprintf(stdout, "DIMENSION %s '' incremental 100 %u noreset\n", w->name, hz);
}
fprintf(stdout, "CHART %s.major_faults '' '%s Major Page Faults (swap read)' 'page faults/s' swap %s.major_faults stacked 20010 %d\n", type, title, type, update_every);
continue;
}
+ if(strcmp("no-childs", argv[i]) == 0) {
+ include_exited_childs = 0;
+ continue;
+ }
+
+ if(strcmp("with-childs", argv[i]) == 0) {
+ include_exited_childs = 1;
+ continue;
+ }
+
if(!name) {
name = argv[i];
continue;
}
#endif /* NETDATA_INTERNAL_CHECKS */
- info("starting...");
-
procfile_adaptive_initial_allocation = 1;
time_t started_t = time(NULL);
}
fprintf(stdout, "CHART netdata.apps_cpu '' 'Apps Plugin CPU' 'milliseconds/s' apps.plugin netdata.apps_cpu stacked 140000 %1$d\n"
- "DIMENSION user '' incremental 1 1000\n"
- "DIMENSION system '' incremental 1 1000\n"
- "CHART netdata.apps_files '' 'Apps Plugin Files' 'files/s' apps.plugin netdata.apps_files line 140001 %1$d\n"
- "DIMENSION files '' incremental 1 1\n"
- "DIMENSION pids '' absolute 1 1\n"
- "DIMENSION fds '' absolute 1 1\n"
- "DIMENSION targets '' absolute 1 1\n", update_every);
+ "DIMENSION user '' incremental 1 1000\n"
+ "DIMENSION system '' incremental 1 1000\n"
+ "CHART netdata.apps_files '' 'Apps Plugin Files' 'files/s' apps.plugin netdata.apps_files line 140001 %1$d\n"
+ "DIMENSION files '' incremental 1 1\n"
+ "DIMENSION pids '' absolute 1 1\n"
+ "DIMENSION fds '' absolute 1 1\n"
+ "DIMENSION targets '' absolute 1 1\n", update_every);
#ifndef PROFILING_MODE
unsigned long long sunext = (time(NULL) - (time(NULL) % update_every) + update_every) * 1000000ULL;
#ifndef PROFILING_MODE
// delay until it is our time to run
while((sunow = timems()) < sunext)
- usleep((useconds_t)(sunext - sunow));
+ usecsleep(sunext - sunow);
// find the next time we need to run
while(timems() > sunext)
send_collected_data_to_netdata(users_root_target, "users", dt);
send_collected_data_to_netdata(groups_root_target, "groups", dt);
- if(debug) fprintf(stderr, "apps.plugin: done Loop No %llu\n", counter);
+ if(unlikely(debug))
+ fprintf(stderr, "apps.plugin: done Loop No %llu\n", counter);
current_t = time(NULL);
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/mman.h>
-
+#include <time.h>
#include "log.h"
#include "common.h"
return now.tv_sec * 1000000ULL + now.tv_usec;
}
+int usecsleep(unsigned long long usec) {
+
+#ifdef NETDATA_WITH_NANOSLEEP
+ // we expect microseconds (1.000.000 per second)
+ // but timespec is nanoseconds (1.000.000.000 per second)
+ struct timespec req = { .tv_sec = usec / 1000000, .tv_nsec = (usec % 1000000) * 1000 }, rem;
+
+ while(nanosleep(&req, &rem) == -1) {
+ error("nanosleep() failed for %llu microseconds.", usec);
+
+ if(likely(errno == EINTR)) {
+ req.tv_sec = rem.tv_sec;
+ req.tv_nsec = rem.tv_nsec;
+ }
+ else {
+ error("Cannot nanosleep() for %llu microseconds.", usec);
+ break;
+ }
+ }
+
+ return 0;
+#else
+ int ret = usleep(usec);
+ if(unlikely(ret == -1 && errno == EINVAL)) {
+ // on certain systems, usec has to be up to 999999
+ if(usec > 999999) {
+ int counter = usec / 999999;
+ while(counter--)
+ usleep(999999);
+
+ usleep(usec % 999999);
+ }
+ else {
+ error("Cannot usleep() for %llu microseconds.", usec);
+ return ret;
+ }
+ }
+
+ if(ret != 0)
+ error("usleep() failed for %llu microseconds.", usec);
+
+ return ret;
+#endif
+}
+
unsigned char netdata_map_chart_names[256] = {
[0] = '\0', //
[1] = '_', //
extern pid_t gettid(void);
extern unsigned long long timems(void);
+extern int usecsleep(unsigned long long usec);
extern char *fgets_trim_len(char *buf, size_t buf_size, FILE *fp, size_t *len);
// delay until it is our time to run
while((sunow = timems()) < sunext)
- usleep((useconds_t)(sunext - sunow));
+ usecsleep(sunext - sunow);
// find the next time we need to run
while(timems() > sunext)
#include "rrd.h"
#include "plugin_proc.h"
-#define RRD_TYPE_STAT "cpu"
-#define RRD_TYPE_STAT_LEN strlen(RRD_TYPE_STAT)
-
int do_proc_stat(int update_every, unsigned long long dt) {
+ (void)dt;
+
static procfile *ff = NULL;
static int do_cpu = -1, do_cpu_cores = -1, do_interrupts = -1, do_context = -1, do_forks = -1, do_processes = -1;
+ static uint32_t hash_intr, hash_ctxt, hash_processes, hash_procs_running, hash_procs_blocked;
+
+ if(unlikely(do_cpu == -1)) {
+ do_cpu = config_get_boolean("plugin:proc:/proc/stat", "cpu utilization", 1);
+ do_cpu_cores = config_get_boolean("plugin:proc:/proc/stat", "per cpu core utilization", 1);
+ do_interrupts = config_get_boolean("plugin:proc:/proc/stat", "cpu interrupts", 1);
+ do_context = config_get_boolean("plugin:proc:/proc/stat", "context switches", 1);
+ do_forks = config_get_boolean("plugin:proc:/proc/stat", "processes started", 1);
+ do_processes = config_get_boolean("plugin:proc:/proc/stat", "processes running", 1);
+
+ hash_intr = simple_hash("intr");
+ hash_ctxt = simple_hash("ctxt");
+ hash_processes = simple_hash("processes");
+ hash_procs_running = simple_hash("procs_running");
+ hash_procs_blocked = simple_hash("procs_blocked");
+ }
- if(do_cpu == -1) do_cpu = config_get_boolean("plugin:proc:/proc/stat", "cpu utilization", 1);
- if(do_cpu_cores == -1) do_cpu_cores = config_get_boolean("plugin:proc:/proc/stat", "per cpu core utilization", 1);
- if(do_interrupts == -1) do_interrupts = config_get_boolean("plugin:proc:/proc/stat", "cpu interrupts", 1);
- if(do_context == -1) do_context = config_get_boolean("plugin:proc:/proc/stat", "context switches", 1);
- if(do_forks == -1) do_forks = config_get_boolean("plugin:proc:/proc/stat", "processes started", 1);
- if(do_processes == -1) do_processes = config_get_boolean("plugin:proc:/proc/stat", "processes running", 1);
-
- if(dt) {};
-
- if(!ff) {
+ if(unlikely(!ff)) {
char filename[FILENAME_MAX + 1];
snprintfz(filename, FILENAME_MAX, "%s%s", global_host_prefix, "/proc/stat");
ff = procfile_open(config_get("plugin:proc:/proc/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;
RRDSET *st;
for(l = 0; l < lines ;l++) {
- if(strncmp(procfile_lineword(ff, l, 0), "cpu", 3) == 0) {
+ char *row_key = procfile_lineword(ff, l, 0);
+ uint32_t hash = simple_hash(row_key);
+
+ // faster strncmp(row_key, "cpu", 3) == 0
+ if(likely(row_key[0] == 'c' && row_key[1] == 'p' && row_key[2] == 'u')) {
words = procfile_linewords(ff, l);
- if(words < 9) {
+ if(unlikely(words < 9)) {
error("Cannot read /proc/stat cpu line. Expected 9 params, read %u.", words);
continue;
}
char *id;
unsigned long long user = 0, nice = 0, system = 0, idle = 0, iowait = 0, irq = 0, softirq = 0, steal = 0, guest = 0, guest_nice = 0;
- id = procfile_lineword(ff, l, 0);
+ id = row_key;
user = strtoull(procfile_lineword(ff, l, 1), NULL, 10);
nice = strtoull(procfile_lineword(ff, l, 2), NULL, 10);
system = strtoull(procfile_lineword(ff, l, 3), NULL, 10);
if(words >= 10) guest = strtoull(procfile_lineword(ff, l, 9), NULL, 10);
if(words >= 11) guest_nice = strtoull(procfile_lineword(ff, l, 10), NULL, 10);
- char *title = "Core utilization";
- char *type = RRD_TYPE_STAT;
- char *context = "cpu.cpu";
- char *family = "utilization";
- long priority = 1000;
- int isthistotal = 0;
+ char *title, *type, *context, *family;
+ long priority;
+ int isthistotal;
- if(strcmp(id, "cpu") == 0) {
- isthistotal = 1;
- type = "system";
+ if(unlikely(strcmp(id, "cpu")) == 0) {
title = "Total CPU utilization";
+ type = "system";
context = "system.cpu";
family = id;
priority = 100;
+ isthistotal = 1;
+ }
+ else {
+ title = "Core utilization";
+ type = "cpu";
+ context = "cpu.cpu";
+ family = "utilization";
+ priority = 1000;
+ isthistotal = 0;
}
- if((isthistotal && do_cpu) || (!isthistotal && do_cpu_cores)) {
+ if(likely((isthistotal && do_cpu) || (!isthistotal && do_cpu_cores))) {
st = rrdset_find_bytype(type, id);
- if(!st) {
+ if(unlikely(!st)) {
st = rrdset_create(type, id, NULL, family, context, title, "percentage", priority, update_every, RRDSET_TYPE_STACKED);
long multiplier = 1;
rrdset_done(st);
}
}
- else if(strcmp(procfile_lineword(ff, l, 0), "intr") == 0) {
+ else if(hash == hash_intr && strcmp(row_key, "intr") == 0) {
unsigned long long value = strtoull(procfile_lineword(ff, l, 1), NULL, 10);
// --------------------------------------------------------------------
- if(do_interrupts) {
+ if(likely(do_interrupts)) {
st = rrdset_find_bytype("system", "intr");
- if(!st) {
+ if(unlikely(!st)) {
st = rrdset_create("system", "intr", NULL, "interrupts", NULL, "CPU Interrupts", "interrupts/s", 900, update_every, RRDSET_TYPE_LINE);
st->isdetail = 1;
rrdset_done(st);
}
}
- else if(strcmp(procfile_lineword(ff, l, 0), "ctxt") == 0) {
+ else if(hash == hash_ctxt && strcmp(row_key, "ctxt") == 0) {
unsigned long long value = strtoull(procfile_lineword(ff, l, 1), NULL, 10);
// --------------------------------------------------------------------
- if(do_context) {
+ if(likely(do_context)) {
st = rrdset_find_bytype("system", "ctxt");
- if(!st) {
+ if(unlikely(!st)) {
st = rrdset_create("system", "ctxt", NULL, "processes", NULL, "CPU Context Switches", "context switches/s", 800, update_every, RRDSET_TYPE_LINE);
rrddim_add(st, "switches", NULL, 1, 1, RRDDIM_INCREMENTAL);
rrdset_done(st);
}
}
- else if(!processes && strcmp(procfile_lineword(ff, l, 0), "processes") == 0) {
+ else if(hash == hash_processes && !processes && strcmp(row_key, "processes") == 0) {
processes = strtoull(procfile_lineword(ff, l, 1), NULL, 10);
}
- else if(!running && strcmp(procfile_lineword(ff, l, 0), "procs_running") == 0) {
+ else if(hash == hash_procs_running && !running && strcmp(row_key, "procs_running") == 0) {
running = strtoull(procfile_lineword(ff, l, 1), NULL, 10);
}
- else if(!blocked && strcmp(procfile_lineword(ff, l, 0), "procs_blocked") == 0) {
+ else if(hash == hash_procs_blocked && !blocked && strcmp(row_key, "procs_blocked") == 0) {
blocked = strtoull(procfile_lineword(ff, l, 1), NULL, 10);
}
}
// --------------------------------------------------------------------
- if(do_forks) {
+ if(likely(do_forks)) {
st = rrdset_find_bytype("system", "forks");
- if(!st) {
+ if(unlikely(!st)) {
st = rrdset_create("system", "forks", NULL, "processes", NULL, "Started Processes", "processes/s", 700, update_every, RRDSET_TYPE_LINE);
st->isdetail = 1;
// --------------------------------------------------------------------
- if(do_processes) {
+ if(likely(do_processes)) {
st = rrdset_find_bytype("system", "processes");
- if(!st) {
+ if(unlikely(!st)) {
st = rrdset_create("system", "processes", NULL, "processes", NULL, "System Processes", "processes", 600, update_every, RRDSET_TYPE_LINE);
rrddim_add(st, "running", NULL, 1, 1, RRDDIM_ABSOLUTE);
// registry enabled?
registry.enabled = config_get_boolean("registry", "enabled", 0);
+ if(mkdir(VARLIB_DIR, 0755) == -1 && errno != EEXIST)
+ error("Cannot create directory '" VARLIB_DIR "'");
+
// pathnames
registry.pathname = config_get("registry", "registry db directory", VARLIB_DIR "/registry");
if(mkdir(registry.pathname, 0755) == -1 && errno != EEXIST) {
char *ret = NULL;
static char *cache_dir = NULL;
- if(!cache_dir) cache_dir = config_get("global", "cache directory", CACHE_DIR);
+ if(!cache_dir) {
+ cache_dir = config_get("global", "cache directory", CACHE_DIR);
+ int r = mkdir(cache_dir, 0755);
+ if(r != 0 && errno != EEXIST)
+ error("Cannot create directory '%s'", cache_dir);
+ }
char b[FILENAME_MAX + 1];
char n[FILENAME_MAX + 1];
// calculate the proper last_collected_time, using usec_since_last_update
unsigned long long ut = st->last_collected_time.tv_sec * 1000000ULL + st->last_collected_time.tv_usec + st->usec_since_last_update;
st->last_collected_time.tv_sec = (time_t) (ut / 1000000ULL);
- st->last_collected_time.tv_usec = (useconds_t) (ut % 1000000ULL);
+ st->last_collected_time.tv_usec = (suseconds_t) (ut % 1000000ULL);
}
// if this set has not been updated in the past
// set a fake last_updated, in the past using usec_since_last_update
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 = (useconds_t) (ut % 1000000ULL);
+ st->last_updated.tv_usec = (suseconds_t) (ut % 1000000ULL);
// the first entry should not be stored
store_this_entry = 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 = (useconds_t) (ut % 1000000ULL);
+ st->last_updated.tv_usec = (suseconds_t) (ut % 1000000ULL);
// the first entry should not be stored
store_this_entry = 0;
int dimensions;
st->collected_total = 0;
for( rd = st->dimensions, dimensions = 0 ; likely(rd) ; rd = rd->next, dimensions++ )
- st->collected_total += rd->collected_value;
+ if(likely(rd->updated)) st->collected_total += rd->collected_value;
uint32_t storage_flags = SN_EXISTS;
// at this stage we do not interpolate anything
for( rd = st->dimensions ; likely(rd) ; rd = rd->next ) {
+ if(unlikely(!rd->updated)) {
+ rd->calculated_value = 0;
+ continue;
+ }
+
if(unlikely(st->debug)) debug(D_RRD_STATS, "%s/%s: START "
" last_collected_value = " COLLECTED_NUMBER_FORMAT
" collected_value = " COLLECTED_NUMBER_FORMAT
);
switch(rd->algorithm) {
- case RRDDIM_ABSOLUTE:
- rd->calculated_value = (calculated_number)rd->collected_value
- * (calculated_number)rd->multiplier
- / (calculated_number)rd->divisor;
-
- if(unlikely(st->debug))
- debug(D_RRD_STATS, "%s/%s: CALC ABS/ABS-NO-IN "
- CALCULATED_NUMBER_FORMAT " = "
- COLLECTED_NUMBER_FORMAT
- " * " CALCULATED_NUMBER_FORMAT
- " / " CALCULATED_NUMBER_FORMAT
- , st->id, rd->name
- , rd->calculated_value
- , rd->collected_value
- , (calculated_number)rd->multiplier
- , (calculated_number)rd->divisor
- );
- break;
+ case RRDDIM_ABSOLUTE:
+ rd->calculated_value = (calculated_number)rd->collected_value
+ * (calculated_number)rd->multiplier
+ / (calculated_number)rd->divisor;
+
+ if(unlikely(st->debug))
+ debug(D_RRD_STATS, "%s/%s: CALC ABS/ABS-NO-IN "
+ CALCULATED_NUMBER_FORMAT " = "
+ COLLECTED_NUMBER_FORMAT
+ " * " CALCULATED_NUMBER_FORMAT
+ " / " CALCULATED_NUMBER_FORMAT
+ , st->id, rd->name
+ , rd->calculated_value
+ , rd->collected_value
+ , (calculated_number)rd->multiplier
+ , (calculated_number)rd->divisor
+ );
+ break;
case RRDDIM_PCENT_OVER_ROW_TOTAL:
- if(unlikely(!st->collected_total)) rd->calculated_value = 0;
+ if(unlikely(!st->collected_total))
+ rd->calculated_value = 0;
else
- // the percentage of the current value
- // over the total of all dimensions
- rd->calculated_value =
- (calculated_number)100
- * (calculated_number)rd->collected_value
- / (calculated_number)st->collected_total;
+ // the percentage of the current value
+ // over the total of all dimensions
+ rd->calculated_value =
+ (calculated_number)100
+ * (calculated_number)rd->collected_value
+ / (calculated_number)st->collected_total;
if(unlikely(st->debug))
debug(D_RRD_STATS, "%s/%s: CALC PCENT-ROW "
break;
case RRDDIM_INCREMENTAL:
- if(unlikely(!rd->updated || rd->counter <= 1)) {
+ if(unlikely(rd->counter <= 1)) {
rd->calculated_value = 0;
continue;
}
rd->last_collected_value = rd->collected_value;
}
- rd->calculated_value = (calculated_number)(rd->collected_value - rd->last_collected_value)
- * (calculated_number)rd->multiplier
- / (calculated_number)rd->divisor;
+ rd->calculated_value =
+ (calculated_number)(rd->collected_value - rd->last_collected_value)
+ * (calculated_number)rd->multiplier
+ / (calculated_number)rd->divisor;
if(unlikely(st->debug))
debug(D_RRD_STATS, "%s/%s: CALC INC PRE "
break;
case RRDDIM_PCENT_OVER_DIFF_TOTAL:
- if(unlikely(!rd->updated || rd->counter <= 1)) {
+ if(unlikely(rd->counter <= 1)) {
rd->calculated_value = 0;
continue;
}
// the percentage of the current increment
// over the increment of all dimensions together
- if(unlikely(st->collected_total == st->last_collected_total)) rd->calculated_value = rd->last_calculated_value;
- else rd->calculated_value =
- (calculated_number)100
- * (calculated_number)(rd->collected_value - rd->last_collected_value)
- / (calculated_number)(st->collected_total - st->last_collected_total);
+ if(unlikely(st->collected_total == st->last_collected_total))
+ rd->calculated_value = 0;
+ else
+ rd->calculated_value =
+ (calculated_number)100
+ * (calculated_number)(rd->collected_value - rd->last_collected_value)
+ / (calculated_number)(st->collected_total - st->last_collected_total);
if(unlikely(st->debug))
debug(D_RRD_STATS, "%s/%s: CALC PCENT-DIFF "
if(likely(stored_entries || !store_this_entry)) {
st->last_updated.tv_sec = st->last_collected_time.tv_sec;
st->last_updated.tv_usec = st->last_collected_time.tv_usec;
+ st->last_collected_total = st->collected_total;
}
for( rd = st->dimensions; likely(rd) ; rd = rd->next ) {
, rd->calculated_value
);
}
- st->last_collected_total = st->collected_total;
// ALL DONE ABOUT THE DATA UPDATE
// --------------------------------------------------------------------
!strcmp(chart_id, "systemd") ||
!strcmp(chart_id, "system.slice") ||
!strcmp(chart_id, "machine.slice") ||
+ !strcmp(chart_id, "init.scope") ||
!strcmp(chart_id, "user") ||
!strcmp(chart_id, "system") ||
!strcmp(chart_id, "machine") ||
// delay until it is our time to run
while((sunow = timems()) < sunext)
- usleep((useconds_t)(sunext - sunow));
+ usecsleep(sunext - sunow);
// find the next time we need to run
while(timems() > sunext)
#include <stdlib.h>
#include <string.h>
#include <sys/resource.h>
+#include <math.h>
#include "common.h"
#include "storage_number.h"
struct feed_values {
unsigned long long microseconds;
- calculated_number value;
+ collected_number value;
};
struct test {
unsigned long result_entries;
struct feed_values *feed;
calculated_number *results;
+
+ collected_number *feed2;
+ calculated_number *results2;
};
// --------------------------------------------------------------------------------------------------------------------
10, // feed entries
9, // result entries
test1_feed, // feed
- test1_results // results
+ test1_results, // results
+ NULL, // feed2
+ NULL // results2
};
// --------------------------------------------------------------------------------------------------------------------
10, // feed entries
9, // result entries
test2_feed, // feed
- test2_results // results
+ test2_results, // results
+ NULL, // feed2
+ NULL // results2
};
// --------------------------------------------------------------------------------------------------------------------
10, // feed entries
9, // result entries
test3_feed, // feed
- test3_results // results
+ test3_results, // results
+ NULL, // feed2
+ NULL // results2
};
// --------------------------------------------------------------------------------------------------------------------
10, // feed entries
9, // result entries
test4_feed, // feed
- test4_results // results
+ test4_results, // results
+ NULL, // feed2
+ NULL // results2
};
// --------------------------------------------------------------------------------------------------------------------
10, // feed entries
9, // result entries
test5_feed, // feed
- test5_results // results
+ test5_results, // results
+ NULL, // feed2
+ NULL // results2
};
// --------------------------------------------------------------------------------------------------------------------
16, // feed entries
4, // result entries
test6_feed, // feed
- test6_results // results
+ test6_results, // results
+ NULL, // feed2
+ NULL // results2
};
// --------------------------------------------------------------------------------------------------------------------
10, // feed entries
18, // result entries
test7_feed, // feed
- test7_results // results
+ test7_results, // results
+ NULL, // feed2
+ NULL // results2
};
// --------------------------------------------------------------------------------------------------------------------
6, // feed entries
10, // result entries
test8_feed, // feed
- test8_results // results
+ test8_results, // results
+ NULL, // feed2
+ NULL // results2
};
// --------------------------------------------------------------------------------------------------------------------
16, // feed entries
4, // result entries
test9_feed, // feed
- test9_results // results
+ test9_results, // results
+ NULL, // feed2
+ NULL // results2
};
// --------------------------------------------------------------------------------------------------------------------
RRDDIM_INCREMENTAL, // algorithm
10, // feed entries
7, // result entries
- test10_feed, // feed
- test10_results // results
+ test10_feed, // feed
+ test10_results, // results
+ NULL, // feed2
+ NULL // results2
+};
+
+// --------------------------------------------------------------------------------------------------------------------
+// test11
+
+struct feed_values test11_feed[] = {
+ { 0, 10 },
+ { 1000000, 20 },
+ { 1000000, 30 },
+ { 1000000, 40 },
+ { 1000000, 50 },
+ { 1000000, 60 },
+ { 1000000, 70 },
+ { 1000000, 80 },
+ { 1000000, 90 },
+ { 1000000, 100 },
+};
+
+collected_number test11_feed2[] = {
+ 10, 20, 30, 40, 50, 60, 70, 80, 90, 100
+};
+
+calculated_number test11_results[] = {
+ 50, 50, 50, 50, 50, 50, 50, 50, 50
+};
+
+calculated_number test11_results2[] = {
+ 50, 50, 50, 50, 50, 50, 50, 50, 50
+};
+
+struct test test11 = {
+ "test11", // name
+ "test percentage-of-incremental-row with equal values",
+ 1, // update_every
+ 1, // multiplier
+ 1, // divisor
+ RRDDIM_PCENT_OVER_DIFF_TOTAL, // algorithm
+ 10, // feed entries
+ 9, // result entries
+ test11_feed, // feed
+ test11_results, // results
+ test11_feed2, // feed2
+ test11_results2 // results2
+};
+
+// --------------------------------------------------------------------------------------------------------------------
+// test12
+
+struct feed_values test12_feed[] = {
+ { 0, 10 },
+ { 1000000, 20 },
+ { 1000000, 30 },
+ { 1000000, 40 },
+ { 1000000, 50 },
+ { 1000000, 60 },
+ { 1000000, 70 },
+ { 1000000, 80 },
+ { 1000000, 90 },
+ { 1000000, 100 },
+};
+
+collected_number test12_feed2[] = {
+ 10*3, 20*3, 30*3, 40*3, 50*3, 60*3, 70*3, 80*3, 90*3, 100*3
+};
+
+calculated_number test12_results[] = {
+ 25, 25, 25, 25, 25, 25, 25, 25, 25
+};
+
+calculated_number test12_results2[] = {
+ 75, 75, 75, 75, 75, 75, 75, 75, 75
+};
+
+struct test test12 = {
+ "test12", // name
+ "test percentage-of-incremental-row with equal values",
+ 1, // update_every
+ 1, // multiplier
+ 1, // divisor
+ RRDDIM_PCENT_OVER_DIFF_TOTAL, // algorithm
+ 10, // feed entries
+ 9, // result entries
+ test12_feed, // feed
+ test12_results, // results
+ test12_feed2, // feed2
+ test12_results2 // results2
+};
+
+// --------------------------------------------------------------------------------------------------------------------
+// test13
+
+struct feed_values test13_feed[] = {
+ { 500000, 1000 },
+ { 600000, 1000 + 600 },
+ { 200000, 1600 + 200 },
+ { 1000000, 1800 + 1000 },
+ { 200000, 2800 + 200 },
+ { 2000000, 3000 + 2000 },
+ { 600000, 5000 + 600 },
+ { 400000, 5600 + 400 },
+ { 900000, 6000 + 900 },
+ { 1000000, 6900 + 1000 },
+};
+
+calculated_number test13_results[] = {
+ 83.3333300, 100, 100, 100, 100, 100, 100
+};
+
+struct test test13 = {
+ "test13", // name
+ "test incremental values updated in short and long durations",
+ 1, // update_every
+ 1, // multiplier
+ 1, // divisor
+ RRDDIM_PCENT_OVER_DIFF_TOTAL, // algorithm
+ 10, // feed entries
+ 7, // result entries
+ test13_feed, // feed
+ test13_results, // results
+ NULL, // feed2
+ NULL // results2
};
// --------------------------------------------------------------------------------------------------------------------
// create the chart
RRDSET *st = rrdset_create("netdata", name, name, "netdata", NULL, "Unit Testing", "a value", 1, 1, RRDSET_TYPE_LINE);
- RRDDIM *rd = rrddim_add(st, "dimension", NULL, test->multiplier, test->divisor, test->algorithm);
+ RRDDIM *rd = rrddim_add(st, "dim1", NULL, test->multiplier, test->divisor, test->algorithm);
+
+ RRDDIM *rd2 = NULL;
+ if(test->feed2)
+ rd2 = rrddim_add(st, "dim2", NULL, test->multiplier, test->divisor, test->algorithm);
+
st->debug = 1;
// feed it with the test data
if(debug_flags) fprintf(stderr, "\n\n");
if(c) {
- fprintf(stderr, " > %s: feeding position %lu, after %llu microseconds, with value " CALCULATED_NUMBER_FORMAT "\n", test->name, c+1, test->feed[c].microseconds, test->feed[c].value);
+ fprintf(stderr, " > %s: feeding position %lu, after %llu microseconds\n", test->name, c+1, test->feed[c].microseconds);
rrdset_next_usec(st, test->feed[c].microseconds);
}
else {
- fprintf(stderr, " > %s: feeding position %lu with value " CALCULATED_NUMBER_FORMAT "\n", test->name, c+1, test->feed[c].value);
+ fprintf(stderr, " > %s: feeding position %lu\n", test->name, c+1);
+ }
+
+ fprintf(stderr, " >> %s with value " COLLECTED_NUMBER_FORMAT "\n", rd->name, test->feed[c].value);
+ rrddim_set(st, "dim1", test->feed[c].value);
+
+ if(rd2) {
+ fprintf(stderr, " >> %s with value " COLLECTED_NUMBER_FORMAT "\n", rd2->name, test->feed2[c]);
+ rrddim_set(st, "dim2", test->feed2[c]);
}
- rrddim_set(st, "dimension", test->feed[c].value);
rrdset_done(st);
// align the first entry to second boundary
unsigned long max = (st->counter < test->result_entries)?st->counter:test->result_entries;
for(c = 0 ; c < max ; c++) {
- calculated_number v = unpack_storage_number(rd->values[c]), n = test->results[c];
- fprintf(stderr, " %s: checking position %lu, expecting value " CALCULATED_NUMBER_FORMAT ", found " CALCULATED_NUMBER_FORMAT ", %s\n", test->name, c+1, n, v, (v == n)?"OK":"### E R R O R ###");
- if(v != n) errors++;
+ calculated_number v = unpack_storage_number(rd->values[c]);
+ calculated_number n = test->results[c];
+ int same = (roundl(v * 10000000.0) == roundl(n * 10000000.0))?1:0;
+ fprintf(stderr, " %s/%s: checking position %lu, expecting value " CALCULATED_NUMBER_FORMAT ", found " CALCULATED_NUMBER_FORMAT ", %s\n", test->name, rd->name, c+1, n, v, (same)?"OK":"### E R R O R ###");
+ if(!same) errors++;
+
+ if(rd2) {
+ v = unpack_storage_number(rd2->values[c]);
+ n = test->results2[c];
+ same = (roundl(v * 10000000.0) == roundl(n * 10000000.0))?1:0;
+ fprintf(stderr, " %s/%s: checking position %lu, expecting value " CALCULATED_NUMBER_FORMAT ", found " CALCULATED_NUMBER_FORMAT ", %s\n", test->name, rd2->name, c+1, n, v, (same)?"OK":"### E R R O R ###");
+ if(!same) errors++;
+ }
}
return errors;
if(run_test(&test10))
return 1;
+ if(run_test(&test11))
+ return 1;
+
+ if(run_test(&test12))
+ return 1;
+
+ if(run_test(&test13))
+ return 1;
+
return 0;
}
-#!/sbin/runscript
+#!/sbin/openrc-run
# The user netdata is configured to run as.
# If you edit its configuration file to set a different
<html lang="en">
<head>
<title>NetData Dashboard</title>
+ <meta name="application-name" content="netdata">
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta charset="utf-8">
<html lang="en">
<head>
<title>NetData Dashboard</title>
+ <meta name="application-name" content="netdata">
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta charset="utf-8">
<html lang="en">
<head>
<title>NetData Dashboard</title>
+ <meta name="application-name" content="netdata">
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta charset="utf-8">
<html lang="en">
<head>
<title>NetData - Real-time performance monitoring, done right!</title>
+ <meta name="application-name" content="netdata">
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta charset="utf-8">
and that you have chown it to be owned by netdata:netdata
-->
<!-- <script type="text/javascript" src="http://my.server:19999/dashboard.js"></script> -->
- <script type="text/javascript" src="dashboard.js?v40"></script>
+ <script type="text/javascript" src="dashboard.js?v41"></script>
<script>
// --- OPTIONS FOR THE CHARTS --
// destroy charts not shown (lowers memory on the browsers)
- // set this to 'yes' to destroy, 'false' to hide the charts
- NETDATA.options.current.destroy_on_hide = false;
+ // set this to 'true' to destroy, 'false' to hide the charts
+ NETDATA.options.current.destroy_on_hide = true;
// set this to false, to always show all dimensions
NETDATA.options.current.eliminate_zero_dimensions = true;
// set this to false, to lower the pressure on the browser
- NETDATA.options.current.concurrent_refreshes = true;
+ NETDATA.options.current.concurrent_refreshes = false;
// if you need to support slow mobile phones, set this to false
NETDATA.options.current.parallel_refresher = true;
.mygauge {
position: relative;
display: block;
- width: 20vw;
- height: 12vw;
+ width: 18vw;
+ height: 11vw;
}
.mygauge-button {
</div>
<div class="mygauge-button">
<br/> <br/>
- <button type="button" class="btn btn-default" data-toggle="button" aria-pressed="false" autocomplete="off" onclick="window.location='//london.my-netdata.io/default.html'" style="font-size: 1.5vw;">Enter London!</button>
- <div style="font-size: 1vw;">
+ <button type="button" class="btn btn-default" data-toggle="button" aria-pressed="false" autocomplete="off" onclick="window.location='//london.my-netdata.io/default.html'" style="font-size: 1.0vw;">Enter London!</button>
+ <div style="font-size: 0.8vw;">
Donated by DigitalOcean.com
</div>
</div>
</div>
<div class="mygauge-button">
<br/> <br/>
- <button type="button" class="btn btn-default" data-toggle="button" aria-pressed="false" autocomplete="off" onclick="window.location='//atlanta.my-netdata.io/default.html'" style="font-size: 1.5vw;">Enter Atlanta!</button>
- <div style="font-size: 1vw;">
+ <button type="button" class="btn btn-default" data-toggle="button" aria-pressed="false" autocomplete="off" onclick="window.location='//atlanta.my-netdata.io/default.html'" style="font-size: 1.0vw;">Enter Atlanta!</button>
+ <div style="font-size: 0.8vw;">
Donated by CDN77.com
</div>
</div>
<div class="mygauge-combo">
<div class="mygauge">
<div data-netdata="netdata.requests"
- data-host="//athens.my-netdata.io"
- data-title="EU - Greece"
+ data-host="//sanfrancisco.netdata.rocks"
+ data-title="US - California"
data-chart-library="gauge"
data-width="100%"
data-after="-300"
</div>
<div class="mygauge-button">
<br/> <br/>
- <button type="button" class="btn btn-default" data-toggle="button" aria-pressed="false" autocomplete="off" onclick="window.location='//athens.my-netdata.io/default.html'" style="font-size: 1.5vw;">Come to Greece!</button>
+ <button type="button" class="btn btn-default" data-toggle="button" aria-pressed="false" autocomplete="off" onclick="window.location='//sanfrancisco.netdata.rocks/default.html'" style="font-size: 1.0vw;">Enter California!</button>
<div style="font-size: 0.8vw;">
-
+ Donated by DigitalOcean.com
+ </div>
+ </div>
+ </div>
+ <div class="mygauge-combo">
+ <div class="mygauge">
+ <div data-netdata="netdata.requests"
+ data-host="//toronto.netdata.rocks"
+ data-title="Canada"
+ data-chart-library="gauge"
+ data-width="100%"
+ data-after="-300"
+ data-points="300"
+ data-colors="#885588"
+ ></div>
+ </div>
+ <div class="mygauge-button">
+ <br/> <br/>
+ <button type="button" class="btn btn-default" data-toggle="button" aria-pressed="false" autocomplete="off" onclick="window.location='//toronto.netdata.rocks/default.html'" style="font-size: 1.0vw;">Enter Canada!</button>
+ <div style="font-size: 0.8vw;">
+ Donated by DigitalOcean.com
+ </div>
+ </div>
+ </div>
+ <br/> <br/>
+ <div class="mygauge-combo">
+ <div class="mygauge">
+ <div data-netdata="netdata.requests"
+ data-host="//frankfurt.netdata.rocks"
+ data-title="EU - Germany"
+ data-chart-library="easypiechart"
+ data-width="75%"
+ data-after="-300"
+ data-points="300"
+ data-colors="#AAAA55"
+ ></div>
+ </div>
+ <div class="mygauge-button">
+ <br/> <br/>
+ <button type="button" class="btn btn-default" data-toggle="button" aria-pressed="false" autocomplete="off" onclick="window.location='//frankfurt.netdata.rocks/default.html'" style="font-size: 1.0vw;">Enter Germany!</button>
+ <div style="font-size: 0.8vw;">
+ Donated by DigitalOcean.com
+ </div>
+ </div>
+ </div>
+ <div class="mygauge-combo">
+ <div class="mygauge">
+ <div data-netdata="netdata.requests"
+ data-host="//newyork.netdata.rocks"
+ data-title="US - New York"
+ data-chart-library="easypiechart"
+ data-width="75%"
+ data-after="-300"
+ data-points="300"
+ data-colors="#BB5533"
+ ></div>
+ </div>
+ <div class="mygauge-button">
+ <br/> <br/>
+ <button type="button" class="btn btn-default" data-toggle="button" aria-pressed="false" autocomplete="off" onclick="window.location='//newyork.netdata.rocks/default.html'" style="font-size: 1.0vw;">Enter New York!</button>
+ <div style="font-size: 0.8vw;">
+ Donated by DigitalOcean.com
+ </div>
+ </div>
+ </div>
+ <div class="mygauge-combo">
+ <div class="mygauge">
+ <div data-netdata="netdata.requests"
+ data-host="//singapore.netdata.rocks"
+ data-title="Signapore"
+ data-chart-library="easypiechart"
+ data-width="75%"
+ data-after="-300"
+ data-points="300"
+ data-colors="#5588BB"
+ ></div>
+ </div>
+ <div class="mygauge-button">
+ <br/> <br/>
+ <button type="button" class="btn btn-default" data-toggle="button" aria-pressed="false" autocomplete="off" onclick="window.location='//singapore.netdata.rocks/default.html'" style="font-size: 1.0vw;">Enter Singapore!</button>
+ <div style="font-size: 0.8vw;">
+ Donated by DigitalOcean.com
+ </div>
+ </div>
+ </div>
+ <div class="mygauge-combo">
+ <div class="mygauge">
+ <div data-netdata="netdata.requests"
+ data-host="//bangalore.netdata.rocks"
+ data-title="India"
+ data-chart-library="easypiechart"
+ data-width="75%"
+ data-after="-300"
+ data-points="300"
+ data-colors="#BB55BB"
+ ></div>
+ </div>
+ <div class="mygauge-button">
+ <br/> <br/>
+ <button type="button" class="btn btn-default" data-toggle="button" aria-pressed="false" autocomplete="off" onclick="window.location='//bangalore.netdata.rocks/default.html'" style="font-size: 1.0vw;">Enter India!</button>
+ <div style="font-size: 0.8vw;">
+ Donated by DigitalOcean.com
</div>
</div>
</div>
this page is a custom <b>netdata</b> dashboard
</div>
<div class="mycontent">
- charts are coming from 3 servers, in parallel
+ charts are coming from 8 servers, in parallel
<br/>
the servers are not aware of this multi-server dashboard,
<br/>
- each server is not aware of the other 2 servers,
+ each server is not aware of the other servers,
<br/>
but on this dashboard <b>they are one</b>!
</div>
<div class="mysparkline">
<div class="mysparkline-overchart-label">
- <b>EU - Greece</b> web requests/s
+ <b>US - California</b> web requests/s
</div>
<div class="mysparkline-overchart-value" id="nginx.requests.netdata3" >
</div>
<div data-netdata="nginx.requests"
data-dimensions="requests"
- data-host="//athens.my-netdata.io"
+ data-host="//sanfrancisco.netdata.rocks"
data-chart-library="dygraph"
data-dygraph-theme="sparkline"
data-dygraph-type="area"
data-show-value-of-requests-at="nginx.requests.netdata3"
></div>
</div>
+
+ <div class="mysparkline">
+ <div class="mysparkline-overchart-label">
+ <b>Canada</b> web requests/s
+ </div>
+ <div class="mysparkline-overchart-value" id="nginx.requests.netdata4" >
+ </div>
+ <div data-netdata="nginx.requests"
+ data-dimensions="requests"
+ data-host="//toronto.netdata.rocks"
+ data-chart-library="dygraph"
+ data-dygraph-theme="sparkline"
+ data-dygraph-type="area"
+ data-width="100%"
+ data-height="100%"
+ data-after="-300"
+ data-colors="#885588"
+ data-show-value-of-requests-at="nginx.requests.netdata4"
+ ></div>
+ </div>
</div>
<div role="tabpanel" class="tab-pane" id="nginx_connections">
<div class="mysparkline">
<div class="mysparkline-overchart-label">
- <b>EU - Greece</b> active connections
+ <b>US - California</b> active connections
</div>
<div class="mysparkline-overchart-value" id="nginx.connections.netdata3" >
</div>
<div data-netdata="nginx.connections"
data-dimensions="active"
- data-host="//athens.my-netdata.io"
+ data-host="//sanfrancisco.netdata.rocks"
data-chart-library="dygraph"
data-dygraph-theme="sparkline"
data-dygraph-type="area"
data-show-value-of-active-at="nginx.connections.netdata3"
></div>
</div>
+
+ <div class="mysparkline">
+ <div class="mysparkline-overchart-label">
+ <b>Canada</b> active connections
+ </div>
+ <div class="mysparkline-overchart-value" id="nginx.connections.netdata4" >
+ </div>
+ <div data-netdata="nginx.connections"
+ data-dimensions="active"
+ data-host="//toronto.netdata.rocks"
+ data-chart-library="dygraph"
+ data-dygraph-theme="sparkline"
+ data-dygraph-type="area"
+ data-width="100%"
+ data-height="100%"
+ data-after="-300"
+ data-colors="#885588"
+ data-show-value-of-active-at="nginx.connections.netdata4"
+ ></div>
+ </div>
</div>
</div>
<div class="myfullchart">
<div data-netdata="tc.world_out"
- data-host="//athens.my-netdata.io"
+ data-host="//sanfrancisco.netdata.rocks"
+ data-chart-library="dygraph"
+ data-title="US - California, traffic we send per service"
+ data-width="100%"
+ data-height="100%"
+ data-after="-300"
+ ></div>
+ </div>
+
+ <div class="myfullchart">
+ <div data-netdata="tc.world_out"
+ data-host="//toronto.netdata.rocks"
data-chart-library="dygraph"
- data-title="EU - Greece, traffic we send per service"
+ data-title="Canada, traffic we send per service"
data-width="100%"
data-height="100%"
data-after="-300"
></div>
</div>
</div>
+
<div role="tabpanel" class="tab-pane" id="inbound">
<div class="myfullchart">
<div data-netdata="tc.world_in"
<div class="myfullchart">
<div data-netdata="tc.world_in"
- data-host="//athens.my-netdata.io"
+ data-host="//sanfrancisco.netdata.rocks"
+ data-chart-library="dygraph"
+ data-title="US - California, traffic we receive per service"
+ data-width="100%"
+ data-height="100%"
+ data-after="-300"
+ ></div>
+ </div>
+
+ <div class="myfullchart">
+ <div data-netdata="tc.world_in"
+ data-host="//toronto.netdata.rocks"
data-chart-library="dygraph"
- data-title="EU - Greece, traffic we receive per service"
+ data-title="Canada, traffic we receive per service"
data-width="100%"
data-height="100%"
data-after="-300"
<div class="mysparkline">
<div class="mysparkline-overchart-label">
- <b>EU - Greece</b>, TCP SYN packets/s received
+ <b>US - California</b>, TCP SYN packets/s received
</div>
<div class="mysparkline-overchart-value" id="netfilter.synproxy_syn_received.netdata3" >
</div>
<div data-netdata="netfilter.synproxy_syn_received"
data-dimensions="received"
- data-host="//athens.my-netdata.io"
+ data-host="//sanfrancisco.netdata.rocks"
data-chart-library="dygraph"
data-dygraph-theme="sparkline"
data-dygraph-type="area"
data-show-value-of-received-at="netfilter.synproxy_syn_received.netdata3"
></div>
</div>
+
+ <div class="mysparkline">
+ <div class="mysparkline-overchart-label">
+ <b>Canada</b>, TCP SYN packets/s received
+ </div>
+ <div class="mysparkline-overchart-value" id="netfilter.synproxy_syn_received.netdata4" >
+ </div>
+ <div data-netdata="netfilter.synproxy_syn_received"
+ data-dimensions="received"
+ data-host="//toronto.netdata.rocks"
+ data-chart-library="dygraph"
+ data-dygraph-theme="sparkline"
+ data-dygraph-type="area"
+ data-width="100%"
+ data-height="100%"
+ data-after="-300"
+ data-colors="#885588"
+ data-show-value-of-received-at="netfilter.synproxy_syn_received.netdata4"
+ ></div>
+ </div>
</div>
<div style="width: 100%; text-align: right; font-size: 1vw;">
<i class="fa fa-comment" aria-hidden="true"></i> <i>did you notice the decimal numbers?
data-width="100%"
data-height="100%"
data-after="-300"
+ data-dygraph-valuerange="[0, 100]"
></div>
</div>
data-width="100%"
data-height="100%"
data-after="-300"
+ data-dygraph-valuerange="[0, 100]"
+ ></div>
+ </div>
+
+ <div class="myfullchart">
+ <div data-netdata="system.cpu"
+ data-host="//sanfrancisco.netdata.rocks"
+ data-chart-library="dygraph"
+ data-title="US - California, CPU Usage"
+ data-width="100%"
+ data-height="100%"
+ data-after="-300"
+ data-dygraph-valuerange="[0, 100]"
></div>
</div>
<div class="myfullchart">
<div data-netdata="system.cpu"
- data-host="//athens.my-netdata.io"
+ data-host="//toronto.netdata.rocks"
data-chart-library="dygraph"
- data-title="EU - Greece, CPU Usage"
+ data-title="Canada, CPU Usage"
data-width="100%"
data-height="100%"
data-after="-300"
+ data-dygraph-valuerange="[0, 100]"
></div>
</div>
</div>
<div class="mysparkline">
<div class="mysparkline-overchart-label">
- <b>EU - Greece</b>, CPU % of a single core
+ <b>US - California</b>, CPU % of a single core
</div>
<div class="mysparkline-overchart-value" id="users.cpu.netdata3" >
</div>
<div data-netdata="users.cpu"
data-dimensions="netdata"
- data-host="//athens.my-netdata.io"
+ data-host="//sanfrancisco.netdata.rocks"
data-chart-library="dygraph"
data-dygraph-theme="sparkline"
data-dygraph-type="area"
></div>
</div>
+ <div class="mysparkline">
+ <div class="mysparkline-overchart-label">
+ <b>Toronto</b>, CPU % of a single core
+ </div>
+ <div class="mysparkline-overchart-value" id="users.cpu.netdata4" >
+ </div>
+ <div data-netdata="users.cpu"
+ data-dimensions="netdata"
+ data-host="//toronto.netdata.rocks"
+ data-chart-library="dygraph"
+ data-dygraph-theme="sparkline"
+ data-dygraph-type="area"
+ data-width="100%"
+ data-height="100%"
+ data-after="-300"
+ data-colors="#885588"
+ data-show-value-of-netdata-at="users.cpu.netdata4"
+ ></div>
+ </div>
+
<div style="width: 100%; text-align: right; font-size: 1vw;">
<i class="fa fa-comment" aria-hidden="true"></i> <i>this utilization is about the whole netdata process tree and the percentage is of <b>a single core</b>!
<br/>including <b>BASH</b> plugins (it monitors <code>mysql</code> on the demo sites), <b>node.js</b> plugins (it monitors <code>bind9</code> on the demo sites), etc.
<div class="mysparkline">
<div class="mysparkline-overchart-label">
- <b>EU - Greece</b>, API average response time in milliseconds
+ <b>US - California</b>, API average response time in milliseconds
</div>
<div class="mysparkline-overchart-value" id="netdata.response_time3" >
</div>
<div data-netdata="netdata.response_time"
- data-host="//athens.my-netdata.io"
+ data-host="//sanfrancisco.netdata.rocks"
data-chart-library="dygraph"
data-dygraph-theme="sparkline"
data-dygraph-type="area"
></div>
</div>
+ <div class="mysparkline">
+ <div class="mysparkline-overchart-label">
+ <b>Canada</b>, API average response time in milliseconds
+ </div>
+ <div class="mysparkline-overchart-value" id="netdata.response_time4" >
+ </div>
+ <div data-netdata="netdata.response_time"
+ data-host="//toronto.netdata.rocks"
+ data-chart-library="dygraph"
+ data-dygraph-theme="sparkline"
+ data-dygraph-type="area"
+ data-width="100%"
+ data-height="100%"
+ data-after="-300"
+ data-colors="#885588"
+ data-show-value-of-response_time-at="netdata.response_time4"
+ ></div>
+ </div>
+
<div style="width: 100%; text-align: right; font-size: 1vw;">
<i class="fa fa-comment" aria-hidden="true"></i> <i>netdata is really <b>fast</b> (the values are milliseconds!)
<br/>
<html lang="en">
<head>
<title>netdata dashboard</title>
+ <meta name="application-name" content="netdata">
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta charset="utf-8">
'apps': {
title: 'Applications',
- info: 'Per application statistics are collected using netdata\'s <code>apps.plugin</code>. This plugin walks through the entire <code>/proc</code> filesystem and aggregates statistics for applications of interest, defined in <code>/etc/netdata/apps_groups.conf</code> (the default is <a href="https://github.com/firehol/netdata/blob/master/conf.d/apps_groups.conf" target="_blank">here</a>). The plugin internally builds a process tree (much like <code>ps fax</code> 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).<br/><b>IMPORTANT</b>: The values shown here are not 100% accurate. They only include values for the processes running. If an application is spawning children continuously, which are terminated in just a few milliseconds (like shell scripts do), the values reported will be inaccurate. Linux does report the values for the exited children of a process. However, these values are reported to the parent process <b>only when the child exits</b>. If these values, of the exited child processes, were also aggregated in the charts below, the charts would have been full of spikes, presenting unrealistic utilization for each process group. So, we decided to ignore these values and present only the utilization of <b>the currently running processes</b>.',
+ info: 'Per application statistics are collected using netdata\'s <code>apps.plugin</code>. This plugin walks through the entire <code>/proc</code> filesystem and aggregates statistics for applications of interest, defined in <code>/etc/netdata/apps_groups.conf</code> (the default is <a href="https://github.com/firehol/netdata/blob/master/conf.d/apps_groups.conf" target="_blank">here</a>). The plugin internally builds a process tree (much like <code>ps fax</code> 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 <code>top</code>, although the netdata plugin counts also the resources of exited children (unlike <code>top</code> 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',
- info: 'Per user statistics are collected using netdata\'s <code>apps.plugin</code>. This plugin walks through the entire <code>/proc</code> filesystem and aggregates statistics per user.<br/><b>IMPORTANT</b>: The values shown here are not 100% accurate. They only include values for the processes running. If an application is spawning children continuously, which are terminated in just a few milliseconds (like shell scripts do), the values reported will be inaccurate. Linux does report the values for the exited children of a process. However, these values are reported to the parent process <b>only when the child exits</b>. If these values, of the exited child processes, were also aggregated in the charts below, the charts would have been full of spikes, presenting unrealistic utilization for each process group. So, we decided to ignore these values and present only the utilization of <b>the currently running processes</b>.',
+ info: 'Per user statistics are collected using netdata\'s <code>apps.plugin</code>. This plugin walks through the entire <code>/proc</code> filesystem and aggregates statistics per user. The reported values are compatible with <code>top</code>, although the netdata plugin counts also the resources of exited children (unlike <code>top</code> 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',
- info: 'Per user group statistics are collected using netdata\'s <code>apps.plugin</code>. This plugin walks through the entire <code>/proc</code> filesystem and aggregates statistics per user group.<br/><b>IMPORTANT</b>: The values shown here are not 100% accurate. They only include values for the processes running. If an application is spawning children continuously, which are terminated in just a few milliseconds (like shell scripts do), the values reported will be inaccurate. Linux does report the values for the exited children of a process. However, these values are reported to the parent process <b>only when the child exits</b>. If these values, of the exited child processes, were also aggregated in the charts below, the charts would have been full of spikes, presenting unrealistic utilization for each process group. So, we decided to ignore these values and present only the utilization of <b>the currently running processes</b>.',
+ info: 'Per user group statistics are collected using netdata\'s <code>apps.plugin</code>. This plugin walks through the entire <code>/proc</code> filesystem and aggregates statistics per user group. The reported values are compatible with <code>top</code>, although the netdata plugin counts also the resources of exited children (unlike <code>top</code> 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
},
<html lang="en">
<head>
<title>NetData Registry Dashboard</title>
+ <meta name="application-name" content="netdata">
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta charset="utf-8">
<html lang="en">
<head>
<title>NetData TV Dashboard</title>
+ <meta name="application-name" content="netdata">
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta charset="utf-8">