summaryrefslogtreecommitdiffstats
path: root/plugins.d/charts.d.plugin
diff options
context:
space:
mode:
Diffstat (limited to 'plugins.d/charts.d.plugin')
-rwxr-xr-xplugins.d/charts.d.plugin713
1 files changed, 0 insertions, 713 deletions
diff --git a/plugins.d/charts.d.plugin b/plugins.d/charts.d.plugin
deleted file mode 100755
index 9bd03fd47..000000000
--- a/plugins.d/charts.d.plugin
+++ /dev/null
@@ -1,713 +0,0 @@
-#!/usr/bin/env bash
-
-# netdata
-# real-time performance and health monitoring, done right!
-# (C) 2017 Costa Tsaousis <costa@tsaousis.gr>
-# GPL v3+
-#
-# charts.d.plugin allows easy development of BASH plugins
-#
-# if you need to run parallel charts.d processes, link this file to a different name
-# in the same directory, with a .plugin suffix and netdata will start both of them,
-# each will have a different config file and modules configuration directory.
-#
-
-export PATH="${PATH}:/sbin:/usr/sbin:/usr/local/bin:/usr/local/sbin"
-
-PROGRAM_FILE="$0"
-PROGRAM_NAME="$(basename $0)"
-PROGRAM_NAME="${PROGRAM_NAME/.plugin}"
-MODULE_NAME="main"
-
-# -----------------------------------------------------------------------------
-# create temp dir
-
-debug=0
-TMP_DIR=
-chartsd_cleanup() {
- trap '' EXIT QUIT HUP INT TERM
-
- if [ ! -z "$TMP_DIR" -a -d "$TMP_DIR" ]
- then
- [ $debug -eq 1 ] && echo >&2 "$PROGRAM_NAME: cleaning up temporary directory $TMP_DIR ..."
- rm -rf "$TMP_DIR"
- fi
- exit 0
-}
-trap chartsd_cleanup EXIT QUIT HUP INT TERM
-
-if [ $UID = "0" ]
-then
- TMP_DIR="$( mktemp -d /var/run/netdata-${PROGRAM_NAME}-XXXXXXXXXX )"
-else
- TMP_DIR="$( mktemp -d /tmp/.netdata-${PROGRAM_NAME}-XXXXXXXXXX )"
-fi
-
-logdate() {
- date "+%Y-%m-%d %H:%M:%S"
-}
-
-log() {
- local status="${1}"
- shift
-
- echo >&2 "$(logdate): ${PROGRAM_NAME}: ${status}: ${MODULE_NAME}: ${*}"
-
-}
-
-warning() {
- log WARNING "${@}"
-}
-
-error() {
- log ERROR "${@}"
-}
-
-info() {
- log INFO "${@}"
-}
-
-fatal() {
- log FATAL "${@}"
- echo "DISABLE"
- exit 1
-}
-
-debug() {
- [ $debug -eq 1 ] && log DEBUG "${@}"
-}
-
-# -----------------------------------------------------------------------------
-# check a few commands
-
-require_cmd() {
- local x=$(which "${1}" 2>/dev/null || command -v "${1}" 2>/dev/null)
- if [ -z "${x}" -o ! -x "${x}" ]
- then
- warning "command '${1}' is not found in ${PATH}."
- eval "${1^^}_CMD=\"\""
- return 1
- fi
-
- eval "${1^^}_CMD=\"${x}\""
- return 0
-}
-
-require_cmd date || exit 1
-require_cmd sed || exit 1
-require_cmd basename || exit 1
-require_cmd dirname || exit 1
-require_cmd cat || exit 1
-require_cmd grep || exit 1
-require_cmd egrep || exit 1
-require_cmd mktemp || exit 1
-require_cmd awk || exit 1
-require_cmd timeout || exit 1
-require_cmd curl || exit 1
-
-# -----------------------------------------------------------------------------
-
-[ $(( ${BASH_VERSINFO[0]} )) -lt 4 ] && fatal "BASH version 4 or later is required, but found version: ${BASH_VERSION}. Please upgrade."
-
-info "started from '$PROGRAM_FILE' with options: $*"
-
-# -----------------------------------------------------------------------------
-# internal defaults
-# netdata exposes a few environment variables for us
-
-[ -z "${NETDATA_PLUGINS_DIR}" ] && NETDATA_PLUGINS_DIR="$(dirname "${0}")"
-[ -z "${NETDATA_CONFIG_DIR}" ] && NETDATA_CONFIG_DIR="$(dirname "${0}")/../../../../etc/netdata"
-
-pluginsd="${NETDATA_PLUGINS_DIR}"
-confd="${NETDATA_CONFIG_DIR}"
-chartsd="$pluginsd/../charts.d"
-
-myconfig="$confd/$PROGRAM_NAME.conf"
-
-minimum_update_frequency="${NETDATA_UPDATE_EVERY-1}"
-update_every=${minimum_update_frequency} # this will be overwritten by the command line
-
-# work around for non BASH shells
-charts_create="_create"
-charts_update="_update"
-charts_check="_check"
-charts_undescore="_"
-
-# when making iterations, charts.d can loop more frequently
-# to prevent plugins missing iterations.
-# this is a percentage relative to update_every to align its
-# iterations.
-# The minimum is 10%, the maximum 100%.
-# So, if update_every is 1 second and time_divisor is 50,
-# charts.d will iterate every 500ms.
-# Charts will be called to collect data only if the time
-# passed since the last time the collected data is equal or
-# above their update_every.
-time_divisor=50
-
-# number of seconds to run without restart
-# after this time, charts.d.plugin will exit
-# netdata will restart it
-restart_timeout=$((3600 * 4))
-
-# check if the charts.d plugins are using global variables
-# they should not.
-# It does not currently support BASH v4 arrays, so it is
-# disabled
-dryrunner=0
-
-# check for timeout command
-check_for_timeout=1
-
-# the default enable/disable value for all charts
-enable_all_charts="yes"
-
-# -----------------------------------------------------------------------------
-# parse parameters
-
-check=0
-chart_only=
-while [ ! -z "$1" ]
-do
- if [ "$1" = "check" ]
- then
- check=1
- shift
- continue
- fi
-
- if [ "$1" = "debug" -o "$1" = "all" ]
- then
- debug=1
- shift
- continue
- fi
-
- if [ -f "$chartsd/$1.chart.sh" ]
- then
- debug=1
- chart_only="$( echo $1.chart.sh | sed "s/\.chart\.sh$//g" )"
- shift
- continue
- fi
-
- if [ -f "$chartsd/$1" ]
- then
- debug=1
- chart_only="$( echo $1 | sed "s/\.chart\.sh$//g" )"
- shift
- continue
- fi
-
- # number check
- n="$1"
- x=$(( n ))
- if [ "$x" = "$n" ]
- then
- shift
- update_every=$x
- [ $update_every -lt $minimum_update_frequency ] && update_every=$minimum_update_frequency
- continue
- fi
-
- fatal "Cannot understand parameter $1. Aborting."
-done
-
-
-# -----------------------------------------------------------------------------
-# loop control
-
-# default sleep function
-LOOPSLEEPMS_HIGHRES=0
-now_ms=
-current_time_ms_default() {
- now_ms="$(date +'%s')000"
-}
-current_time_ms="current_time_ms_default"
-current_time_ms_accuracy=1
-mysleep="sleep"
-
-# if found and included, this file overwrites loopsleepms()
-# and current_time_ms() with a high resolution timer function
-# for precise looping.
-. "$pluginsd/loopsleepms.sh.inc"
-
-# -----------------------------------------------------------------------------
-# load my configuration
-
-if [ -f "$myconfig" ]
- then
- . "$myconfig"
- [ $? -ne 0 ] && fatal "cannot load $myconfig"
-
- time_divisor=$((time_divisor))
- [ $time_divisor -lt 10 ] && time_divisor=10
- [ $time_divisor -gt 100 ] && time_divisor=100
-else
- info "configuration file '$myconfig' not found. Using defaults."
-fi
-
-# we check for the timeout command, after we load our
-# configuration, so that the user may overwrite the
-# timeout command we use, providing a function that
-# can emulate the timeout command we need:
-# > timeout SECONDS command ...
-if [ $check_for_timeout -eq 1 ]
- then
- require_cmd timeout || exit 1
-fi
-
-# -----------------------------------------------------------------------------
-# internal checks
-
-# netdata passes the requested update frequency as the first argument
-update_every=$(( update_every + 1 - 1)) # makes sure it is a number
-test $update_every -eq 0 && update_every=1 # if it is zero, make it 1
-
-# check the charts.d directory
-[ ! -d "$chartsd" ] && fatal "cannot find charts directory '$chartsd'"
-
-# -----------------------------------------------------------------------------
-# library functions
-
-fixid() {
- echo "$*" |\
- tr -c "[A-Z][a-z][0-9]" "_" |\
- sed -e "s|^_\+||g" -e "s|_\+$||g" -e "s|_\+|_|g" |\
- tr "[A-Z]" "[a-z]"
-}
-
-run() {
- local ret pid="${BASHPID}" t
-
- if [ "z${1}" = "z-t" -a "${2}" != "0" ]
- then
- t="${2}"
- shift 2
- timeout ${t} "${@}" 2>"${TMP_DIR}/run.${pid}"
- ret=$?
- else
- "${@}" 2>"${TMP_DIR}/run.${pid}"
- ret=$?
- fi
-
- if [ ${ret} -ne 0 ]
- then
- {
- printf "$(logdate): ${PROGRAM_NAME}: ${status}: ${MODULE_NAME}: command '"
- printf "%q " "${@}"
- printf "' failed:\n --- BEGIN TRACE ---\n"
- cat "${TMP_DIR}/run.${pid}"
- printf " --- END TRACE ---\n"
- } >&2
- fi
- rm "${TMP_DIR}/run.${pid}"
-
- return ${ret}
-}
-
-# convert any floating point number
-# to integer, give a multiplier
-# the result is stored in ${FLOAT2INT_RESULT}
-# so that no fork is necessary
-# the multiplier must be a power of 10
-float2int() {
- local f m="$2" a b l v=($1)
- f=${v[0]}
-
- # the length of the multiplier - 1
- l=$(( ${#m} - 1 ))
-
- # check if the number is in scientific notation
- if [[ ${f} =~ ^[[:space:]]*(-)?[0-9.]+(e|E)(\+|-)[0-9]+ ]]
- then
- # convert it to decimal
- # unfortunately, this fork cannot be avoided
- # if you know of a way to avoid it, please let me know
- f=$(printf "%0.${l}f" ${f})
- fi
-
- # split the floating point number
- # in integer (a) and decimal (b)
- a=${f/.*/}
- b=${f/*./}
-
- # if the integer part is missing
- # set it to zero
- [ -z "${a}" ] && a="0"
-
- # strip leading zeros from the integer part
- # base 10 convertion
- a=$((10#$a))
-
- # check the length of the decimal part
- # against the length of the multiplier
- if [ ${#b} -gt ${l} ]
- then
- # too many digits - take the most significant
- b=${b:0:${l}}
-
- elif [ ${#b} -lt ${l} ]
- then
- # too few digits - pad with zero on the right
- local z="00000000000000000000000" r=$((l - ${#b}))
- b="${b}${z:0:${r}}"
- fi
-
- # strip leading zeros from the decimal part
- # base 10 convertion
- b=$((10#$b))
-
- # store the result
- FLOAT2INT_RESULT=$(( (a * m) + b ))
-}
-
-
-# -----------------------------------------------------------------------------
-# charts check functions
-
-all_charts() {
- cd "$chartsd"
- [ $? -ne 0 ] && error "cannot cd to $chartsd" && return 1
-
- ls *.chart.sh | sed "s/\.chart\.sh$//g"
-}
-
-declare -A charts_enable_keyword=(
- ['apache']="force"
- ['cpu_apps']="force"
- ['cpufreq']="force"
- ['example']="force"
- ['exim']="force"
- ['hddtemp']="force"
- ['load_average']="force"
- ['mem_apps']="force"
- ['mysql']="force"
- ['nginx']="force"
- ['phpfpm']="force"
- ['postfix']="force"
- ['sensors']="force"
- ['squid']="force"
- ['tomcat']="force"
- )
-
-all_enabled_charts() {
- local charts= enabled= required=
-
- # find all enabled charts
-
- for chart in $( all_charts )
- do
- MODULE_NAME="${chart}"
-
- eval "enabled=\$$chart"
- if [ -z "${enabled}" ]
- then
- enabled="${enable_all_charts}"
- fi
-
- required="${charts_enable_keyword[${chart}]}"
- [ -z "${required}" ] && required="yes"
-
- if [ ! "${enabled}" = "${required}" ]
- then
- info "is disabled. Add a line with $chart=$required in $myconfig to enable it (or remove the line that disables it)."
- else
- debug "is enabled for auto-detection."
- local charts="$charts $chart"
- fi
- done
- MODULE_NAME="main"
-
- local charts2=
- for chart in $charts
- do
- MODULE_NAME="${chart}"
-
- # check the enabled charts
- local check="$( cat "$chartsd/$chart.chart.sh" | sed "s/^ \+//g" | grep "^$chart$charts_check()" )"
- if [ -z "$check" ]
- then
- error "module '$chart' does not seem to have a $chart$charts_check() function. Disabling it."
- continue
- fi
-
- local create="$( cat "$chartsd/$chart.chart.sh" | sed "s/^ \+//g" | grep "^$chart$charts_create()" )"
- if [ -z "$create" ]
- then
- error "module '$chart' does not seem to have a $chart$charts_create() function. Disabling it."
- continue
- fi
-
- local update="$( cat "$chartsd/$chart.chart.sh" | sed "s/^ \+//g" | grep "^$chart$charts_update()" )"
- if [ -z "$update" ]
- then
- error "module '$chart' does not seem to have a $chart$charts_update() function. Disabling it."
- continue
- fi
-
- # check its config
- #if [ -f "$confd/$chart.conf" ]
- #then
- # if [ ! -z "$( cat "$confd/$chart.conf" | sed "s/^ \+//g" | grep -v "^$" | grep -v "^#" | grep -v "^$chart$charts_undescore" )" ]
- # then
- # error "module's $chart config $confd/$chart.conf should only have lines starting with $chart$charts_undescore . Disabling it."
- # continue
- # fi
- #fi
-
- #if [ $dryrunner -eq 1 ]
- # then
- # "$pluginsd/charts.d.dryrun-helper.sh" "$chart" "$chartsd/$chart.chart.sh" "$confd/$chart.conf" >/dev/null
- # if [ $? -ne 0 ]
- # then
- # error "module's $chart did not pass the dry run check. This means it uses global variables not starting with $chart. Disabling it."
- # continue
- # fi
- #fi
-
- local charts2="$charts2 $chart"
- done
- MODULE_NAME="main"
-
- echo $charts2
- debug "enabled charts: $charts2"
-}
-
-# -----------------------------------------------------------------------------
-# load the charts
-
-suffix_retries="_retries"
-suffix_update_every="_update_every"
-active_charts=
-for chart in $( all_enabled_charts )
-do
- MODULE_NAME="${chart}"
-
- debug "loading module: '$chartsd/$chart.chart.sh'"
-
- . "$chartsd/$chart.chart.sh"
-
- if [ -f "$confd/$PROGRAM_NAME/$chart.conf" ]
- then
- debug "loading module configuration: '$confd/$PROGRAM_NAME/$chart.conf'"
- . "$confd/$PROGRAM_NAME/$chart.conf"
- elif [ -f "$confd/$chart.conf" ]
- then
- debug "loading module configuration: '$confd/$chart.conf'"
- . "$confd/$chart.conf"
- else
- warning "configuration file '$confd/$PROGRAM_NAME/$chart.conf' not found. Using defaults."
- fi
-
- eval "dt=\$$chart$suffix_update_every"
- dt=$(( dt + 1 - 1 )) # make sure it is a number
- if [ $dt -lt $update_every ]
- then
- eval "$chart$suffix_update_every=$update_every"
- fi
-
- $chart$charts_check
- if [ $? -eq 0 ]
- then
- debug "module '$chart' activated"
- active_charts="$active_charts $chart"
- else
- error "module's '$chart' check() function reports failure."
- fi
-done
-MODULE_NAME="main"
-debug "activated modules: $active_charts"
-
-
-# -----------------------------------------------------------------------------
-# check overwrites
-
-# enable work time reporting
-debug_time=
-test $debug -eq 1 && debug_time=tellwork
-
-# if we only need a specific chart, remove all the others
-if [ ! -z "${chart_only}" ]
-then
- debug "requested to run only for: '${chart_only}'"
- check_charts=
- for chart in $active_charts
- do
- if [ "$chart" = "$chart_only" ]
- then
- check_charts="$chart"
- break
- fi
- done
- active_charts="$check_charts"
-fi
-debug "activated charts: $active_charts"
-
-# stop if we just need a pre-check
-if [ $check -eq 1 ]
-then
- info "CHECK RESULT"
- info "Will run the charts: $active_charts"
- exit 0
-fi
-
-# -----------------------------------------------------------------------------
-
-cd "${TMP_DIR}" || exit 1
-
-# -----------------------------------------------------------------------------
-# create charts
-
-run_charts=
-for chart in $active_charts
-do
- MODULE_NAME="${chart}"
-
- debug "calling '$chart$charts_create()'..."
- $chart$charts_create
- if [ $? -eq 0 ]
- then
- run_charts="$run_charts $chart"
- debug "'$chart' initialized."
- else
- error "module's '$chart' function '$chart$charts_create()' reports failure."
- fi
-done
-MODULE_NAME="main"
-debug "run_charts='$run_charts'"
-
-
-# -----------------------------------------------------------------------------
-# update dimensions
-
-[ -z "$run_charts" ] && fatal "No charts to collect data from."
-
-declare -A charts_last_update=() charts_update_every=() charts_retries=() charts_next_update=() charts_run_counter=() charts_serial_failures=()
-global_update() {
- local exit_at \
- c=0 dt ret last_ms exec_start_ms exec_end_ms \
- chart now_charts=() next_charts=($run_charts) \
- next_ms x seconds millis
-
- # return the current time in ms in $now_ms
- ${current_time_ms}
-
- exit_at=$(( now_ms + (restart_timeout * 1000) ))
-
- for chart in $run_charts
- do
- eval "charts_update_every[$chart]=\$$chart$suffix_update_every"
- test -z "${charts_update_every[$chart]}" && charts_update_every[$chart]=$update_every
-
- eval "charts_retries[$chart]=\$$chart$suffix_retries"
- test -z "${charts_retries[$chart]}" && charts_retries[$chart]=10
-
- charts_last_update[$chart]=$((now_ms - (now_ms % (charts_update_every[$chart] * 1000) ) ))
- charts_next_update[$chart]=$(( charts_last_update[$chart] + (charts_update_every[$chart] * 1000) ))
- charts_run_counter[$chart]=0
- charts_serial_failures[$chart]=0
-
- echo "CHART netdata.plugin_chartsd_$chart '' 'Execution time for $chart plugin' 'milliseconds / run' charts.d netdata.plugin_charts area 145000 ${charts_update_every[$chart]}"
- echo "DIMENSION run_time 'run time' absolute 1 1"
- done
-
- # the main loop
- while [ "${#next_charts[@]}" -gt 0 ]
- do
- c=$((c + 1))
- now_charts=("${next_charts[@]}")
- next_charts=()
-
- # return the current time in ms in $now_ms
- ${current_time_ms}
-
- for chart in "${now_charts[@]}"
- do
- MODULE_NAME="${chart}"
-
- if [ ${now_ms} -ge ${charts_next_update[$chart]} ]
- then
- last_ms=${charts_last_update[$chart]}
- dt=$(( (now_ms - last_ms) ))
-
- charts_last_update[$chart]=${now_ms}
-
- while [ ${charts_next_update[$chart]} -lt ${now_ms} ]
- do
- charts_next_update[$chart]=$(( charts_next_update[$chart] + (charts_update_every[$chart] * 1000) ))
- done
-
- # the first call should not give a duration
- # so that netdata calibrates to current time
- dt=$(( dt * 1000 ))
- charts_run_counter[$chart]=$(( charts_run_counter[$chart] + 1 ))
- if [ ${charts_run_counter[$chart]} -eq 1 ]
- then
- dt=
- fi
-
- exec_start_ms=$now_ms
- $chart$charts_update $dt
- ret=$?
-
- # return the current time in ms in $now_ms
- ${current_time_ms}; exec_end_ms=$now_ms
-
- echo "BEGIN netdata.plugin_chartsd_$chart $dt"
- echo "SET run_time = $(( exec_end_ms - exec_start_ms ))"
- echo "END"
-
- if [ $ret -eq 0 ]
- then
- charts_serial_failures[$chart]=0
- next_charts+=($chart)
- else
- charts_serial_failures[$chart]=$(( charts_serial_failures[$chart] + 1 ))
-
- if [ ${charts_serial_failures[$chart]} -gt ${charts_retries[$chart]} ]
- then
- error "module's '$chart' update() function reported failure ${charts_serial_failures[$chart]} times. Disabling it."
- else
- error "module's '$chart' update() function reports failure. Will keep trying for a while."
- next_charts+=($chart)
- fi
- fi
- else
- next_charts+=($chart)
- fi
- done
- MODULE_NAME="${chart}"
-
- # wait the time you are required to
- next_ms=$((now_ms + (update_every * 1000 * 100) ))
- for x in "${charts_next_update[@]}"; do [ ${x} -lt ${next_ms} ] && next_ms=${x}; done
- next_ms=$((next_ms - now_ms))
-
- if [ ${LOOPSLEEPMS_HIGHRES} -eq 1 -a ${next_ms} -gt 0 ]
- then
- next_ms=$(( next_ms + current_time_ms_accuracy ))
- seconds=$(( next_ms / 1000 ))
- millis=$(( next_ms % 1000 ))
- if [ ${millis} -lt 10 ]
- then
- millis="00${millis}"
- elif [ ${millis} -lt 100 ]
- then
- millis="0${millis}"
- fi
-
- debug "sleeping for ${seconds}.${millis} seconds."
- ${mysleep} ${seconds}.${millis}
- else
- debug "sleeping for ${update_every} seconds."
- ${mysleep} $update_every
- fi
-
- test ${now_ms} -ge ${exit_at} && exit 0
- done
-
- fatal "nothing left to do, exiting..."
-}
-
-global_update