4 PROGRAM_NAME="charts.d"
5 echo >&2 "$PROGRAM_NAME: started from '$PROGRAM_FILE' with options: $*"
7 if [ $(( ${BASH_VERSINFO[0]} )) -lt 4 ]
10 echo >&2 "$PROGRAM_NAME: ERROR"
11 echo >&2 "BASH version 4 or later is required."
12 echo >&2 "You are running version: ${BASH_VERSION}"
13 echo >&2 "Please upgrade."
18 # check a few commands
23 echo >&2 "$PROGRAM_NAME: ERROR: Command '$1' is not found in the system path."
29 require_cmd date || exit 1
30 require_cmd sed || exit 1
31 require_cmd basename || exit 1
32 require_cmd dirname || exit 1
33 require_cmd cat || exit 1
34 require_cmd grep || exit 1
35 require_cmd mktemp || exit 1
37 # -----------------------------------------------------------------------------
39 # netdata exposes a few environment variables for us
41 pause_method="sleep" # use either "suspend" or "sleep"
42 # DO NOT USE SUSPEND - LINUX WILL SUSPEND NETDATA TOO
43 # THE WHOLE PROCESS GROUP - NOT JUST THE SHELL
45 pluginsd="${NETDATA_PLUGINS_DIR}"
46 [ -z "$pluginsd" ] && pluginsd="$( dirname $PROGRAM_FILE )"
48 confd="${NETDATA_CONFIG_DIR-/etc/netdata}"
49 chartsd="$pluginsd/../charts.d"
50 myconfig="$confd/charts.d.conf"
52 minimum_update_frequency="${NETDATA_UPDATE_EVERY-1}"
53 update_every=${minimum_update_frequency} # this will be overwritten by the command line
55 # work around for non BASH shells
56 charts_create="_create"
57 charts_update="_update"
61 # -----------------------------------------------------------------------------
76 if [ "$1" = "debug" -o "$1" = "all" ]
83 if [ -f "$chartsd/$1.chart.sh" ]
86 chart_only="$( echo $1.chart.sh | sed "s/\.chart\.sh$//g" )"
91 if [ -f "$chartsd/$1" ]
94 chart_only="$( echo $1 | sed "s/\.chart\.sh$//g" )"
106 [ $update_every -lt $minimum_update_frequency ] && update_every=$minimum_update_frequency
110 echo >&2 "Cannot understand parameter $1. Aborting."
116 # -----------------------------------------------------------------------------
117 # load my configuration
119 if [ -f "$myconfig" ]
124 echo >&2 "$PROGRAM_NAME: cannot load $myconfig"
130 if [ "$pause_method" = "suspend" ]
132 # enable bash job control
133 # this is required for suspend to work
137 # -----------------------------------------------------------------------------
140 # netdata passes the requested update frequency as the first argument
141 update_every=$(( update_every + 1 - 1)) # makes sure it is a number
142 test $update_every -eq 0 && update_every=1 # if it is zero, make it 1
144 # check the charts.d directory
145 if [ ! -d "$chartsd" ]
147 echo >&2 "$PROGRAM_NAME: cannot find charts directory '$chartsd'"
152 # -----------------------------------------------------------------------------
155 # default sleep function
162 now_ms="$(date +'%s')000"
165 # if found and included, this file overwrites loopsleepms()
166 # and current_time_ms() with a high resolution timer function
167 # for precise looping.
168 . "$pluginsd/loopsleepms.sh.inc"
171 # -----------------------------------------------------------------------------
172 # charts check functions
176 [ $? -ne 0 ] && echo >&2 "$PROGRAM_NAME: Cannot cd to $chartsd" && return 1
178 ls *.chart.sh | sed "s/\.chart\.sh$//g"
181 all_enabled_charts() {
184 # find all enabled charts
186 for chart in $( all_charts )
188 eval "enabled=\$$chart"
189 if [ "$enabled" = "yes" ]
191 [ $debug -eq 1 ] && echo >&2 "$PROGRAM_NAME: '$chart' is enabled."
192 local charts="$charts $chart"
194 echo >&2 "$PROGRAM_NAME: '$chart' is NOT enabled. Add a line with $chart=yes in $myconfig to enable it."
201 # check the enabled charts
202 local check="$( cat "$chartsd/$chart.chart.sh" | sed "s/^ \+//g" | grep "^$chart$charts_check()" )"
205 echo >&2 "$PROGRAM_NAME: chart '$chart' does not seem to have a $chart$charts_check() function. Disabling it."
209 local create="$( cat "$chartsd/$chart.chart.sh" | sed "s/^ \+//g" | grep "^$chart$charts_create()" )"
212 echo >&2 "$PROGRAM_NAME: chart '$chart' does not seem to have a $chart$charts_create() function. Disabling it."
216 local update="$( cat "$chartsd/$chart.chart.sh" | sed "s/^ \+//g" | grep "^$chart$charts_update()" )"
219 echo >&2 "$PROGRAM_NAME: chart '$chart' does not seem to have a $chart$charts_update() function. Disabling it."
224 #if [ -f "$confd/$chart.conf" ]
226 # if [ ! -z "$( cat "$confd/$chart.conf" | sed "s/^ \+//g" | grep -v "^$" | grep -v "^#" | grep -v "^$chart$charts_undescore" )" ]
228 # echo >&2 "$PROGRAM_NAME: chart's $chart config $confd/$chart.conf should only have lines starting with $chart$charts_undescore . Disabling it."
233 "$pluginsd/charts.d.dryrun-helper.sh" "$chart" "$chartsd/$chart.chart.sh" "$confd/$chart.conf" >/dev/null
236 echo >&2 "$PROGRAM_NAME: chart's $chart did not pass the dry run check. This means it uses global variables not starting with $chart. Disabling it."
240 local charts2="$charts2 $chart"
244 [ $debug -eq 1 ] && echo >&2 "$PROGRAM_NAME: enabled charts: $charts2"
248 # -----------------------------------------------------------------------------
251 suffix_update_every="_update_every"
253 for chart in $( all_enabled_charts )
255 [ $debug -eq 1 ] && echo >&2 "$PROGRAM_NAME: loading chart: '$chartsd/$chart.chart.sh'"
256 . "$chartsd/$chart.chart.sh"
258 if [ -f "$confd/$chart.conf" ]
260 [ $debug -eq 1 ] && echo >&2 "$PROGRAM_NAME: loading chart options: '$confd/$chart.conf'"
261 . "$confd/$chart.conf"
264 eval "dt=\$$chart$suffix_update_every"
265 dt=$(( dt + 1 - 1 )) # make sure it is a number
266 if [ $dt -lt $update_every ]
268 eval "$chart$suffix_update_every=$update_every"
274 [ $debug -eq 1 ] && echo >&2 "$PROGRAM_NAME: '$chart' activated"
275 active_charts="$active_charts $chart"
277 echo >&2 "$PROGRAM_NAME: chart '$chart' check() function reports failure."
280 [ $debug -eq 1 ] && echo >&2 "$PROGRAM_NAME: activated charts: $active_charts"
283 # -----------------------------------------------------------------------------
286 # enable work time reporting
288 test $debug -eq 1 && debug_time=tellwork
290 # if we only need a specific chart, remove all the others
291 if [ ! -z "${chart_only}" ]
293 [ $debug -eq 1 ] && echo >&2 "$PROGRAM_NAME: requested to run only for: '${chart_only}'"
295 for chart in $active_charts
297 if [ "$chart" = "$chart_only" ]
299 check_charts="$chart"
303 active_charts="$check_charts"
305 [ $debug -eq 1 ] && echo >&2 "$PROGRAM_NAME: activated charts: $active_charts"
307 # stop if we just need a pre-check
310 echo >&2 "CHECK RESULT"
311 echo >&2 "Will run the charts: $active_charts"
315 # -----------------------------------------------------------------------------
321 if [ ! -z "$TMP_DIR" -a -d "$TMP_DIR" ]
323 [ $debug -eq 1 ] && echo >&2 "$PROGRAM_NAME: cleaning up temporary directory $TMP_DIR ..."
328 trap chartsd_cleanup EXIT
329 trap chartsd_cleanup SIGHUP
330 trap chartsd_cleanup INT
334 TMP_DIR="$( mktemp -d /var/run/netdata-charts.d-XXXXXXXXXX )"
336 TMP_DIR="$( mktemp -d /tmp/.netdata-charts.d-XXXXXXXXXX )"
339 cd "$TMP_DIR" || exit 1
341 # -----------------------------------------------------------------------------
346 tr -c "[A-Z][a-z][0-9]" "_" |\
347 sed -e "s|^_\+||g" -e "s|_\+$||g" -e "s|_\+|_|g" |\
352 # -----------------------------------------------------------------------------
356 for chart in $active_charts
358 [ $debug -eq 1 ] && echo >&2 "$PROGRAM_NAME: Calling '$chart$charts_create()'..."
362 run_charts="$run_charts $chart"
363 [ $debug -eq 1 ] && echo >&2 "$PROGRAM_NAME: '$chart' has initialized."
365 echo >&2 "$PROGRAM_NAME: chart '$chart' function '$chart$charts_create()' reports failure."
368 [ $debug -eq 1 ] && echo >&2 "$PROGRAM_NAME: run_charts='$run_charts'"
371 # -----------------------------------------------------------------------------
374 declare -A charts_last_update=() charts_min_dt=()
376 local exit_after=$((3600 / update_every)) \
378 chart now_charts=() next_charts=($run_charts)
380 # return the current time in ms in $now_ms
383 for chart in $run_charts
385 eval "charts_min_dt[$chart]=\$$chart$suffix_update_every"
386 test -z "${charts_min_dt[$chart]}" && charts_min_dt[$charts]=$update_every
387 charts_last_update[$chart]=$((now_ms - (charts_min_dt[$chart] * 1000) ))
394 now_charts=("${next_charts[@]}")
397 for chart in "${now_charts[@]}"
399 # return the current time in ms in $now_ms
402 dt=$(( (now_ms - charts_last_update[$chart]) * 1000 ))
403 if [ $dt -ge $(( charts_min_dt[$chart] * 1000000 )) ]
405 charts_last_update[$chart]=$now_ms
407 # the first call should not give a duration
408 # so that netdata calibrates to current time
411 $chart$charts_update $dt
414 next_charts+=($chart)
416 echo >&2 "$PROGRAM_NAME: chart '$chart' update() function reports failure. Disabling it."
419 next_charts+=($chart)
423 if [ "$pause_method" = "suspend" ]
425 echo "STOPPING_WAKE_ME_UP_PLEASE"
426 suspend || ( echo >&2 "$PROGRAM_NAME: suspend returned error $?, falling back to sleep."; loopsleepms $debug_time $update_every )
428 # wait the time you are required to
429 loopsleepms $debug_time $update_every
432 test $c -gt $exit_after && exit 0