diff options
Diffstat (limited to 'plugins.d')
-rw-r--r-- | plugins.d/Makefile.in | 141 | ||||
-rwxr-xr-x | plugins.d/alarm-notify.sh | 162 | ||||
-rwxr-xr-x | plugins.d/cgroup-name.sh | 7 | ||||
-rwxr-xr-x | plugins.d/fping.plugin | 31 | ||||
-rwxr-xr-x | plugins.d/python.d.plugin | 76 | ||||
-rwxr-xr-x | plugins.d/tc-qos-helper.sh | 100 |
6 files changed, 351 insertions, 166 deletions
diff --git a/plugins.d/Makefile.in b/plugins.d/Makefile.in index 7e90c9808..2a8806cb1 100644 --- a/plugins.d/Makefile.in +++ b/plugins.d/Makefile.in @@ -1,8 +1,9 @@ -# Makefile.in generated by automake 1.15 from Makefile.am. +# Makefile.in generated by automake 1.11.3 from Makefile.am. # @configure_input@ -# Copyright (C) 1994-2014 Free Software Foundation, Inc. - +# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, +# 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Free Software +# Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. @@ -16,61 +17,6 @@ VPATH = @srcdir@ -am__is_gnu_make = { \ - if test -z '$(MAKELEVEL)'; then \ - false; \ - elif test -n '$(MAKE_HOST)'; then \ - true; \ - elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ - true; \ - else \ - false; \ - fi; \ -} -am__make_running_with_option = \ - case $${target_option-} in \ - ?) ;; \ - *) echo "am__make_running_with_option: internal error: invalid" \ - "target option '$${target_option-}' specified" >&2; \ - exit 1;; \ - esac; \ - has_opt=no; \ - sane_makeflags=$$MAKEFLAGS; \ - if $(am__is_gnu_make); then \ - sane_makeflags=$$MFLAGS; \ - else \ - case $$MAKEFLAGS in \ - *\\[\ \ ]*) \ - bs=\\; \ - sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ - | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ - esac; \ - fi; \ - skip_next=no; \ - strip_trailopt () \ - { \ - flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ - }; \ - for flg in $$sane_makeflags; do \ - test $$skip_next = yes && { skip_next=no; continue; }; \ - case $$flg in \ - *=*|--*) continue;; \ - -*I) strip_trailopt 'I'; skip_next=yes;; \ - -*I?*) strip_trailopt 'I';; \ - -*O) strip_trailopt 'O'; skip_next=yes;; \ - -*O?*) strip_trailopt 'O';; \ - -*l) strip_trailopt 'l'; skip_next=yes;; \ - -*l?*) strip_trailopt 'l';; \ - -[dEDm]) skip_next=yes;; \ - -[JT]) skip_next=yes;; \ - esac; \ - case $$flg in \ - *$$target_option*) has_opt=yes; break;; \ - esac; \ - done; \ - test $$has_opt = yes -am__make_dryrun = (target_option=n; $(am__make_running_with_option)) -am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ @@ -90,9 +36,11 @@ POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ subdir = plugins.d +DIST_COMMON = $(dist_plugins_DATA) $(dist_plugins_SCRIPTS) \ + $(srcdir)/Makefile.am $(srcdir)/Makefile.in ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/m4/ax_c___atomic.m4 \ - $(top_srcdir)/m4/ax_c__generic.m4 \ + $(top_srcdir)/m4/ax_c__generic.m4 $(top_srcdir)/m4/ax_c_lto.m4 \ $(top_srcdir)/m4/ax_c_mallinfo.m4 \ $(top_srcdir)/m4/ax_c_mallopt.m4 \ $(top_srcdir)/m4/ax_check_compile_flag.m4 \ @@ -101,8 +49,6 @@ am__aclocal_m4_deps = $(top_srcdir)/m4/ax_c___atomic.m4 \ $(top_srcdir)/m4/tcmalloc.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) -DIST_COMMON = $(srcdir)/Makefile.am $(dist_plugins_SCRIPTS) \ - $(dist_plugins_DATA) $(am__DIST_COMMON) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/config.h CONFIG_CLEAN_FILES = @@ -136,32 +82,12 @@ am__uninstall_files_from_dir = { \ } am__installdirs = "$(DESTDIR)$(pluginsdir)" "$(DESTDIR)$(pluginsdir)" SCRIPTS = $(dist_plugins_SCRIPTS) -AM_V_P = $(am__v_P_@AM_V@) -am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) -am__v_P_0 = false -am__v_P_1 = : -AM_V_GEN = $(am__v_GEN_@AM_V@) -am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) -am__v_GEN_0 = @echo " GEN " $@; -am__v_GEN_1 = -AM_V_at = $(am__v_at_@AM_V@) -am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) -am__v_at_0 = @ -am__v_at_1 = SOURCES = DIST_SOURCES = -am__can_run_installinfo = \ - case $$AM_UPDATE_INFO_DIR in \ - n|no|NO) false;; \ - *) (install-info --version) >/dev/null 2>&1;; \ - esac DATA = $(dist_plugins_DATA) -am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) -am__DIST_COMMON = $(srcdir)/Makefile.in DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ -AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ @@ -185,7 +111,11 @@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +IPMIMONITORING_CFLAGS = @IPMIMONITORING_CFLAGS@ +IPMIMONITORING_LIBS = @IPMIMONITORING_LIBS@ LDFLAGS = @LDFLAGS@ +LIBCAP_CFLAGS = @LIBCAP_CFLAGS@ +LIBCAP_LIBS = @LIBCAP_LIBS@ LIBMNL_CFLAGS = @LIBMNL_CFLAGS@ LIBMNL_LIBS = @LIBMNL_LIBS@ LIBOBJS = @LIBOBJS@ @@ -199,6 +129,10 @@ MKDIR_P = @MKDIR_P@ NFACCT_CFLAGS = @NFACCT_CFLAGS@ NFACCT_LIBS = @NFACCT_LIBS@ OBJEXT = @OBJEXT@ +OPTIONAL_IPMIMONITORING_CFLAGS = @OPTIONAL_IPMIMONITORING_CFLAGS@ +OPTIONAL_IPMIMONITORING_LIBS = @OPTIONAL_IPMIMONITORING_LIBS@ +OPTIONAL_LIBCAP_CFLAGS = @OPTIONAL_LIBCAP_CFLAGS@ +OPTIONAL_LIBCAP_LIBS = @OPTIONAL_LIBCAP_LIBS@ OPTIONAL_MATH_CLFAGS = @OPTIONAL_MATH_CLFAGS@ OPTIONAL_MATH_LIBS = @OPTIONAL_MATH_LIBS@ OPTIONAL_NFACCT_CLFAGS = @OPTIONAL_NFACCT_CLFAGS@ @@ -333,6 +267,7 @@ $(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__confi echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu plugins.d/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --gnu plugins.d/Makefile +.PRECIOUS: Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ @@ -352,11 +287,8 @@ $(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) $(am__aclocal_m4_deps): install-dist_pluginsSCRIPTS: $(dist_plugins_SCRIPTS) @$(NORMAL_INSTALL) + test -z "$(pluginsdir)" || $(MKDIR_P) "$(DESTDIR)$(pluginsdir)" @list='$(dist_plugins_SCRIPTS)'; test -n "$(pluginsdir)" || list=; \ - if test -n "$$list"; then \ - echo " $(MKDIR_P) '$(DESTDIR)$(pluginsdir)'"; \ - $(MKDIR_P) "$(DESTDIR)$(pluginsdir)" || exit 1; \ - fi; \ for p in $$list; do \ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ if test -f "$$d$$p"; then echo "$$d$$p"; echo "$$p"; else :; fi; \ @@ -387,11 +319,8 @@ uninstall-dist_pluginsSCRIPTS: dir='$(DESTDIR)$(pluginsdir)'; $(am__uninstall_files_from_dir) install-dist_pluginsDATA: $(dist_plugins_DATA) @$(NORMAL_INSTALL) + test -z "$(pluginsdir)" || $(MKDIR_P) "$(DESTDIR)$(pluginsdir)" @list='$(dist_plugins_DATA)'; test -n "$(pluginsdir)" || list=; \ - if test -n "$$list"; then \ - echo " $(MKDIR_P) '$(DESTDIR)$(pluginsdir)'"; \ - $(MKDIR_P) "$(DESTDIR)$(pluginsdir)" || exit 1; \ - fi; \ for p in $$list; do \ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ echo "$$d$$p"; \ @@ -406,11 +335,11 @@ uninstall-dist_pluginsDATA: @list='$(dist_plugins_DATA)'; test -n "$(pluginsdir)" || list=; \ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ dir='$(DESTDIR)$(pluginsdir)'; $(am__uninstall_files_from_dir) -tags TAGS: - -ctags CTAGS: +tags: TAGS +TAGS: -cscope cscopelist: +ctags: CTAGS +CTAGS: distdir: $(DISTFILES) @@ -549,20 +478,18 @@ uninstall-am: uninstall-dist_pluginsDATA uninstall-dist_pluginsSCRIPTS .MAKE: install-am install-strip -.PHONY: all all-am check check-am clean clean-generic cscopelist-am \ - ctags-am distclean distclean-generic distdir dvi dvi-am html \ - html-am info info-am install install-am install-data \ - install-data-am install-dist_pluginsDATA \ - install-dist_pluginsSCRIPTS install-dvi install-dvi-am \ - install-exec install-exec-am install-html install-html-am \ - install-info install-info-am install-man install-pdf \ - install-pdf-am install-ps install-ps-am install-strip \ - installcheck installcheck-am installdirs maintainer-clean \ - maintainer-clean-generic mostlyclean mostlyclean-generic pdf \ - pdf-am ps ps-am tags-am uninstall uninstall-am \ - uninstall-dist_pluginsDATA uninstall-dist_pluginsSCRIPTS - -.PRECIOUS: Makefile +.PHONY: all all-am check check-am clean clean-generic distclean \ + distclean-generic distdir dvi dvi-am html html-am info info-am \ + install install-am install-data install-data-am \ + install-dist_pluginsDATA install-dist_pluginsSCRIPTS \ + install-dvi install-dvi-am install-exec install-exec-am \ + install-html install-html-am install-info install-info-am \ + install-man install-pdf install-pdf-am install-ps \ + install-ps-am install-strip installcheck installcheck-am \ + installdirs maintainer-clean maintainer-clean-generic \ + mostlyclean mostlyclean-generic pdf pdf-am ps ps-am uninstall \ + uninstall-am uninstall-dist_pluginsDATA \ + uninstall-dist_pluginsSCRIPTS # Tell versions [3.59,3.63) of GNU make to not export all variables. diff --git a/plugins.d/alarm-notify.sh b/plugins.d/alarm-notify.sh index d6f3d8b2a..d0188fe3b 100755 --- a/plugins.d/alarm-notify.sh +++ b/plugins.d/alarm-notify.sh @@ -16,6 +16,7 @@ # Supported notification methods: # - emails by @ktsaou # - slack.com notifications by @ktsaou +# - discordapp.com notifications by @lowfive # - pushover.net notifications by @ktsaou # - pushbullet.com push notifications by Tiago Peralta @tperalta82 PR #1070 # - telegram.org notifications by @hashworks PR #1002 @@ -23,7 +24,7 @@ # - kafka notifications by @ktsaou #1342 # - pagerduty.com notifications by Jim Cooley @jimcooley PR #1373 # - messagebird.com notifications by @tech_no_logical #1453 -# - hipchart notifications by @ktsaou #1561 +# - hipchat notifications by @ktsaou #1561 # ----------------------------------------------------------------------------- # testing notifications @@ -46,7 +47,7 @@ then echo >&2 echo >&2 "# SENDING TEST ${x} ALARM TO ROLE: ${recipient}" - "${0}" "${recipient}" "$(hostname)" 1 1 "${id}" "$(date +%s)" "test_alarm" "test.chart" "test.family" "${x}" "${last}" 100 90 "${0}" 1 $((0 + id)) "units" "this is a test alarm to verify notifications work" + "${0}" "${recipient}" "$(hostname)" 1 1 "${id}" "$(date +%s)" "test_alarm" "test.chart" "test.family" "${x}" "${last}" 100 90 "${0}" 1 $((0 + id)) "units" "this is a test alarm to verify notifications work" "new value" "old value" if [ $? -ne 0 ] then echo >&2 "# FAILED" @@ -138,6 +139,15 @@ duration="${15}" # the duration in seconds of the previous alarm state non_clear_duration="${16}" # the total duration in seconds this is/was non-clear units="${17}" # the units of the value info="${18}" # a short description of the alarm +value_string="${19}" # friendly value (with units) +old_value_string="${20}" # friendly old value (with units) + +# ----------------------------------------------------------------------------- +# find a suitable hostname to use, if netdata did not supply a hostname + +[ -z "${host}" ] && host="${NETDATA_HOSTNAME}" +[ -z "${host}" ] && host="${NETDATA_REGISTRY_HOSTNAME}" +[ -z "${host}" ] && host="$(hostname 2>/dev/null)" # ----------------------------------------------------------------------------- # screen statuses we don't need to send a notification @@ -145,14 +155,14 @@ info="${18}" # a short description of the alarm # don't do anything if this is not WARNING, CRITICAL or CLEAR if [ "${status}" != "WARNING" -a "${status}" != "CRITICAL" -a "${status}" != "CLEAR" ] then - info "not sending notification for ${status} on '${chart}.${name}'" + info "not sending notification for ${status} of '${host}.${chart}.${name}'" exit 1 fi # don't do anything if this is CLEAR, but it was not WARNING or CRITICAL if [ "${old_status}" != "WARNING" -a "${old_status}" != "CRITICAL" -a "${status}" = "CLEAR" ] then - info "not sending notification for ${status} on '${chart}.${name}' (last status was ${old_status})" + info "not sending notification for ${status} of '${host}.${chart}.${name}' (last status was ${old_status})" exit 1 fi @@ -172,6 +182,7 @@ sendmail= # enable / disable features SEND_SLACK="YES" +SEND_DISCORD="YES" SEND_PUSHOVER="YES" SEND_TWILIO="YES" SEND_HIPCHAT="YES" @@ -187,6 +198,11 @@ SLACK_WEBHOOK_URL= DEFAULT_RECIPIENT_SLACK= declare -A role_recipients_slack=() +# discord configs +DISCORD_WEBHOOK_URL= +DEFAULT_RECIPIENT_DISCORD= +declare -A role_recipients_discord=() + # pushover configs PUSHOVER_APP_TOKEN= DEFAULT_RECIPIENT_PUSHOVER= @@ -205,6 +221,7 @@ DEFAULT_RECIPIENT_TWILIO= declare -A role_recipients_twilio=() # hipchat configs +HIPCHAT_SERVER= HIPCHAT_AUTH_TOKEN= DEFAULT_RECIPIENT_HIPCHAT= declare -A role_recipients_hipchat=() @@ -283,6 +300,7 @@ filter_recipient_by_criticality() { # find the recipients' addresses per method declare -A arr_slack=() +declare -A arr_discord=() declare -A arr_pushover=() declare -A arr_pushbullet=() declare -A arr_twilio=() @@ -363,6 +381,14 @@ do [ "${r}" != "disabled" ] && filter_recipient_by_criticality slack "${r}" && arr_slack[${r/|*/}]="1" done + # discord + a="${role_recipients_discord[${x}]}" + [ -z "${a}" ] && a="${DEFAULT_RECIPIENT_DISCORD}" + for r in ${a//,/ } + do + [ "${r}" != "disabled" ] && filter_recipient_by_criticality discord "${r}" && arr_discord[${r/|*/}]="1" + done + # pagerduty.com a="${role_recipients_pd[${x}]}" [ -z "${a}" ] && a="${DEFAULT_RECIPIENT_PD}" @@ -376,6 +402,10 @@ done to_slack="${!arr_slack[*]}" [ -z "${to_slack}" ] && SEND_SLACK="NO" +# build the list of discord recipients (channels) +to_discord="${!arr_discord[*]}" +[ -z "${to_discord}" ] && SEND_DISCORD="NO" + # build the list of pushover recipients (user tokens) to_pushover="${!arr_pushover[*]}" [ -z "${to_pushover}" ] && SEND_PUSHOVER="NO" @@ -420,6 +450,9 @@ done # check slack [ -z "${SLACK_WEBHOOK_URL}" ] && SEND_SLACK="NO" +# check discord +[ -z "${DISCORD_WEBHOOK_URL}" ] && SEND_DISCORD="NO" + # check pushover [ -z "${PUSHOVER_APP_TOKEN}" ] && SEND_PUSHOVER="NO" @@ -459,6 +492,7 @@ fi if [ \( \ "${SEND_PUSHOVER}" = "YES" \ -o "${SEND_SLACK}" = "YES" \ + -o "${SEND_DISCORD}" = "YES" \ -o "${SEND_HIPCHAT}" = "YES" \ -o "${SEND_TWILIO}" = "YES" \ -o "${SEND_MESSAGEBIRD}" = "YES" \ @@ -476,6 +510,7 @@ if [ \( \ SEND_PUSHBULLET="NO" SEND_TELEGRAM="NO" SEND_SLACK="NO" + SEND_DISCORD="NO" SEND_TWILIO="NO" SEND_HIPCHAT="NO" SEND_MESSAGEBIRD="NO" @@ -495,6 +530,7 @@ if [ "${SEND_EMAIL}" != "YES" \ -a "${SEND_PUSHOVER}" != "YES" \ -a "${SEND_TELEGRAM}" != "YES" \ -a "${SEND_SLACK}" != "YES" \ + -a "${SEND_DISCORD}" != "YES" \ -a "${SEND_TWILIO}" != "YES" \ -a "${SEND_HIPCHAT}" != "YES" \ -a "${SEND_MESSAGEBIRD}" != "YES" \ @@ -503,17 +539,10 @@ if [ "${SEND_EMAIL}" != "YES" \ -a "${SEND_PD}" != "YES" \ ] then - fatal "All notification methods are disabled. Not sending notification to '${roles}' for '${name}' = '${value}' of chart '${chart}' for status '${status}'." + fatal "All notification methods are disabled. Not sending notification for host '${host}', chart '${chart}' to '${roles}' for '${name}' = '${value}' for status '${status}'." fi # ----------------------------------------------------------------------------- -# find a suitable hostname to use, if netdata did not supply a hostname - -[ -z "${host}" ] && host="${NETDATA_HOSTNAME}" -[ -z "${host}" ] && host="${NETDATA_REGISTRY_HOSTNAME}" -[ -z "${host}" ] && host="$(hostname 2>/dev/null)" - -# ----------------------------------------------------------------------------- # get the date the alarm happened date="$(date --date=@${when} 2>/dev/null)" @@ -747,13 +776,13 @@ send_pd() { then for PD_SERVICE_KEY in ${recipients} do - d="${status} ${name}=${value} ${units} - ${host}, ${family}" + d="${status} ${name} = ${value_string} - ${host}, ${family}" ${pd_send} -k ${PD_SERVICE_KEY} \ -t ${t} \ -d "${d}" \ -i ${alarm_id} \ -f 'info'="${info}" \ - -f 'value_w_units'="${value} ${units}" \ + -f 'value_w_units'="${value_string}" \ -f 'when'="${when}" \ -f 'duration'="${duration}" \ -f 'roles'="${roles}" \ @@ -774,10 +803,10 @@ send_pd() { retval=$? if [ ${retval} -eq 0 ] then - info "sent pagerduty.com notification using service key ${PD_SERVICE_KEY::-26}....: ${d}" + info "sent pagerduty.com notification for host ${host} ${chart}.${name} using service key ${PD_SERVICE_KEY::-26}....: ${d}" sent=$((sent + 1)) else - error "failed to send pagerduty.com notification using service key ${PD_SERVICE_KEY::-26}.... (error code ${retval}): ${d}" + error "failed to send pagerduty.com notification for ${host} ${chart}.${name} using service key ${PD_SERVICE_KEY::-26}.... (error code ${retval}): ${d}" fi done @@ -826,16 +855,15 @@ send_twilio() { send_hipchat() { local authtoken="${1}" recipients="${2}" message="${3}" httpcode sent=0 room color sender msg_format notify - if [ "${SEND_HIPCHAT}" = "YES" -a ! -z "${authtoken}" -a ! -z "${recipients}" -a ! -z "${message}" ] - then - + if [ "${SEND_HIPCHAT}" = "YES" -a ! -z "${HIPCHAT_SERVER}" -a ! -z "${authtoken}" -a ! -z "${recipients}" -a ! -z "${message}" ] + then # A label to be shown in addition to the sender's name # Valid length range: 0 - 64. sender="netdata" # Valid values: html, text. # Defaults to 'html'. - msg_format="text" + msg_format="html" # Background color for message. Valid values: yellow, green, red, purple, gray, random. Defaults to 'yellow'. case "${status}" in @@ -856,9 +884,9 @@ send_hipchat() { -H "Content-type: application/json" \ -H "Authorization: Bearer ${authtoken}" \ -d "{\"color\": \"${color}\", \"from\": \"${netdata}\", \"message_format\": \"${msg_format}\", \"message\": \"${message}\", \"notify\": \"${notify}\"}" \ - "https://api.hipchat.com/v2/room/${room}/notification") - - if [ "${httpcode}" == "200" ] + "https://${HIPCHAT_SERVER}/v2/room/${room}/notification") + + if [ "${httpcode}" == "204" ] then info "sent HipChat notification for: ${host} ${chart}.${name} is ${status} to '${room}'" sent=$((sent + 1)) @@ -1008,6 +1036,66 @@ EOF return 1 } +# ----------------------------------------------------------------------------- +# discord sender + +send_discord() { + local webhook="${1}/slack" channels="${2}" httpcode sent=0 channel color payload + + [ "${SEND_DISCORD}" != "YES" ] && return 1 + + case "${status}" in + WARNING) color="warning" ;; + CRITICAL) color="danger" ;; + CLEAR) color="good" ;; + *) color="#777777" ;; + esac + + for channel in ${channels} + do + payload="$(cat <<EOF + { + "channel": "#${channel}", + "username": "netdata on ${host}", + "text": "${host} ${status_message}, \`${chart}\` (_${family}_), *${alarm}*", + "icon_url": "${images_base_url}/images/seo-performance-128.png", + "attachments": [ + { + "color": "${color}", + "title": "${alarm}", + "title_link": "${goto_url}", + "text": "${info}", + "fields": [ + { + "title": "${chart}", + "value": "${family}" + } + ], + "thumb_url": "${image}", + "footer_icon": "${images_base_url}/images/seo-performance-128.png", + "footer": "${host}", + "ts": ${when} + } + ] + } +EOF + )" + + httpcode=$(${curl} --write-out %{http_code} --silent --output /dev/null -X POST --data-urlencode "payload=${payload}" "${webhook}") + if [ "${httpcode}" == "200" ] + then + info "sent discord notification for: ${host} ${chart}.${name} is ${status} to '${channel}'" + sent=$((sent + 1)) + else + error "failed to send discord notification for: ${host} ${chart}.${name} is ${status} to '${channel}', with HTTP error code ${httpcode}." + fi + done + + [ ${sent} -gt 0 ] && return 0 + + return 1 +} + # ----------------------------------------------------------------------------- # prepare the content of the notification @@ -1034,7 +1122,7 @@ status_message="status unknown" color="grey" # the alarm value -alarm="${name//_/ } = ${value} ${units}" +alarm="${name//_/ } = ${value_string}" # the image of the alarm image="${images_base_url}/images/seo-performance-128.png" @@ -1109,6 +1197,15 @@ send_slack "${SLACK_WEBHOOK_URL}" "${to_slack}" SENT_SLACK=$? # ----------------------------------------------------------------------------- +# send the discord notification + +# discord aggregates posts from the same username +# so we use "${host} ${status}" as the bot username, to make them diff + +send_discord "${DISCORD_WEBHOOK_URL}" "${to_discord}" +SENT_DISCORD=$? + +# ----------------------------------------------------------------------------- # send the pushover notification send_pushover "${PUSHOVER_APP_TOKEN}" "${to_pushover}" "${when}" "${goto_url}" "${status}" "${host} ${status_message} - ${name//_/ } - ${chart}" " @@ -1187,14 +1284,13 @@ SENT_PD=$? # ----------------------------------------------------------------------------- # send hipchat message -send_hipchat "${HIPCHAT_AUTH_TOKEN}" "${to_hipchat}" " -<b>${alarm}</b> ${info_html}<br/> -<small><b>${chart}</b><br/>Chart<br/> </small> -<small><b>${family}</b><br/>Family<br/> </small> -<small><b>${severity}</b><br/>Severity<br/> </small> -<small><b>${date}${raised_for_html}</b><br/>Time<br/> </small> -<a href=\"${goto_url}\">View Netdata</a><br/> -<small><small>The source of this alarm is line ${src}</small></small> +send_hipchat "${HIPCHAT_AUTH_TOKEN}" "${to_hipchat}" " \ +${host} ${status_message}<br/> \ +<b>${alarm}</b> ${info_html}<br/> \ +<b>${chart}</b> (family <b>${family}</b>)<br/> \ +<b>${date}${raised_for_html}</b><br/> \ +<a href=\\\"${goto_url}\\\">View netdata dashboard</a> \ +(source of alarm ${src}) \ " SENT_HIPCHAT=$? @@ -1301,6 +1397,7 @@ if [ ${SENT_EMAIL} -eq 0 \ -o ${SENT_PUSHOVER} -eq 0 \ -o ${SENT_TELEGRAM} -eq 0 \ -o ${SENT_SLACK} -eq 0 \ + -o ${SENT_DISCORD} -eq 0 \ -o ${SENT_TWILIO} -eq 0 \ -o ${SENT_HIPCHAT} -eq 0 \ -o ${SENT_MESSAGEBIRD} -eq 0 \ @@ -1315,3 +1412,4 @@ fi # we did not send anything exit 1 + diff --git a/plugins.d/cgroup-name.sh b/plugins.d/cgroup-name.sh index 9bb3bcabb..a1e3abe08 100755 --- a/plugins.d/cgroup-name.sh +++ b/plugins.d/cgroup-name.sh @@ -98,6 +98,8 @@ if [ -z "${NAME}" ] then if [[ "${CGROUP}" =~ ^.*docker[-_/\.][a-fA-F0-9]+[-_\.]?.*$ ]] then + # docker containers + DOCKERID="$( echo "${CGROUP}" | sed "s|^.*docker[-_/]\([a-fA-F0-9]\+\)[-_\.]\?.*$|\1|" )" # echo "DOCKERID=${DOCKERID}" @@ -117,6 +119,11 @@ if [ -z "${NAME}" ] info "docker container '${DOCKERID}' is named '${NAME}'" fi fi + elif [[ "${CGROUP}" =~ machine.slice_machine.*-qemu ]] + then + # libvirtd / qemu virtual machines + + NAME="$(echo ${CGROUP} | sed 's/machine.slice_machine.*-qemu//; s/\/x2d//; s/\/x2d/\-/g; s/\.scope//g')" fi [ -z "${NAME}" ] && NAME="${CGROUP}" diff --git a/plugins.d/fping.plugin b/plugins.d/fping.plugin index d523f4474..232c00630 100755 --- a/plugins.d/fping.plugin +++ b/plugins.d/fping.plugin @@ -22,20 +22,39 @@ if [ "${1}" = "install" ] "${@}" || exit 1 } + download() { + local curl="$(which curl 2>/dev/null || command -v curl 2>/dev/null)" + [ ! -z "${curl}" ] && run curl -s -L "${1}" && return 0 + + local wget="$(which wget 2>/dev/null || command -v wget 2>/dev/null)" + [ ! -z "${wget}" ] && run wget -q -O - "${1}" && return 0 + + echo >&2 "Cannot find 'curl' or 'wget' in this system." && exit 1 + } + [ ! -d /usr/src ] && run mkdir -p /usr/src [ ! -d /usr/local/bin ] && run mkdir -p /usr/local/bin run cd /usr/src - if [ -d fping-ktsaou.git ] + if [ -d fping-3.15 ] then - run cd fping-ktsaou.git - run git pull - else - run git clone https://github.com/ktsaou/fping.git fping-ktsaou.git - run cd fping-ktsaou.git + run rm -rf fping-3.15 || exit 1 fi + download 'https://github.com/schweikert/fping/archive/3.15.tar.gz' | run tar -zxvpf - + [ $? -ne 0 ] && exit 1 + run cd fping-3.15 || exit 1 + + #if [ -d fping-ktsaou.git ] + # then + # run cd fping-ktsaou.git + # run git pull + #else + # run git clone https://github.com/ktsaou/fping.git fping-ktsaou.git + # run cd fping-ktsaou.git + #fi + run ./autogen.sh run ./configure --prefix=/usr/local run make clean diff --git a/plugins.d/python.d.plugin b/plugins.d/python.d.plugin index b4e6473a6..efa62cbc5 100755 --- a/plugins.d/python.d.plugin +++ b/plugins.d/python.d.plugin @@ -67,6 +67,34 @@ try: except ImportError: msg.fatal('Cannot find yaml library') +try: + from collections import OrderedDict + ORDERED = True + DICT = OrderedDict + msg.info('YAML output is ordered') +except ImportError: + try: + from ordereddict import OrderedDict + ORDERED = True + DICT = OrderedDict + msg.info('YAML output is ordered') + except ImportError: + ORDERED = False + DICT = dict + msg.info('YAML output is unordered') +if ORDERED: + def ordered_load(stream, Loader=yaml.Loader, object_pairs_hook=OrderedDict): + class OrderedLoader(Loader): + pass + + def construct_mapping(loader, node): + loader.flatten_mapping(node) + return object_pairs_hook(loader.construct_pairs(node)) + OrderedLoader.add_constructor( + yaml.resolver.BaseResolver.DEFAULT_MAPPING_TAG, + construct_mapping) + return yaml.load(stream, OrderedLoader) + class PythonCharts(object): """ @@ -77,12 +105,16 @@ class PythonCharts(object): modules=None, modules_path='../python.d/', modules_configs='../conf.d/', - modules_disabled=None): + modules_disabled=None, + modules_enabled=None, + default_run=None): """ :param modules: list :param modules_path: str :param modules_configs: str :param modules_disabled: list + :param modules_enabled: list + :param default_run: bool """ if modules is None: @@ -95,13 +127,13 @@ class PythonCharts(object): self.configs = modules_configs # load modules - loaded_modules = self._load_modules(modules_path, modules, modules_disabled) + loaded_modules = self._load_modules(modules_path, modules, modules_disabled, modules_enabled, default_run) # load configuration files configured_modules = self._load_configs(loaded_modules) # good economy and prosperity: - self.jobs = self._create_jobs(configured_modules) # type: list + self.jobs = self._create_jobs(configured_modules) # type <list> # enable timetable override like `python.d.plugin mysql debug 1` if DEBUG_FLAG and OVERRIDE_UPDATE_EVERY: @@ -131,7 +163,7 @@ class PythonCharts(object): msg.error("Problem loading", name, str(e)) return None - def _load_modules(self, path, modules, disabled): + def _load_modules(self, path, modules, disabled, enabled, default_run): """ Load modules from 'modules' list or dynamically every file from 'path' (only .chart.py files) :param path: str @@ -157,7 +189,10 @@ class PythonCharts(object): msg.fatal('no modules found.') else: # scan directory specified in path and load all modules from there - names = os.listdir(path) + if default_run is False: + names = [module for module in os.listdir(path) if module[:-9] in enabled] + else: + names = os.listdir(path) for mod in names: if mod.replace(MODULE_EXTENSION, "") in disabled: msg.error(mod + ": disabled module ", mod.replace(MODULE_EXTENSION, "")) @@ -235,7 +270,7 @@ class PythonCharts(object): # check if there are dict in config dict many_jobs = False for name in config: - if type(config[name]) is dict: + if isinstance(config[name], DICT): many_jobs = True break @@ -343,7 +378,8 @@ class PythonCharts(object): if job.override_name is not None: new_name = job.__module__ + '_' + sub(r'\s+', '_', job.override_name) if new_name in overridden: - msg.info("DROPPED:", job.name, ", job '" + job.override_name + "' is already served by another job.") + msg.info("DROPPED:", job.name, ", job '" + job.override_name + + "' is already served by another job.") self._stop(job) i -= 1 else: @@ -420,7 +456,10 @@ def read_config(path): """ try: with open(path, 'r') as stream: - config = yaml.load(stream) + if ORDERED: + config = ordered_load(stream, yaml.SafeLoader) + else: + config = yaml.load(stream) except (OSError, IOError): msg.error(str(path), "is not a valid configuration file") return None @@ -452,7 +491,7 @@ def parse_cmdline(directory, *commands): elif cmd == "trace" or cmd == "all": TRACE_FLAG = True elif os.path.isfile(directory + cmd + ".chart.py") or os.path.isfile(directory + cmd): - #DEBUG_FLAG = True + # DEBUG_FLAG = True mods.append(cmd.replace(".chart.py", "")) else: try: @@ -477,7 +516,9 @@ def run(): global DEBUG_FLAG, TRACE_FLAG, BASE_CONFIG # read configuration file - disabled = [] + disabled = ['nginx_log', 'gunicorn_log'] + enabled = list() + default_run = True configfile = CONFIG_DIR + "python.d.conf" msg.PROGRAM = PROGRAM msg.info("reading configuration file:", configfile) @@ -519,12 +560,17 @@ def run(): except (KeyError, TypeError): pass + default_run = True if ('default_run' not in conf or conf.get('default_run')) else False + for k, v in conf.items(): - if k in ("update_every", "debug", "enabled"): + if k in ("update_every", "debug", "enabled", "default_run"): continue - if v is False: - disabled.append(k) - + if default_run: + if v is False: + disabled.append(k) + else: + if v is True: + enabled.append(k) # parse passed command line arguments modules = parse_cmdline(MODULES_DIR, *sys.argv) msg.DEBUG_FLAG = DEBUG_FLAG @@ -539,7 +585,7 @@ def run(): ", ONLY_MODULES=" + str(modules)) # run plugins - charts = PythonCharts(modules, MODULES_DIR, CONFIG_DIR + "python.d/", disabled) + charts = PythonCharts(modules, MODULES_DIR, CONFIG_DIR + "python.d/", disabled, enabled, default_run) charts.check() charts.create() charts.update() diff --git a/plugins.d/tc-qos-helper.sh b/plugins.d/tc-qos-helper.sh index e9253c8f2..074fece9a 100755 --- a/plugins.d/tc-qos-helper.sh +++ b/plugins.d/tc-qos-helper.sh @@ -12,12 +12,58 @@ export PATH="${PATH}:/sbin:/usr/sbin:/usr/local/sbin" export LC_ALL=C + +# ----------------------------------------------------------------------------- +# find /var/run/fireqos + +# the default +fireqos_run_dir="/var/run/fireqos" + +function realdir { + local r="$1" + local t=$(readlink "$r") + + while [ "$t" ] + do + r=$(cd $(dirname "$r") && cd $(dirname "$t") && pwd -P)/$(basename "$t") + t=$(readlink "$r") + done + + dirname "$r" +} + +if [ ! -d "${fireqos_run_dir}" ] + then + + # the fireqos executable - we will use it to find its config + fireqos="$(which fireqos 2>/dev/null || command -v fireqos 2>/dev/null)" + + if [ ! -z "${fireqos}" ] + then + + fireqos_exec_dir="$(realdir ${fireqos})" + + if [ ! -z "${fireqos_exec_dir}" -a "${fireqos_exec_dir}" != "." -a -f "${fireqos_exec_dir}/install.config" ] + then + + LOCALSTATEDIR= + source "${fireqos_exec_dir}/install.config" + + if [ -d "${LOCALSTATEDIR}/run/fireqos" ] + then + fireqos_run_dir="${LOCALSTATEDIR}/run/fireqos" + fi + fi + fi +fi + +# ----------------------------------------------------------------------------- +# logging functions + PROGRAM_FILE="$0" PROGRAM_NAME="$(basename $0)" PROGRAM_NAME="${PROGRAM_NAME/.plugin}" -# ----------------------------------------------------------------------------- - logdate() { date "+%Y-%m-%d %H:%M:%S" } @@ -52,6 +98,7 @@ debug() { [ $debug -eq 1 ] && log DEBUG "${@}" } + # ----------------------------------------------------------------------------- plugins_dir="${NETDATA_PLUGINS_DIR}" @@ -59,23 +106,52 @@ plugins_dir="${NETDATA_PLUGINS_DIR}" config_dir=${NETDATA_CONFIG_DIR-/etc/netdata} tc="$(which tc 2>/dev/null || command -v tc 2>/dev/null)" -fireqos_run_dir="/var/run/fireqos" + + +# ----------------------------------------------------------------------------- +# user configuration + +# time in seconds to refresh QoS class/qdisc names qos_get_class_names_every=120 + +# time in seconds to exit - netdata will restart the script qos_exit_every=3600 +# what to use? classes or qdiscs? +tc_show="qdisc" # can also be "class" + + +# ----------------------------------------------------------------------------- # 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 +case "${tc_show}" in + qdisc|class) + ;; + + *) + error "tc_show variable can be either 'qdisc' or 'class' but is set to '${tc_show}'. Assuming it is 'qdisc'." + tc_show="qdisc" + ;; +esac + + +# ----------------------------------------------------------------------------- # default sleep function + LOOPSLEEPMS_LASTWORK=0 loopsleepms() { sleep $1 @@ -85,6 +161,10 @@ loopsleepms() { # with a high resolution timer function for precise looping. . "${plugins_dir}/loopsleepms.sh.inc" + +# ----------------------------------------------------------------------------- +# final checks we can run + if [ -z "${tc}" -o ! -x "${tc}" ] then fatal "cannot find command 'tc' in this system." @@ -93,11 +173,20 @@ fi tc_devices= fix_names= +# ----------------------------------------------------------------------------- + setclassname() { - echo "SETCLASSNAME $3 $2" + if [ "${tc_show}" = "qdisc" ] + then + echo "SETCLASSNAME $4 $2" + else + echo "SETCLASSNAME $3 $2" + fi } show_tc_cls() { + [ "${tc_show}" = "qdisc" ] && return 1 + local x="${1}" if [ -f /etc/iproute2/tc_cls ] @@ -110,7 +199,6 @@ show_tc_cls() { done </etc/iproute2/tc_cls return 0 fi - return 1 } @@ -144,7 +232,7 @@ show_tc() { echo "BEGIN ${x}" # netdata can parse the output of tc - ${tc} -s class show dev ${x} + ${tc} -s ${tc_show} show dev ${x} # check FireQOS names for classes if [ ! -z "${fix_names}" ] |