Now buffer_jsdate() and buffer_date() are a little bit faster.
system/netdata-openrc
system/netdata-init-d
+system/netdata.logrotate
netdata-installer.log
netdata-uninstaller.sh
+netdata (1.1.0) - 2016-04-20
+
+ Dozens of commits that improve netdata in several ways:
+
+ - Data collection: added IPv6 monitoring
+ - Data collection: added SYNPROXY DDoS protection monitoring
+ - Data collection: apps.plugin: added charts for users and user groups
+ - Data collection: apps.plugin: grouping of processes now support patterns
+ - Data collection: apps.plugin: now it is faster, after the new features added
+ - Data collection: better auto-detection of partitions for disk monitoring
+ - Data collection: better fireqos intergation for QoS monitoring
+ - Data collection: squid monitoring now uses squidclient
+ - Data collection: SNMP monitoring now supports 64bit counters
+ - API: fixed issues in CSV output generation
+ - API: netdata can now be restricted to listen on a specific IP
+ - Core and apps.plugin: error log flood protection
+ - Dashboard: better error handling when the netdata server is unreachable
+ - Dashboard: each chart now has a toolbox
+ - Dashboard: on-line help support
+ - Dashboard: check for netdata updates button
+ - Dashboard: added example /tv.html dashboard
+ - Packaging: now compiles with musl libc (alpine linux)
+ - Packaging: added debian packaging
+ - Packaging: support non-root installations
+ - Packaging: the installer generates uninstall script
+
netdata (1.0.0) - 2016-03-22
- first public release
src \
system \
web \
+ contrib \
$(NULL)
dist_noinst_DATA = netdata.spec
It should run on **any Linux** system. It has been tested on:
- Gentoo
-- ArchLinux
+- Arch Linux
- Ubuntu / Debian
- CentOS
- Fedora
nginx.chart.sh \
nut.chart.sh \
opensips.chart.sh \
+ phpfpm.chart.sh \
postfix.chart.sh \
sensors.chart.sh \
squid.chart.sh \
+ tomcat.chart.sh \
$(NULL)
dist_charts_DATA = \
-#!/bin/sh
+#!/bin/bash
# _update_every is a special variable - it holds the number of seconds
# between the calls of the _update() function
-#!/bin/sh
+#!/bin/bash
# the URL to download apache status info
apache_url="http://127.0.0.1:80/server-status?auto"
apache_get() {
local oIFS="${IFS}" ret
- IFS=$':\n' apache_response=($(curl -s "${apache_url}"))
+ IFS=$':\n' apache_response=($(curl -Ss "${apache_url}"))
ret=$?
IFS="${oIFS}"
-#!/bin/sh
+#!/bin/bash
# if this chart is called X.chart.sh, then all functions and global variables
# must start with X_
-#!/bin/sh
+#!/bin/bash
# http://dev.mysql.com/doc/refman/5.0/en/server-status-variables.html
#
-#!/bin/sh
+#!/bin/bash
# if this chart is called X.chart.sh, then all functions and global variables
# must start with X_
nginx_writing=0
nginx_waiting=0
nginx_get() {
- nginx_response=($(curl -s "${nginx_url}"))
+ nginx_response=($(curl -Ss "${nginx_url}"))
[ $? -ne 0 -o "${#nginx_response[@]}" -eq 0 ] && return 1
if [ "${nginx_response[0]}" != "Active" \
--- /dev/null
+#!/bin/bash
+
+# if this chart is called X.chart.sh, then all functions and global variables
+# must start with X_
+
+# first, you need open php-fpm status in php-fpm.conf
+# second, you need add status location in nginx.conf
+# you can see, https://easyengine.io/tutorials/php/fpm-status-page/
+
+declare -A phpfpm_urls=()
+
+# _update_every is a special variable - it holds the number of seconds
+# between the calls of the _update() function
+phpfpm_update_every=
+phpfpm_priority=60000
+
+declare -a phpfpm_response=()
+phpfpm_pool=""
+phpfpm_start_time=""
+phpfpm_start_since=0
+phpfpm_accepted_conn=0
+phpfpm_listen_queue=0
+phpfpm_max_listen_queue=0
+phpfpm_listen_queue_len=0
+phpfpm_idle_processes=0
+phpfpm_active_processes=0
+phpfpm_total_processes=0
+phpfpm_max_active_processes=0
+phpfpm_max_children_reached=0
+phpfpm_slow_requests=0
+phpfpm_get() {
+ url=$1
+ phpfpm_response=($(curl -Ss "${url}"))
+ [ $? -ne 0 -o "${#phpfpm_response[@]}" -eq 0 ] && return 1
+
+ if [[ "${phpfpm_response[0]}" != "pool:" \
+ || "${phpfpm_response[2]}" != "process" \
+ || "${phpfpm_response[5]}" != "start" \
+ || "${phpfpm_response[12]}" != "accepted" \
+ || "${phpfpm_response[15]}" != "listen" \
+ || "${phpfpm_response[16]}" != "queue:" \
+ || "${phpfpm_response[26]}" != "idle" \
+ || "${phpfpm_response[29]}" != "active" \
+ || "${phpfpm_response[32]}" != "total" \
+ || "${phpfpm_response[43]}" != "slow" \
+ ]]
+ then
+ echo >&2 "phpfpm: invalid response from phpfpm status server: ${phpfpm_response[*]}"
+ return 1
+ fi
+
+ phpfpm_pool="${phpfpm_response[1]}"
+ phpfpm_start_time="${phpfpm_response[7]} ${phpfpm_response[8]}"
+ phpfpm_start_since="${phpfpm_response[11]}"
+ phpfpm_accepted_conn="${phpfpm_response[14]}"
+ phpfpm_listen_queue="${phpfpm_response[17]}"
+ phpfpm_max_listen_queue="${phpfpm_response[21]}"
+ phpfpm_listen_queue_len="${phpfpm_response[25]}"
+ phpfpm_idle_processes="${phpfpm_response[28]}"
+ phpfpm_active_processes="${phpfpm_response[31]}"
+ phpfpm_total_processes="${phpfpm_response[34]}"
+ phpfpm_max_active_processes="${phpfpm_response[38]}"
+ phpfpm_max_children_reached="${phpfpm_response[42]}"
+ phpfpm_slow_requests="${phpfpm_response[45]}"
+
+ if [[ -z "${phpfpm_pool}" \
+ || -z "${phpfpm_start_time}" \
+ || -z "${phpfpm_start_since}" \
+ || -z "${phpfpm_accepted_conn}" \
+ || -z "${phpfpm_listen_queue}" \
+ || -z "${phpfpm_max_listen_queue}" \
+ || -z "${phpfpm_listen_queue_len}" \
+ || -z "${phpfpm_idle_processes}" \
+ || -z "${phpfpm_active_processes}" \
+ || -z "${phpfpm_total_processes}" \
+ || -z "${phpfpm_max_active_processes}" \
+ || -z "${phpfpm_max_children_reached}" \
+ || -z "${phpfpm_slow_requests}" \
+ ]]
+ then
+ echo >&2 "phpfpm: empty values got from phpfpm status server: ${phpfpm_response[*]}"
+ return 1
+ fi
+
+ return 0
+}
+
+# _check is called once, to find out if this chart should be enabled or not
+phpfpm_check() {
+ if [ ${#phpfpm_urls[@]} -eq 0 ]; then
+ phpfpm_urls[local]="http://localhost/status"
+ fi
+
+ local m
+ for m in "${!phpfpm_urls[@]}"
+ do
+ phpfpm_get "${phpfpm_urls[$m]}"
+ if [ $? -ne 0 ]; then
+ echo >&2 "phpfpm: cannot find status on URL '${phpfpm_url[$m]}'. Please set phpfpm_urls[$m]='http://localhost/status' in $confd/phpfpm.conf"
+ unset phpfpm_urls[$m]
+ continue
+ fi
+ done
+
+ if [ ${#phpfpm_urls[@]} -eq 0 ]; then
+ echo >&2 "phpfpm: no phpfpm servers found. Please set phpfpm_urls[name]='url' to whatever needed to get status to the phpfpm server, in $confd/phpfpm.conf"
+ return 1
+ fi
+
+ # this should return:
+ # - 0 to enable the chart
+ # - 1 to disable the chart
+
+ return 0
+}
+
+# _create is called once, to create the charts
+phpfpm_create() {
+ local m
+ for m in "${!phpfpm_urls[@]}"
+ do
+ cat <<EOF
+CHART phpfpm_$m.connections '' "PHP-FPM Active Connections" "connections" phpfpm phpfpm.connections line $[phpfpm_priority + 1] $phpfpm_update_every
+DIMENSION active '' absolute 1 1
+DIMENSION maxActive 'max active' absolute 1 1
+DIMENSION idle '' absolute 1 1
+
+CHART phpfpm_$m.requests '' "PHP-FPM Requests" "requests/s" phpfpm phpfpm.requests line $[phpfpm_priority + 2] $phpfpm_update_every
+DIMENSION requests '' incremental 1 1
+
+CHART phpfpm_$m.performance '' "PHP-FPM Performance" "status" phpfpm phpfpm.performance line $[phpfpm_priority + 3] $phpfpm_update_every
+DIMENSION reached 'max children reached' absolute 1 1
+DIMENSION slow 'slow requests' absolute 1 1
+EOF
+ done
+
+ return 0
+}
+
+# _update is called continiously, to collect the values
+phpfpm_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
+
+ local m
+ for m in "${!phpfpm_urls[@]}"
+ do
+ phpfpm_get "${phpfpm_urls[$m]}"
+ if [ $? -ne 0 ]; then
+ continue
+ fi
+
+ # write the result of the work.
+ cat <<EOF
+BEGIN phpfpm_$m.connections $1
+SET active = $[phpfpm_active_processes]
+SET maxActive = $[phpfpm_max_active_processes]
+SET idle = $[phpfpm_idle_processes]
+END
+BEGIN phpfpm_$m.requests $1
+SET requests = $[phpfpm_accepted_conn]
+END
+BEGIN phpfpm_$m.performance $1
+SET reached = $[phpfpm_max_children_reached]
+SET slow = $[phpfpm_slow_requests]
+END
+EOF
+ done
+
+ return 0
+}
--- /dev/null
+#!/bin/bash
+
+# Description: Tomcat netdata charts.d plugin
+# Author: Jorge Romero
+
+# the URL to download tomcat status info
+tomcat_url="http://localhost:8080/manager/status?XML=true"
+
+# _update_every is a special variable - it holds the number of seconds
+# between the calls of the _update() function
+tomcat_update_every=
+
+tomcat_priority=60000
+
+# convert tomcat floating point values
+# to integer using this multiplier
+# this only affects precision - the values
+# will be in the proper units
+tomcat_decimal_detail=1000000
+
+# used by volume chart to convert bytes to KB
+tomcat_decimal_KB_detail=1000
+
+tomcat_check() {
+
+ require_cmd xmlstarlet || return 1
+
+ tomcat_get
+ if [ $? -ne 0 ]
+ then
+ echo >&2 "tomcat: cannot find stub_status on URL '${tomcat_url}'. Please set tomcat_url='http://<user>:<password>@localhost:8080/manager/status?XML=true'"
+ return 1
+ fi
+
+ # this should return:
+ # - 0 to enable the chart
+ # - 1 to disable the chart
+
+ return 0
+}
+
+tomcat_get() {
+ # Collect tomcat values
+ mapfile -t lines < <(curl -Ss "$tomcat_url" |\
+ xmlstarlet sel \
+ -t -m "/status/jvm/memory" -v @free \
+ -n -m "/status/connector[@name='\"http-bio-8080\"']/threadInfo" -v @currentThreadCount \
+ -n -v @currentThreadsBusy \
+ -n -m "/status/connector[@name='\"http-bio-8080\"']/requestInfo" -v @requestCount \
+ -n -v @bytesSent -n -)
+
+ tomcat_jvm_freememory="${lines[0]}"
+ tomcat_threads="${lines[1]}"
+ tomcat_threads_busy="${lines[2]}"
+ tomcat_accesses="${lines[3]}"
+ tomcat_volume="${lines[4]}"
+
+ return 0
+}
+
+# _create is called once, to create the charts
+tomcat_create() {
+ cat <<EOF
+CHART tomcat.accesses '' "tomcat requests" "requests/s" statistics tomcat.accesses area $[tomcat_priority + 8] $tomcat_update_every
+DIMENSION accesses '' incremental
+CHART tomcat.volume '' "tomcat volume" "KB/s" volume tomcat.volume area $[tomcat_priority + 5] $tomcat_update_every
+DIMENSION volume '' incremental divisor ${tomcat_decimal_KB_detail}
+CHART tomcat.threads '' "tomcat threads" "current threads" statistics tomcat.threads line $[tomcat_priority + 6] $tomcat_update_every
+DIMENSION current '' absolute 1
+DIMENSION busy '' absolute 1
+CHART tomcat.jvm '' "JVM Free Memory" "MB" statistics tomcat.jvm area $[tomcat_priority + 8] $tomcat_update_every
+DIMENSION jvm '' absolute 1 ${tomcat_decimal_detail}
+EOF
+ return 0
+}
+
+# _update is called continiously, to collect the values
+tomcat_update() {
+ local reqs net
+ # 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
+
+ tomcat_get || return 1
+
+ # write the result of the work.
+ cat <<VALUESEOF
+BEGIN tomcat.accesses $1
+SET accesses = $[tomcat_accesses]
+END
+BEGIN tomcat.volume $1
+SET volume = $[tomcat_volume]
+END
+BEGIN tomcat.threads $1
+SET current = $[tomcat_threads]
+SET busy = $[tomcat_threads_busy]
+END
+BEGIN tomcat.jvm $1
+SET jvm = $[tomcat_jvm_freememory]
+END
+VALUESEOF
+
+ return 0
+}
AC_PREREQ(2.60)
define([VERSION_MAJOR], [1])
-define([VERSION_MINOR], [0])
+define([VERSION_MINOR], [1])
define([VERSION_FIX], [1])
define([VERSION_NUMBER], VERSION_MAJOR[.]VERSION_MINOR[.]VERSION_FIX)
define([VERSION_SUFFIX], [_master])
dnl Set to "1" for a first RPM release of a new version
-PACKAGE_RPM_RELEASE="0.0.$(echo VERSION_SUFFIX | sed 's/^_//')"
+PACKAGE_RPM_RELEASE="0.0.$(echo VERSION_SUFFIX | sed s/^_//)"
AC_INIT([netdata], VERSION_NUMBER[]VERSION_SUFFIX)
src/Makefile
system/Makefile
web/Makefile
+ contrib/Makefile
])
AC_OUTPUT
--- /dev/null
+MAINTAINERCLEANFILES= $(srcdir)/Makefile.in
+
+dist_noinst_DATA = \
+ README.md \
+ debian/copyright \
+ debian/netdata.conf \
+ debian/source/format \
+ debian/compat \
+ debian/netdata.install \
+ debian/netdata.lintian-overrides \
+ debian/rules \
+ debian/netdata.docs \
+ debian/netdata.default \
+ debian/control \
+ debian/netdata.postinst.in \
+ debian/netdata.service \
+ debian/changelog \
+ debian/netdata.postrm \
+ $(NULL)
+
+dist_noinst_SCRIPTS = \
+ debian/netdata.init \
+ $(NULL)
--- /dev/null
+# netdata contrib
+
+## Building .deb packages
+
+The `contrib/debian/` directory contains basic rules to build a
+Debian package. It has been tested on Debian Jessie and Wheezy,
+but should work, possibly with minor changes, if you have other
+dpkg-based systems such as Ubuntu or Mint.
+
+To build netdata for a Debian Jessie system, the debian directory
+has to be available in the root of the netdata source. The easiest
+way to do this is with a symlink:
+
+ ~/netdata$ ln -s contrib/debian
+
+Then build the debian package:
+
+ ~/netdata$ dpkg-buildpackage -us -uc -rfakeroot
+
+This should give a package that can be installed in the parent
+directory, which you can install manually with dpkg.
+
+ ~/netdata$ ls ../*.deb
+ ../netdata_1.0.0_amd64.deb
+ ~/netdata$ sudo dpkg -i ../netdata_1.0.0_amd64.deb
+
+
+### Building for a Debian system without systemd
+
+The included packaging is designed for modern Debian systems that
+are based on systemd. To build non-systemd packages (for example,
+for Debian wheezy), you will need to make a couple of minor
+updates first.
+
+* edit `contrib/debian/rules` and adjust the `dh` rule near the
+ top to remove systemd (see comments in that file).
+
+* edit `contrib/debian/control`: remove `dh-systemd` from the
+ Build-Depends list, and add `pkg-config` to it.
+
+Then proceed as the main instructions above.
+
+### Reinstalling netdata
+
+The recommended way to upgrade netdata packages built from this
+source is to remove the current package from your system, then
+install the new package. Upgrading on wheezy is known to not
+work cleanly; Jessie may behave as expected.
+
--- /dev/null
+netdata (1.0.0) UNRELEASED; urgency=medium
+
+ * Initial release.
+
+ -- Matthew Newton <mcn4@leicester.ac.uk> Fri, 01 Apr 2016 17:24:11 +0100
--- /dev/null
+Source: netdata
+Build-Depends: debhelper (>= 9),
+ dh-autoreconf,
+ dh-systemd (>= 1.5),
+ dpkg-dev (>= 1.13.19),
+ zlib1g-dev
+Section: net
+Priority: optional
+Maintainer: Costa Tsaousis <costa@tsaousis.gr>
+Standards-Version: 3.9.6
+Homepage: https://github.com/firehol/netdata/wiki
+
+Package: netdata
+Architecture: any
+Depends: adduser,
+ libcap2-bin (>= 1:2.0),
+ lsb-base (>= 3.1-23.2),
+ ${misc:Depends},
+ ${shlibs:Depends}
+Description: real-time charts for system monitoring
+ Netdata is a daemon that collects data in realtime (per second)
+ and presents a web site to view and analyze them. The presentation
+ is also real-time and full of interactive charts that precisely
+ render all collected values.
--- /dev/null
+Format: http://www.debian.org/doc/packaging-manuals/copyright-format/1.0/
+Upstream-Name: Netdata
+Upstream-Contact: Costa Tsaousis <costa@tsaousis.gr>
+Source: https://github.com/firehol/netdata
+
+Files: *
+Copyright: 2014-2016, Costa Tsaousis
+License: GPL-3+
+ On Debian systems, the complete text of the GNU General Public
+ License version 3 can be found in /usr/share/common-licenses/GPL-3.
--- /dev/null
+# NetData Configuration
+
+# The current full configuration can be retrieved from the running
+# server at the URL
+#
+# http://localhost:19999/netdata.conf
+#
+# for example:
+#
+# wget -O /etc/netdata/netdata.conf http://localhost:19999/netdata.conf
+#
+
+[global]
+ run as user = netdata
+ web files owner = root
+ web files group = netdata
--- /dev/null
+# Extra arguments to pass to netdata
+#
+#EXTRA_OPTS=""
+
--- /dev/null
+#!/bin/sh
+# Start/stop the netdata daemon.
+#
+### BEGIN INIT INFO
+# Provides: netdata
+# Required-Start: $remote_fs
+# Required-Stop: $remote_fs
+# Should-Start: $network
+# Should-Stop: $network
+# Default-Start: 2 3 4 5
+# Default-Stop:
+# Short-Description: Real-time charts for system monitoring
+# Description: Netdata is a daemon that collects data in realtime (per second)
+# and presents a web site to view and analyze them. The presentation
+# is also real-time and full of interactive charts that precisely
+# render all collected values.
+### END INIT INFO
+
+PATH=/bin:/usr/bin:/sbin:/usr/sbin
+DESC="netdata daemon"
+NAME=netdata
+DAEMON=/usr/sbin/netdata
+PIDFILE=/var/run/netdata/netdata.pid
+SCRIPTNAME=/etc/init.d/"$NAME"
+
+test -f $DAEMON || exit 0
+
+. /lib/lsb/init-functions
+
+[ -r /etc/default/netdata ] && . /etc/default/netdata
+
+case "$1" in
+start) log_daemon_msg "Starting real-time system monitoring" "netdata"
+ start_daemon -p $PIDFILE $DAEMON $EXTRA_OPTS
+ log_end_msg $?
+ ;;
+stop) log_daemon_msg "Stopping real-time system monitoring" "netdata"
+ killproc -p $PIDFILE $DAEMON
+ RETVAL=$?
+ [ $RETVAL -eq 0 ] && [ -e "$PIDFILE" ] && rm -f $PIDFILE
+ log_end_msg $RETVAL
+ # wait for plugins to exit
+ sleep 1
+ ;;
+restart|force-reload) log_daemon_msg "Restarting real-time system monitoring" "netdata"
+ $0 stop
+ $0 start
+ ;;
+status)
+ status_of_proc -p $PIDFILE $DAEMON $NAME && exit 0 || exit $?
+ ;;
+*) log_action_msg "Usage: /etc/init.d/cron {start|stop|status|restart|force-reload}"
+ exit 2
+ ;;
+esac
+exit 0
--- /dev/null
+debian/netdata.conf /etc/netdata/
--- /dev/null
+
+# See Debian policy 10.9. apps.plugin has extra capabilities, so don't let
+# normal users run it.
+netdata: non-standard-executable-perm usr/lib/*/netdata/plugins.d/apps.plugin 0754 != 0755
+
+
+# FontAwesome is at least in the fonts-font-awesome package, but this is
+# not available in wheezy. glyphicons-halflings-regular isn't currently in
+# a Debian package. Therefore don't complain about shipping them with netdata
+# for the time being.
+netdata: duplicate-font-file usr/share/netdata/fonts/*
+netdata: font-in-non-font-package usr/share/netdata/fonts/*
+
+# Files here are marked as conffiles so that local updates to the html files
+# isn't clobbered on upgrade.
+netdata: non-etc-file-marked-as-conffile var/lib/netdata/www/*
--- /dev/null
+#! /bin/sh
+
+set -e
+
+case "$1" in
+ configure)
+ if [ -z "$2" ]; then
+ if ! getent group netdata >/dev/null; then
+ addgroup --quiet --system netdata
+ fi
+
+ if ! getent passwd netdata >/dev/null; then
+ adduser --quiet --system --ingroup netdata --home /var/lib/netdata --no-create-home netdata
+ fi
+
+ if ! dpkg-statoverride --list /var/lib/netdata >/dev/null 2>&1; then
+ dpkg-statoverride --update --add root netdata 0755 /var/lib/netdata
+ fi
+
+ if ! dpkg-statoverride --list /var/lib/netdata/www >/dev/null 2>&1; then
+ dpkg-statoverride --update --add root netdata 0755 /var/lib/netdata/www
+ fi
+
+ if ! dpkg-statoverride --list /var/cache/netdata >/dev/null 2>&1; then
+ dpkg-statoverride --update --add netdata netdata 0755 /var/cache/netdata
+ fi
+
+ fi
+
+ chown -R root:netdata /usr/share/netdata/*
+ chown -R root:netdata /usr/lib/@DEB_HOST_MULTIARCH@/netdata/plugins.d
+ setcap cap_dac_read_search,cap_sys_ptrace+ep /usr/lib/@DEB_HOST_MULTIARCH@/netdata/plugins.d/apps.plugin
+
+#PERMS#
+ ;;
+esac
+
+#DEBHELPER#
+
+exit 0
+
--- /dev/null
+#! /bin/sh
+
+set -e
+
+case "$1" in
+ remove)
+ ;;
+
+ purge)
+ if dpkg-statoverride --list | grep -qw /var/cache/netdata; then
+ dpkg-statoverride --remove /var/cache/netdata
+ fi
+
+ if dpkg-statoverride --list | grep -qw /var/lib/netdata/www; then
+ dpkg-statoverride --remove /var/lib/netdata/www
+ fi
+
+ if dpkg-statoverride --list | grep -qw /var/lib/netdata; then
+ dpkg-statoverride --remove /var/lib/netdata
+ fi
+
+ if getent passwd netdata >/dev/null; then
+ if [ -x /usr/sbin/deluser ]; then
+ deluser --quiet --system netdata || echo "Unable to remove netdata user"
+ fi
+ fi
+
+ if getent group netdata >/dev/null; then
+ if [ -x /usr/sbin/delgroup ]; then
+ delgroup --quiet --system netdata || echo "Unable to remove netdata group"
+ fi
+ fi
+
+ ;;
+
+ *)
+ ;;
+esac
+
+#DEBHELPER#
+
+exit 0
+
--- /dev/null
+[Unit]
+Description=netdata real-time system monitoring
+After=network.target
+
+[Service]
+Type=simple
+EnvironmentFile=-/etc/default/netdata
+ExecStart=/usr/sbin/netdata -nd $EXTRA_OPTS
+TimeoutStopSec=30
+Restart=always
+RestartSec=5
+
+[Install]
+WantedBy=multi-user.target
--- /dev/null
+#!/usr/bin/make -f
+
+# Find the arch we are building for, as this determines
+# the location of plugins in /usr/lib
+DEB_HOST_MULTIARCH ?= $(shell dpkg-architecture -qDEB_HOST_MULTIARCH)
+TOP = $(CURDIR)/debian/netdata
+
+%:
+ # For jessie and beyond
+ #
+ dh $@ --with autoreconf,systemd
+
+ # For wheezy or other non-systemd distributions use the following. You
+ # should also see contrib/README.md which gives details of updates to
+ # make to debian/control.
+ #
+ #dh $@ --with autoreconf
+
+override_dh_auto_configure:
+ dh_auto_configure -- --with-math --with-webdir=/var/lib/netdata/www
+
+debian/%.postinst: debian/%.postinst.in
+ sed 's/@DEB_HOST_MULTIARCH@/$(DEB_HOST_MULTIARCH)/g' $< > $@
+
+override_dh_install: debian/netdata.postinst
+ dh_install
+
+ # Remove unneeded .keep files
+ #
+ find "$(TOP)" -name .keep -exec rm '{}' ';'
+
+ # Move files that local user shouldn't be editing to /usr/share/netdata
+ #
+ mkdir -p "$(TOP)/usr/share/netdata"
+ for D in $$(find "$(TOP)/var/lib/netdata/www/" -maxdepth 1 -type d -printf '%f '); do \
+ echo Relocating $$D; \
+ mv "$(TOP)/var/lib/netdata/www/$$D" "$(TOP)/usr/share/netdata/$$D"; \
+ ln -s "/usr/share/netdata/$$D" "$(TOP)/var/lib/netdata/www/$$D"; \
+ done
+
+ # Update postinst to set correct group for www files on installation.
+ # Should probably be dpkg-statoverride really, but that gets *really*
+ # messy. We also set all web files in /var as conffiles so an upgrade
+ # doesn't splat them.
+ #
+ for D in $$(find "$(TOP)/var/lib/netdata/www/" -maxdepth 1 -type f -printf '%f '); do \
+ echo Updating postinst for $$D; \
+ sed -i "s/^#PERMS#/chgrp netdata \/var\/lib\/netdata\/www\/$$D\n#PERMS#/g" \
+ $(CURDIR)/debian/netdata.postinst; \
+ echo "/var/lib/netdata/www/$$D" >> $(CURDIR)/debian/netdata.conffiles; \
+ done
+ sed -i "/^#PERMS#/d" $(CURDIR)/debian/netdata.postinst
+
+override_dh_installdocs:
+ dh_installdocs
+
+ # Docs should not be under /usr/lib
+ #
+ mv $(TOP)/usr/lib/$(DEB_HOST_MULTIARCH)/netdata/plugins.d/README.md \
+ $(TOP)/usr/share/doc/netdata/README.plugins.md
+ mv $(TOP)/usr/lib/$(DEB_HOST_MULTIARCH)/netdata/charts.d/README.md \
+ $(TOP)/usr/share/doc/netdata/README.charts.md
+
+ # This doc is currently empty, so no point installing it.
+ #
+ rm $(TOP)/usr/lib/$(DEB_HOST_MULTIARCH)/netdata/node.d/README.md
+
+override_dh_fixperms:
+ dh_fixperms
+
+ # apps.plugin should only be runnable by the netdata user. It will be
+ # given extra capabilities in the postinst script.
+ #
+ chmod 0754 $(TOP)/usr/lib/$(DEB_HOST_MULTIARCH)/netdata/plugins.d/apps.plugin
+
+override_dh_installlogrotate:
+ cp system/netdata.logrotate debian/netdata.logrotate
+ dh_installlogrotate
+
+override_dh_clean:
+ dh_clean
+
+ # Tidy up copied/generated files
+ #
+ -[ -r $(CURDIR)/debian/netdata.logrotate ] && rm $(CURDIR)/debian/netdata.logrotate
+ -[ -r $(CURDIR)/debian/netdata.postinst ] && rm $(CURDIR)/debian/netdata.postinst
+ -[ -r $(CURDIR)/debian/netdata.conffiles ] && rm $(CURDIR)/debian/netdata.conffiles
--- /dev/null
+3.0 (native)
# reload the user profile
[ -f /etc/profile ] && . /etc/profile
+# fix PKG_CHECK_MODULES error
+if [ -d /usr/share/aclocal ]
+then
+ ACLOCAL_PATH=${ACLOCAL_PATH-/usr/share/aclocal}
+ export ACLOCAL_PATH
+fi
+
LC_ALL=C
# you can set CFLAGS before running installer
%undefine with_systemd
%endif
-Summary: Linux real time system monitoring, over the web
+Summary: Real-time performance monitoring, done right
Name: @PACKAGE_NAME@
Version: @PACKAGE_RPM_VERSION@
Release: @PACKAGE_RPM_RELEASE@%{?release_suffix}%{?dist}
%{_datadir}/%{name}/web
%changelog
+* Wed Apr 20 2016 Costa Tsaousis <costa@tsaousis.gr> - 1.1.0-1
+- Several new features (IPv6, SYNPROXY, Users, Users Groups).
+- A lot of bug fixes and optimizations.
* Tue Mar 22 2016 Costa Tsaousis <costa@tsaousis.gr> - 1.0.0-1
- First public release.
* Sun Nov 15 2015 Alon Bar-Lev <alonbl@redhat.com> - 0.0.0-1
-e '/: unittest$/d' \
-e '/: iprange$/d' \
-e '/: .*\.o$/d' \
+ -e '/: CMakeLists.txt/d' \
+ -e '/: .travis.yml/d' \
-e '/sbin: \(firehol\|fireqos\|link-balancer\)$/d' \
-e '/sbin: \(update-ipsets\|vnetbuild\|commands.sed\)$/d' > $MYTMP/out
#endif /* NETDATA_INTERNAL_CHECKS */
-
// ----------------------------------------------------------------------------
// system functions
// to retrieve settings of the system
else
snprintf(w->name, MAX_NAME, "%s", pw->pw_name);
+ netdata_fix_id(w->name);
+
w->uid = uid;
w->next = users_root_target;
else
snprintf(w->name, MAX_NAME, "%s", gr->gr_name);
+ netdata_fix_id(w->name);
+
w->gid = gid;
w->next = groups_root_target;
#include "log.h"
#include "common.h"
#include "appconfig.h"
+#include "../config.h"
char *global_host_prefix = "";
int enable_ksm = 1;
+unsigned char netdata_keys_map[256] = {
+ [0] = '\0', //
+ [1] = '_', //
+ [2] = '_', //
+ [3] = '_', //
+ [4] = '_', //
+ [5] = '_', //
+ [6] = '_', //
+ [7] = '_', //
+ [8] = '_', //
+ [9] = '_', //
+ [10] = '_', //
+ [11] = '_', //
+ [12] = '_', //
+ [13] = '_', //
+ [14] = '_', //
+ [15] = '_', //
+ [16] = '_', //
+ [17] = '_', //
+ [18] = '_', //
+ [19] = '_', //
+ [20] = '_', //
+ [21] = '_', //
+ [22] = '_', //
+ [23] = '_', //
+ [24] = '_', //
+ [25] = '_', //
+ [26] = '_', //
+ [27] = '_', //
+ [28] = '_', //
+ [29] = '_', //
+ [30] = '_', //
+ [31] = '_', //
+ [32] = '_', //
+ [33] = '_', // !
+ [34] = '_', // "
+ [35] = '_', // #
+ [36] = '_', // $
+ [37] = '_', // %
+ [38] = '_', // &
+ [39] = '_', // '
+ [40] = '_', // (
+ [41] = '_', // )
+ [42] = '_', // *
+ [43] = '_', // +
+ [44] = '.', // ,
+ [45] = '-', // -
+ [46] = '.', // .
+ [47] = '/', // /
+ [48] = '0', // 0
+ [49] = '1', // 1
+ [50] = '2', // 2
+ [51] = '3', // 3
+ [52] = '4', // 4
+ [53] = '5', // 5
+ [54] = '6', // 6
+ [55] = '7', // 7
+ [56] = '8', // 8
+ [57] = '9', // 9
+ [58] = '_', // :
+ [59] = '_', // ;
+ [60] = '_', // <
+ [61] = '_', // =
+ [62] = '_', // >
+ [63] = '_', // ?
+ [64] = '_', // @
+ [65] = 'a', // A
+ [66] = 'b', // B
+ [67] = 'c', // C
+ [68] = 'd', // D
+ [69] = 'e', // E
+ [70] = 'f', // F
+ [71] = 'g', // G
+ [72] = 'h', // H
+ [73] = 'i', // I
+ [74] = 'j', // J
+ [75] = 'k', // K
+ [76] = 'l', // L
+ [77] = 'm', // M
+ [78] = 'n', // N
+ [79] = 'o', // O
+ [80] = 'p', // P
+ [81] = 'q', // Q
+ [82] = 'r', // R
+ [83] = 's', // S
+ [84] = 't', // T
+ [85] = 'u', // U
+ [86] = 'v', // V
+ [87] = 'w', // W
+ [88] = 'x', // X
+ [89] = 'y', // Y
+ [90] = 'z', // Z
+ [91] = '_', // [
+ [92] = '/', // backslash
+ [93] = '_', // ]
+ [94] = '_', // ^
+ [95] = '_', // _
+ [96] = '_', // `
+ [97] = 'a', // a
+ [98] = 'b', // b
+ [99] = 'c', // c
+ [100] = 'd', // d
+ [101] = 'e', // e
+ [102] = 'f', // f
+ [103] = 'g', // g
+ [104] = 'h', // h
+ [105] = 'i', // i
+ [106] = 'j', // j
+ [107] = 'k', // k
+ [108] = 'l', // l
+ [109] = 'm', // m
+ [110] = 'n', // n
+ [111] = 'o', // o
+ [112] = 'p', // p
+ [113] = 'q', // q
+ [114] = 'r', // r
+ [115] = 's', // s
+ [116] = 't', // t
+ [117] = 'u', // u
+ [118] = 'v', // v
+ [119] = 'w', // w
+ [120] = 'x', // x
+ [121] = 'y', // y
+ [122] = 'z', // z
+ [123] = '_', // {
+ [124] = '_', // |
+ [125] = '_', // }
+ [126] = '_', // ~
+ [127] = '_', //
+ [128] = '_', //
+ [129] = '_', //
+ [130] = '_', //
+ [131] = '_', //
+ [132] = '_', //
+ [133] = '_', //
+ [134] = '_', //
+ [135] = '_', //
+ [136] = '_', //
+ [137] = '_', //
+ [138] = '_', //
+ [139] = '_', //
+ [140] = '_', //
+ [141] = '_', //
+ [142] = '_', //
+ [143] = '_', //
+ [144] = '_', //
+ [145] = '_', //
+ [146] = '_', //
+ [147] = '_', //
+ [148] = '_', //
+ [149] = '_', //
+ [150] = '_', //
+ [151] = '_', //
+ [152] = '_', //
+ [153] = '_', //
+ [154] = '_', //
+ [155] = '_', //
+ [156] = '_', //
+ [157] = '_', //
+ [158] = '_', //
+ [159] = '_', //
+ [160] = '_', //
+ [161] = '_', //
+ [162] = '_', //
+ [163] = '_', //
+ [164] = '_', //
+ [165] = '_', //
+ [166] = '_', //
+ [167] = '_', //
+ [168] = '_', //
+ [169] = '_', //
+ [170] = '_', //
+ [171] = '_', //
+ [172] = '_', //
+ [173] = '_', //
+ [174] = '_', //
+ [175] = '_', //
+ [176] = '_', //
+ [177] = '_', //
+ [178] = '_', //
+ [179] = '_', //
+ [180] = '_', //
+ [181] = '_', //
+ [182] = '_', //
+ [183] = '_', //
+ [184] = '_', //
+ [185] = '_', //
+ [186] = '_', //
+ [187] = '_', //
+ [188] = '_', //
+ [189] = '_', //
+ [190] = '_', //
+ [191] = '_', //
+ [192] = '_', //
+ [193] = '_', //
+ [194] = '_', //
+ [195] = '_', //
+ [196] = '_', //
+ [197] = '_', //
+ [198] = '_', //
+ [199] = '_', //
+ [200] = '_', //
+ [201] = '_', //
+ [202] = '_', //
+ [203] = '_', //
+ [204] = '_', //
+ [205] = '_', //
+ [206] = '_', //
+ [207] = '_', //
+ [208] = '_', //
+ [209] = '_', //
+ [210] = '_', //
+ [211] = '_', //
+ [212] = '_', //
+ [213] = '_', //
+ [214] = '_', //
+ [215] = '_', //
+ [216] = '_', //
+ [217] = '_', //
+ [218] = '_', //
+ [219] = '_', //
+ [220] = '_', //
+ [221] = '_', //
+ [222] = '_', //
+ [223] = '_', //
+ [224] = '_', //
+ [225] = '_', //
+ [226] = '_', //
+ [227] = '_', //
+ [228] = '_', //
+ [229] = '_', //
+ [230] = '_', //
+ [231] = '_', //
+ [232] = '_', //
+ [233] = '_', //
+ [234] = '_', //
+ [235] = '_', //
+ [236] = '_', //
+ [237] = '_', //
+ [238] = '_', //
+ [239] = '_', //
+ [240] = '_', //
+ [241] = '_', //
+ [242] = '_', //
+ [243] = '_', //
+ [244] = '_', //
+ [245] = '_', //
+ [246] = '_', //
+ [247] = '_', //
+ [248] = '_', //
+ [249] = '_', //
+ [250] = '_', //
+ [251] = '_', //
+ [252] = '_', //
+ [253] = '_', //
+ [254] = '_', //
+ [255] = '_' //
+};
+
+// make sure the supplied string
+// is good for a netdata chart/dimension ID/NAME
+void netdata_fix_id(char *s) {
+ while((*s = netdata_keys_map[(unsigned char)*s])) s++;
+}
+
/*
// http://stackoverflow.com/questions/7666509/hash-function-for-string
uint32_t simple_hash(const char *name)
#define abs(x) ((x < 0)? -x : x)
#define usecdiff(now, last) (((((now)->tv_sec * 1000000ULL) + (now)->tv_usec) - (((last)->tv_sec * 1000000ULL) + (last)->tv_usec)))
+extern void netdata_fix_id(char *s);
+
extern uint32_t simple_hash(const char *name);
extern void strreverse(char* begin, char* end);
extern char *mystrsep(char **ptr, char *s);
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
#include "common.h"
#include "log.h"
#define RRD_TYPE_DISK "disk"
+struct disk {
+ unsigned long major;
+ unsigned long minor;
+ int partition_id; // -1 = this is not a partition
+ struct disk *next;
+} *disk_root = NULL;
+
+struct disk *get_disk(unsigned long major, unsigned long minor) {
+ static char path_find_block_device_partition[FILENAME_MAX + 1] = "";
+ struct disk *d;
+
+ // search for it in our RAM list.
+ // this is sequential, but since we just walk through
+ // and the number of disks / partitions in a system
+ // should not be that many, it should be acceptable
+ for(d = disk_root; d ; d = d->next)
+ if(unlikely(d->major == major && d->minor == minor))
+ break;
+
+ // if we found it, return it
+ if(likely(d))
+ return d;
+
+ if(unlikely(!path_find_block_device_partition[0])) {
+ char filename[FILENAME_MAX + 1];
+ snprintf(filename, FILENAME_MAX, "%s%s", global_host_prefix, "/sys/dev/block/%lu:%lu/partition");
+ snprintf(path_find_block_device_partition, FILENAME_MAX, "%s", config_get("plugin:proc:/proc/diskstats", "path to get block device partition", filename));
+ }
+
+ // not found
+ // create a new disk structure
+ d = (struct disk *)malloc(sizeof(struct disk));
+ if(!d) fatal("Cannot allocate memory for struct disk in proc_diskstats.");
+
+ d->major = major;
+ d->minor = minor;
+ d->partition_id = -1;
+ d->next = NULL;
+
+ // append it to the list
+ if(!disk_root)
+ disk_root = d;
+ else {
+ struct disk *last;
+ for(last = disk_root; last->next ;last = last->next);
+ last->next = d;
+ }
+
+ // find if it is a partition
+ // by reading /sys/dev/block/MAJOR:MINOR/partition
+ char buffer[FILENAME_MAX + 1];
+ snprintf(buffer, FILENAME_MAX, path_find_block_device_partition, major, minor);
+
+ int fd = open(buffer, O_RDONLY, 0666);
+ if(likely(fd != -1)) {
+ // we opened it
+ int bytes = read(fd, buffer, FILENAME_MAX);
+ close(fd);
+
+ if(bytes > 0)
+ d->partition_id = strtoul(buffer, NULL, 10);
+ }
+ // if the /partition file does not exist, it is a disk, not a partition
+
+ return d;
+}
+
int do_proc_diskstats(int update_every, unsigned long long dt) {
static procfile *ff = NULL;
static char path_to_get_hw_sector_size[FILENAME_MAX + 1] = "";
if(!path_to_get_hw_sector_size[0]) {
char filename[FILENAME_MAX + 1];
snprintf(filename, FILENAME_MAX, "%s%s", global_host_prefix, "/sys/block/%s/queue/hw_sector_size");
- snprintf(path_to_get_hw_sector_size, FILENAME_MAX, "%s%s", global_host_prefix, config_get("plugin:proc:/proc/diskstats", "path to get h/w sector size", filename));
+ snprintf(path_to_get_hw_sector_size, FILENAME_MAX, "%s", config_get("plugin:proc:/proc/diskstats", "path to get h/w sector size", filename));
}
ff = procfile_readall(ff);
// I/O completion time and the backlog that may be accumulating.
backlog_ms = strtoull(procfile_lineword(ff, l, 13), NULL, 10); // rq_ticks
-
int def_enabled = 0;
// remove slashes from disk names
char *s;
for(s = disk; *s ;s++) if(*s == '/') *s = '_';
+ struct disk *d = get_disk(major, minor);
+ if(d->partition_id == -1)
+ def_enabled = enable_new_disks;
+ else
+ def_enabled = 0;
+
+/*
switch(major) {
case 9: // MDs
case 43: // network block
case 135: // scsi
case 153: // raid
case 202: // xen
+ case 254: // virtio3
case 256: // flash
case 257: // flash
case 259: // nvme0n1 issue #119
def_enabled = 0;
break;
}
+*/
int ddo_io = do_io, ddo_ops = do_ops, ddo_mops = do_mops, ddo_iotime = do_iotime, ddo_qops = do_qops, ddo_util = do_util, ddo_backlog = do_backlog;
// generate the local date time
struct tm tmbuf, *tm = localtime_r(&now, &tmbuf);
if(!tm) { error("localtime() failed."); continue; }
- buffer_date(wb, tm->tm_year + 1900, tm->tm_mon, tm->tm_mday, tm->tm_hour, tm->tm_min, tm->tm_sec);
+ buffer_date(wb, tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday, tm->tm_hour, tm->tm_min, tm->tm_sec);
}
if(unlikely(options & RRDR_OPTION_PERCENTAGE)) {
MAINTAINERCLEANFILES= $(srcdir)/Makefile.in
CLEANFILES = \
netdata-openrc \
+ netdata.logrotate \
netdata.service \
netdata-init-d \
$(NULL)
nodist_noinst_DATA = \
netdata-openrc \
+ netdata.logrotate \
netdata.service \
netdata-init-d \
$(NULL)
dist_noinst_DATA = \
netdata-openrc.in \
+ netdata.logrotate.in \
netdata.service.in \
netdata-init-d.in \
netdata.conf \
--- /dev/null
+@localstatedir_POST@/log/netdata/*.log {
+ daily
+ missingok
+ rotate 14
+ compress
+ delaycompress
+ notifempty
+ sharedscripts
+ postrotate
+ if service netdata status > /dev/null ; then \
+ service netdata restart > /dev/null; \
+ fi;
+ endscript
+}
+
// var netdataNoC3 = true; // do not use C3
// var netdataNoBootstrap = true; // do not load bootstrap
// var netdataDontStart = true; // do not start the thread to process the charts
+// var netdataErrorCallback = null; // Callback function that will be invoked upon error
//
// You can also set the default netdata server, using the following.
// When this variable is not set, we assume the page is hosted on your
101: { message: "Cannot load jQuery", alert: true },
402: { message: "Chart library not found", alert: false },
403: { message: "Chart library not enabled/is failed", alert: false },
- 404: { message: "Chart not found", alert: false }
+ 404: { message: "Chart not found", alert: false },
+ 405: { message: "Cannot download charts index from server", alert: true },
+ 406: { message: "Invalid charts index downloaded from server", alert: true }
};
NETDATA.errorLast = {
code: 0,
console.log("ERROR " + code + ": " + NETDATA.errorCodes[code].message + ": " + msg);
- if(NETDATA.errorCodes[code].alert)
+ var ret = true;
+ if(typeof netdataErrorCallback === 'function') {
+ ret = netdataErrorCallback('system', code, msg);
+ }
+
+ if(ret && NETDATA.errorCodes[code].alert)
alert("ERROR " + code + ": " + NETDATA.errorCodes[code].message + ": " + msg);
};
.done(function(data) {
if(data !== null) {
var h = NETDATA.chartRegistry.fixid(host);
- //console.log('downloaded all charts from ' + host + ' (' + h + ')');
self.charts[h] = data.charts;
}
+ else NETDATA.error(406, host + '/api/v1/charts');
+
if(typeof callback === 'function')
callback(data);
})
.fail(function() {
+ NETDATA.error(405, host + '/api/v1/charts');
+
if(typeof callback === 'function')
callback(null);
});
* show an error instead of the chart
*/
var error = function(msg) {
- that.element.innerHTML = that.id + ': ' + msg;
- that.enabled = false;
- that.current = that.pan;
+ var ret = true;
+
+ if(typeof netdataErrorCallback === 'function') {
+ ret = netdataErrorCallback('chart', that.id, msg);
+ }
+
+ if(ret) {
+ that.element.innerHTML = that.id + ': ' + msg;
+ that.enabled = false;
+ that.current = that.pan;
+ }
};
// GUID - a unique identifier for the chart
{
url: NETDATA.serverDefault + 'lib/bootstrap.min.js',
isAlreadyLoaded: function() {
+ // check if bootstrap is loaded
if(typeof $().emulateTransitionEnd == 'function')
return true;
else {
NETDATA._loadjQuery(function() {
NETDATA.loadRequiredJs(0, function() {
+ if(typeof $().emulateTransitionEnd == 'function') {
+ // bootstrap is not available
+ NETDATA.options.current.show_help = false;
+ }
+
if(typeof netdataDontStart === 'undefined' || !netdataDontStart) {
if(NETDATA.options.debug.main_loop === true)
console.log('starting chart refresh thread');
</script>
<!-- load the dashboard manager - it will do the rest -->
- <script type="text/javascript" src="dashboard.js?v30"></script>
+ <script type="text/javascript" src="dashboard.js?v32"></script>
</head>
<body data-spy="scroll" data-target="#sidebar">
case 'tc':
chart.menu = tmp;
- // find the interface name from the name
- if(typeof options.submenu_names[chart.family] === 'undefined' || options.submenu_names[chart.family] === chart.family)
- options.submenu_names[chart.family] = chart.name.split('.')[1].split('_')[0];
+ // find a name for this device from fireqos info
+ // we strip '_(in|out)' or '(in|out)_'
+ if(typeof options.submenu_names[chart.family] === 'undefined' || options.submenu_names[chart.family] === chart.family) {
+ var n = chart.name.split('.')[1];
+ if(n.endsWith('_in'))
+ options.submenu_names[chart.family] = n.slice(0, n.lastIndexOf('_in'));
+ else if(n.endsWith('_out'))
+ options.submenu_names[chart.family] = n.slice(0, n.lastIndexOf('_out'));
+ else if(n.startsWith('in_'))
+ options.submenu_names[chart.family] = n.slice(3, n.length);
+ else if(n.startsWith('out_'))
+ options.submenu_names[chart.family] = n.slice(4, n.length);
+ }
// increase the priority of IFB devices
+ // to have inbound appear before outbound
if(chart.id.match(/.*-ifb$/))
chart.priority--;