From: Costa Tsaousis Date: Thu, 21 Apr 2016 18:05:41 +0000 (+0300) Subject: Merge pull request #299 from fredericopissarra/master X-Git-Tag: v1.2.0~56 X-Git-Url: https://arthur.barton.de/gitweb/?p=netdata.git;a=commitdiff_plain;h=2e8dedd05e58769ecefed51e6c9fdd3d95dbadcb;hp=dc592ce38ee07cb86246ab6a3e230f76c4f48ccf Merge pull request #299 from fredericopissarra/master Now buffer_jsdate() and buffer_date() are a little bit faster. --- diff --git a/.gitignore b/.gitignore index f4b9fe85..72c79d86 100644 --- a/.gitignore +++ b/.gitignore @@ -60,6 +60,7 @@ web/version.txt system/netdata-openrc system/netdata-init-d +system/netdata.logrotate netdata-installer.log netdata-uninstaller.sh diff --git a/ChangeLog b/ChangeLog index 24403486..eae63fd9 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,29 @@ +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 diff --git a/Makefile.am b/Makefile.am index 8c7e1949..dc109cbd 100644 --- a/Makefile.am +++ b/Makefile.am @@ -35,6 +35,7 @@ SUBDIRS = \ src \ system \ web \ + contrib \ $(NULL) dist_noinst_DATA = netdata.spec diff --git a/README.md b/README.md index 59360d45..e787fa38 100644 --- a/README.md +++ b/README.md @@ -118,7 +118,7 @@ Use our **[automatic installer](https://github.com/firehol/netdata/wiki/Installa It should run on **any Linux** system. It has been tested on: - Gentoo -- ArchLinux +- Arch Linux - Ubuntu / Debian - CentOS - Fedora diff --git a/charts.d/Makefile.am b/charts.d/Makefile.am index 29b41efa..ad11e972 100644 --- a/charts.d/Makefile.am +++ b/charts.d/Makefile.am @@ -17,9 +17,11 @@ dist_charts_SCRIPTS = \ 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 = \ diff --git a/charts.d/ap.chart.sh b/charts.d/ap.chart.sh index 4704b89d..10a65688 100755 --- a/charts.d/ap.chart.sh +++ b/charts.d/ap.chart.sh @@ -1,4 +1,4 @@ -#!/bin/sh +#!/bin/bash # _update_every is a special variable - it holds the number of seconds # between the calls of the _update() function diff --git a/charts.d/apache.chart.sh b/charts.d/apache.chart.sh index efa559dd..c0fd3dc3 100755 --- a/charts.d/apache.chart.sh +++ b/charts.d/apache.chart.sh @@ -1,4 +1,4 @@ -#!/bin/sh +#!/bin/bash # the URL to download apache status info apache_url="http://127.0.0.1:80/server-status?auto" @@ -94,7 +94,7 @@ apache_detect() { 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}" diff --git a/charts.d/example.chart.sh b/charts.d/example.chart.sh index 641d03e5..34a3bc1b 100755 --- a/charts.d/example.chart.sh +++ b/charts.d/example.chart.sh @@ -1,4 +1,4 @@ -#!/bin/sh +#!/bin/bash # if this chart is called X.chart.sh, then all functions and global variables # must start with X_ diff --git a/charts.d/mysql.chart.sh b/charts.d/mysql.chart.sh index 28390528..e037aed5 100755 --- a/charts.d/mysql.chart.sh +++ b/charts.d/mysql.chart.sh @@ -1,4 +1,4 @@ -#!/bin/sh +#!/bin/bash # http://dev.mysql.com/doc/refman/5.0/en/server-status-variables.html # diff --git a/charts.d/nginx.chart.sh b/charts.d/nginx.chart.sh index bc8293c5..91f269be 100755 --- a/charts.d/nginx.chart.sh +++ b/charts.d/nginx.chart.sh @@ -1,4 +1,4 @@ -#!/bin/sh +#!/bin/bash # if this chart is called X.chart.sh, then all functions and global variables # must start with X_ @@ -19,7 +19,7 @@ nginx_reading=0 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" \ diff --git a/charts.d/phpfpm.chart.sh b/charts.d/phpfpm.chart.sh new file mode 100755 index 00000000..60e6b2c1 --- /dev/null +++ b/charts.d/phpfpm.chart.sh @@ -0,0 +1,175 @@ +#!/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 <&2 "tomcat: cannot find stub_status on URL '${tomcat_url}'. Please set tomcat_url='http://:@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 < Fri, 01 Apr 2016 17:24:11 +0100 diff --git a/contrib/debian/compat b/contrib/debian/compat new file mode 100644 index 00000000..ec635144 --- /dev/null +++ b/contrib/debian/compat @@ -0,0 +1 @@ +9 diff --git a/contrib/debian/control b/contrib/debian/control new file mode 100644 index 00000000..c0312c6c --- /dev/null +++ b/contrib/debian/control @@ -0,0 +1,24 @@ +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 +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. diff --git a/contrib/debian/copyright b/contrib/debian/copyright new file mode 100644 index 00000000..11a3d639 --- /dev/null +++ b/contrib/debian/copyright @@ -0,0 +1,10 @@ +Format: http://www.debian.org/doc/packaging-manuals/copyright-format/1.0/ +Upstream-Name: Netdata +Upstream-Contact: Costa Tsaousis +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. diff --git a/contrib/debian/netdata.conf b/contrib/debian/netdata.conf new file mode 100644 index 00000000..a963d80b --- /dev/null +++ b/contrib/debian/netdata.conf @@ -0,0 +1,16 @@ +# 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 diff --git a/contrib/debian/netdata.default b/contrib/debian/netdata.default new file mode 100644 index 00000000..eb1a6903 --- /dev/null +++ b/contrib/debian/netdata.default @@ -0,0 +1,4 @@ +# Extra arguments to pass to netdata +# +#EXTRA_OPTS="" + diff --git a/contrib/debian/netdata.docs b/contrib/debian/netdata.docs new file mode 100644 index 00000000..56631abf --- /dev/null +++ b/contrib/debian/netdata.docs @@ -0,0 +1 @@ +ChangeLog diff --git a/contrib/debian/netdata.init b/contrib/debian/netdata.init new file mode 100755 index 00000000..7403b459 --- /dev/null +++ b/contrib/debian/netdata.init @@ -0,0 +1,56 @@ +#!/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 diff --git a/contrib/debian/netdata.install b/contrib/debian/netdata.install new file mode 100644 index 00000000..45d42b63 --- /dev/null +++ b/contrib/debian/netdata.install @@ -0,0 +1 @@ +debian/netdata.conf /etc/netdata/ diff --git a/contrib/debian/netdata.lintian-overrides b/contrib/debian/netdata.lintian-overrides new file mode 100644 index 00000000..45b2d868 --- /dev/null +++ b/contrib/debian/netdata.lintian-overrides @@ -0,0 +1,16 @@ + +# 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/* diff --git a/contrib/debian/netdata.postinst.in b/contrib/debian/netdata.postinst.in new file mode 100644 index 00000000..5a4e41af --- /dev/null +++ b/contrib/debian/netdata.postinst.in @@ -0,0 +1,41 @@ +#! /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 + diff --git a/contrib/debian/netdata.postrm b/contrib/debian/netdata.postrm new file mode 100644 index 00000000..4ab4eead --- /dev/null +++ b/contrib/debian/netdata.postrm @@ -0,0 +1,43 @@ +#! /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 + diff --git a/contrib/debian/netdata.service b/contrib/debian/netdata.service new file mode 100644 index 00000000..e62ce4ed --- /dev/null +++ b/contrib/debian/netdata.service @@ -0,0 +1,14 @@ +[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 diff --git a/contrib/debian/rules b/contrib/debian/rules new file mode 100755 index 00000000..ec4ec418 --- /dev/null +++ b/contrib/debian/rules @@ -0,0 +1,87 @@ +#!/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 diff --git a/contrib/debian/source/format b/contrib/debian/source/format new file mode 100644 index 00000000..89ae9db8 --- /dev/null +++ b/contrib/debian/source/format @@ -0,0 +1 @@ +3.0 (native) diff --git a/netdata-installer.sh b/netdata-installer.sh index 06a283df..4a3012a4 100755 --- a/netdata-installer.sh +++ b/netdata-installer.sh @@ -3,6 +3,13 @@ # 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 diff --git a/netdata.spec.in b/netdata.spec.in index 40655a52..7d63650e 100644 --- a/netdata.spec.in +++ b/netdata.spec.in @@ -8,7 +8,7 @@ %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} @@ -100,6 +100,9 @@ rm -rf $RPM_BUILD_ROOT %{_datadir}/%{name}/web %changelog +* Wed Apr 20 2016 Costa Tsaousis - 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 - 1.0.0-1 - First public release. * Sun Nov 15 2015 Alon Bar-Lev - 0.0.0-1 diff --git a/packaging/tar-compare b/packaging/tar-compare index 02ec3c29..4e51e84c 100755 --- a/packaging/tar-compare +++ b/packaging/tar-compare @@ -54,6 +54,8 @@ diff -r "$1" $MYTMP/unpack/* | grep "^Only" | sed \ -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 diff --git a/src/apps_plugin.c b/src/apps_plugin.c index 6c7206bd..e8a6f43a 100644 --- a/src/apps_plugin.c +++ b/src/apps_plugin.c @@ -211,7 +211,6 @@ char *strdup_debug(const char *file, int line, const char *function, const char #endif /* NETDATA_INTERNAL_CHECKS */ - // ---------------------------------------------------------------------------- // system functions // to retrieve settings of the system @@ -411,6 +410,8 @@ struct target *get_users_target(uid_t uid) else snprintf(w->name, MAX_NAME, "%s", pw->pw_name); + netdata_fix_id(w->name); + w->uid = uid; w->next = users_root_target; @@ -447,6 +448,8 @@ struct target *get_groups_target(gid_t gid) else snprintf(w->name, MAX_NAME, "%s", gr->gr_name); + netdata_fix_id(w->name); + w->gid = gid; w->next = groups_root_target; diff --git a/src/common.c b/src/common.c index e3c3afe3..cb74b633 100644 --- a/src/common.c +++ b/src/common.c @@ -15,10 +15,276 @@ #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) diff --git a/src/common.h b/src/common.h index 2d5ac59c..e9987af7 100644 --- a/src/common.h +++ b/src/common.h @@ -15,6 +15,8 @@ #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); diff --git a/src/proc_diskstats.c b/src/proc_diskstats.c index 30351322..c2b84aae 100644 --- a/src/proc_diskstats.c +++ b/src/proc_diskstats.c @@ -4,6 +4,9 @@ #include #include #include +#include +#include +#include #include "common.h" #include "log.h" @@ -14,6 +17,73 @@ #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] = ""; @@ -40,7 +110,7 @@ int do_proc_diskstats(int update_every, unsigned long long dt) { 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); @@ -107,13 +177,19 @@ int do_proc_diskstats(int update_every, unsigned long long dt) { // 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 @@ -196,6 +272,7 @@ int do_proc_diskstats(int update_every, unsigned long long dt) { case 135: // scsi case 153: // raid case 202: // xen + case 254: // virtio3 case 256: // flash case 257: // flash case 259: // nvme0n1 issue #119 @@ -232,6 +309,7 @@ int do_proc_diskstats(int update_every, unsigned long long dt) { 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; diff --git a/src/rrd2json.c b/src/rrd2json.c index ad453cb6..88a75044 100644 --- a/src/rrd2json.c +++ b/src/rrd2json.c @@ -936,7 +936,7 @@ static void rrdr2csv(RRDR *r, BUFFER *wb, uint32_t options, const char *startlin // 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)) { diff --git a/system/Makefile.am b/system/Makefile.am index ca22cd55..f16a720e 100644 --- a/system/Makefile.am +++ b/system/Makefile.am @@ -4,6 +4,7 @@ MAINTAINERCLEANFILES= $(srcdir)/Makefile.in CLEANFILES = \ netdata-openrc \ + netdata.logrotate \ netdata.service \ netdata-init-d \ $(NULL) @@ -14,12 +15,14 @@ SUFFIXES = .in 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 \ diff --git a/system/netdata.logrotate.in b/system/netdata.logrotate.in new file mode 100644 index 00000000..763eb09c --- /dev/null +++ b/system/netdata.logrotate.in @@ -0,0 +1,15 @@ +@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 +} + diff --git a/web/dashboard.js b/web/dashboard.js index df258fca..a2089d41 100644 --- a/web/dashboard.js +++ b/web/dashboard.js @@ -11,6 +11,7 @@ // 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 @@ -458,7 +459,9 @@ 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, @@ -473,7 +476,12 @@ 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); }; @@ -540,13 +548,16 @@ .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); }); @@ -870,9 +881,17 @@ * 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 @@ -5291,6 +5310,7 @@ { url: NETDATA.serverDefault + 'lib/bootstrap.min.js', isAlreadyLoaded: function() { + // check if bootstrap is loaded if(typeof $().emulateTransitionEnd == 'function') return true; else { @@ -5387,6 +5407,11 @@ 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'); diff --git a/web/index.html b/web/index.html index 79414171..6f6013da 100644 --- a/web/index.html +++ b/web/index.html @@ -330,7 +330,7 @@ - + @@ -1357,11 +1357,22 @@ function enrichChartData(chart) { 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--;