Skip to content

Instantly share code, notes, and snippets.

@lillesvin
Last active December 11, 2019 11:40
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save lillesvin/0f1cf5205e169ab3b6579ae877d779a6 to your computer and use it in GitHub Desktop.
Save lillesvin/0f1cf5205e169ab3b6579ae877d779a6 to your computer and use it in GitHub Desktop.
Monitor a file looking for a string. If the moving average of the interval is lower than THRESHOLD, do something!
#!/bin/bash
# This is executed whenever conditions are met
# Change this to whatever you would like to have happen
alert() {
echo 'ALERT, ALERT!!!'
printf "Average hit interval: %.2f sec.\n" "$AVG"
printf "Threshold: %d sec.\n" "$THRESHOLD"
printf "Window length: %d\n" "$WINDOW_LENGTH"
printf "Last window: %s\n" "${INTERVALS[*]}"
echo "---"
}
usage() {
cat <<EOF
Usage: $0 [-t INT] [-w INT] [-i INT] <SEARCH> <FILE>
-t Threshold. When the simple moving average drops below
this, trigger an alert. (Default: 5)
-w Window length. Amount of samples to base the moving
average on. (Default: 10)
-i Forced minimum interval between alerts. (Default: 30)
EOF
}
# Defaults
THRESHOLD=5
WINDOW_LENGTH=10
ALERT_INTERVAL=30
while getopts ":t:w:i:h" opt; do
case "${opt}" in
t)
THRESHOLD=${OPTARG}
;;
w)
WINDOW_LENGTH=${OPTARG}
;;
i)
ALERT_INTERVAL=${OPTARG}
;;
h)
usage
exit
;;
*)
usage
exit 1
;;
esac
done
shift $(($OPTIND - 1))
STRING=$1
LOGFILE=$2
INTERVALS=()
LAST=`date +%s`
LAST_ALERT=0
# Header
printf "Monitoring: %s\n" "$LOGFILE"
printf "Watching for: %s\n" "$STRING"
printf "Threshold: %d sec.\n" "$THRESHOLD"
printf "Window length: %d\n" "$WINDOW_LENGTH"
echo "---"
tail -n 0 -F "$LOGFILE" | grep --line-buffered -F "$STRING" | while read; do
# Append latest interval
INTERVALS+=("$(($(date +%s) - $LAST))")
LAST=`date +%s`
# Slice to window length
if [[ ${#INTERVALS[@]} -ge $WINDOW_LENGTH ]]; then
INTERVALS=("${INTERVALS[@]: -$WINDOW_LENGTH:$WINDOW_LENGTH}")
fi
# Calculate average
if [[ ${#INTERVALS[@]} -gt 1 ]]; then
AVG=$(printf "scale=2; (%s)/%d\n" $(IFS=+; echo -n "${INTERVALS[*]}") ${#INTERVALS[@]} | bc)
fi
# Do stuff
if [[ ${#INTERVALS[@]} -ge $WINDOW_LENGTH ]]; then
if (( `echo "$AVG < $THRESHOLD" | bc` )) && (( `echo "($LAST_ALERT + $ALERT_INTERVAL) < $(date +%s)" | bc` )); then
alert
LAST_ALERT=$(date +%s)
fi
fi
done
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment