fully working config handling. support for multiple metrics of the same type. implement signal trapping
This commit is contained in:
parent
f06e238b85
commit
e0a528859f
|
@ -7,7 +7,7 @@ metrics.sh is a lightweight metrics collection and fowarding utility implemented
|
|||
```
|
||||
$ ./metrics.sh --help
|
||||
|
||||
Usage: ./metrics.sh [-d] [-h] [-v] [-m metrics] [-r reporter] [-i interval]
|
||||
Usage: ./metrics.sh [-d] [-h] [-v] [-c] [-m] [-r] [-i]
|
||||
|
||||
Options:
|
||||
|
||||
|
@ -54,8 +54,7 @@ TODO: how to write custom reporters
|
|||
## TODO
|
||||
|
||||
- README
|
||||
- config file support
|
||||
- config file docs
|
||||
- config file auto-generation
|
||||
- load custom/contrib metrics and reporters
|
||||
- same metric multiple times? (e.g. disk_usage for multiple devices)
|
||||
- allow multiple reporters?
|
123
lib/main.sh
123
lib/main.sh
|
@ -28,9 +28,6 @@ main_load () {
|
|||
# register metric
|
||||
__AVAILABLE_METRICS=$(trim "$__AVAILABLE_METRICS $metric")
|
||||
done
|
||||
|
||||
load_metric_with_prefix __m_${metric}_ $file
|
||||
|
||||
}
|
||||
|
||||
main_init () {
|
||||
|
@ -41,12 +38,6 @@ main_init () {
|
|||
# create temp dir
|
||||
TEMP_DIR=$(make_temp_dir)
|
||||
|
||||
# register trap
|
||||
trap '
|
||||
main_terminate
|
||||
trap - TERM && kill -- -$$ INT TERM EXIT
|
||||
' INT TERM EXIT
|
||||
|
||||
# check if reporter exists
|
||||
if ! in_array $__REPORTER "$__AVAILABLE_REPORTERS"; then
|
||||
echo "Error: reporter '$__REPORTER' is not available"
|
||||
|
@ -63,78 +54,96 @@ main_init () {
|
|||
done
|
||||
|
||||
# init reporter
|
||||
if is_function __r_${__REPORTER}_config; then
|
||||
__r_${__REPORTER}_config
|
||||
fi
|
||||
if is_function __r_${__REPORTER}_init; then
|
||||
__r_${__REPORTER}_init
|
||||
fi
|
||||
|
||||
# init metrics
|
||||
for metric in $__METRICS; do
|
||||
local metric_name=$(get_name $metric)
|
||||
local metric_alias=$(get_alias $metric)
|
||||
|
||||
load_metric_with_prefix __m_${metric_alias}_ ./metrics/${metric_name}.sh
|
||||
|
||||
if ! is_function __m_${metric_alias}_init; then
|
||||
continue
|
||||
fi
|
||||
|
||||
__m_${metric_alias}_init
|
||||
done
|
||||
}
|
||||
|
||||
main_collect () {
|
||||
# used by metrics to return results
|
||||
report () {
|
||||
local _r_label _r_result
|
||||
if [ -z $2 ]; then
|
||||
_r_label=$metric
|
||||
_r_result="$1"
|
||||
else
|
||||
_r_label="$metric.$1"
|
||||
_r_result="$2"
|
||||
fi
|
||||
if is_number $_r_result; then
|
||||
__r_${__REPORTER}_report $_r_label $_r_result
|
||||
fi
|
||||
}
|
||||
# register trap
|
||||
trap '
|
||||
trap "" 13
|
||||
trap - INT TERM EXIT
|
||||
echo Exit signal received.
|
||||
kill -13 -$$
|
||||
' 13 INT TERM EXIT
|
||||
|
||||
# collect metrics
|
||||
for metric in $__METRICS; do
|
||||
metric=$(get_alias $metric)
|
||||
if ! is_function __m_${metric}_collect; then
|
||||
continue
|
||||
fi
|
||||
# run in subshell to isolate scope
|
||||
(
|
||||
local metric_name=$(get_name $metric)
|
||||
local metric_alias=$(get_alias $metric)
|
||||
# used by metrics to return results
|
||||
report () {
|
||||
local _r_label _r_result
|
||||
if [ -z $2 ]; then
|
||||
_r_label=$metric_alias
|
||||
_r_result="$1"
|
||||
else
|
||||
_r_label="$metric_alias.$1"
|
||||
_r_result="$2"
|
||||
fi
|
||||
if is_number $_r_result; then
|
||||
__r_${__REPORTER}_report $_r_label $_r_result
|
||||
fi
|
||||
}
|
||||
|
||||
# fork
|
||||
(while true; do
|
||||
__m_${metric}_collect
|
||||
sleep $INTERVAL
|
||||
done) &
|
||||
# init metric
|
||||
if is_function __m_${metric_alias}_config; then
|
||||
__m_${metric_alias}_config
|
||||
fi
|
||||
|
||||
load_metric_with_prefix __m_${metric_alias}_ ./metrics/${metric_name}.sh
|
||||
|
||||
if is_function __m_${metric_alias}_init; then
|
||||
__m_${metric_alias}_init
|
||||
fi
|
||||
|
||||
if ! is_function __m_${metric_alias}_collect; then
|
||||
continue
|
||||
fi
|
||||
|
||||
# collect metrics
|
||||
trap "
|
||||
if is_function __m_${metric_alias}_terminate; then
|
||||
verbose 'Stopping metric ${metric_alias}'
|
||||
__m_${metric_alias}_terminate
|
||||
fi
|
||||
exit 0
|
||||
" 13
|
||||
|
||||
while true; do
|
||||
__m_${metric_alias}_collect
|
||||
sleep $INTERVAL
|
||||
done
|
||||
) &
|
||||
done
|
||||
|
||||
# run forever
|
||||
sleep 2147483647 # `sleep infinity` is not portable
|
||||
# wait until interrupted
|
||||
wait
|
||||
# then wait again for processes to end
|
||||
wait
|
||||
|
||||
main_terminate
|
||||
}
|
||||
|
||||
main_terminate () {
|
||||
# terminate metrics
|
||||
for metric in $__METRICS; do
|
||||
metric=$(get_alias $metric)
|
||||
if ! is_function __m_${metric}_terminate; then
|
||||
continue
|
||||
fi
|
||||
__m_${metric}_terminate
|
||||
done
|
||||
|
||||
# terminate reporter
|
||||
if is_function __r_${__REPORTER}_terminate; then
|
||||
verbose "Stopping reporter ${__REPORTER}"
|
||||
__r_${__REPORTER}_terminate
|
||||
fi
|
||||
|
||||
verbose -n "Cleaning up..."
|
||||
# delete temporary directory
|
||||
if [ -d $TEMP_DIR ]; then
|
||||
rmdir $TEMP_DIR
|
||||
fi
|
||||
verbose "done"
|
||||
}
|
||||
|
||||
main_docs () {
|
||||
|
|
|
@ -24,7 +24,6 @@ parse_config () {
|
|||
|
||||
local _group
|
||||
local _name
|
||||
local _alias
|
||||
local _body
|
||||
|
||||
end_section () {
|
||||
|
@ -34,20 +33,16 @@ parse_config () {
|
|||
|
||||
local fn_name
|
||||
if [ "$_group" = "reporter" ]; then
|
||||
__CFG_REPORTERS=$(trim "${__CFG_REPORTERS} ${_name}:${_alias}")
|
||||
__CFG_REPORTERS=$(trim "${__CFG_REPORTERS} ${_name}")
|
||||
fn_name="__r_"
|
||||
elif [ "$_group" = "metric" ]; then
|
||||
__CFG_METRICS=$(trim "${__CFG_METRICS} ${_name}:${_alias}")
|
||||
__CFG_METRICS=$(trim "${__CFG_METRICS} ${_name}")
|
||||
fn_name="__m_"
|
||||
else
|
||||
fn_name="global"
|
||||
fn_name="main"
|
||||
fi
|
||||
|
||||
if [ -n "$_alias" ]; then
|
||||
fn_name="${fn_name}${_alias}"
|
||||
elif [ -n "$_name" ]; then
|
||||
fn_name="${fn_name}${_name}"
|
||||
fi
|
||||
fn_name=${fn_name}$(get_alias $_name)
|
||||
|
||||
if [ -z "$_body" ]; then
|
||||
return
|
||||
|
@ -68,7 +63,7 @@ parse_config () {
|
|||
local _section=$(echo $line | grep '^\[.*' | sed 's/\[\(.*\)\]/\1/')
|
||||
if [ -n "$_section" ]; then
|
||||
end_section
|
||||
unset _group _name _alias _body
|
||||
unset _group _name _body
|
||||
|
||||
_group=$(echo $_section | awk '{ print $1 }')
|
||||
|
||||
|
@ -78,13 +73,11 @@ parse_config () {
|
|||
fi
|
||||
|
||||
if [ "$_group" = "metrics.sh" ]; then
|
||||
_group="global"
|
||||
_group="main"
|
||||
continue
|
||||
fi
|
||||
|
||||
_section=$(echo $_section | awk '{ print $2 }')
|
||||
_name=$(echo $_section | awk 'BEGIN { FS=":" } { print $1 }')
|
||||
_alias=$(echo $_section | awk 'BEGIN { FS=":" } { print $2 }')
|
||||
_name=$(echo $_section | awk '{ print $2 }')
|
||||
continue
|
||||
fi
|
||||
|
||||
|
|
|
@ -16,4 +16,11 @@ in_array () {
|
|||
|
||||
trim () {
|
||||
echo $1 | sed -e 's/^[[:space:]]*//g' -e 's/[[:space:]]*\$//g'
|
||||
}
|
||||
|
||||
unique_id () {
|
||||
RESTORE_LC_ALL=$LC_ALL
|
||||
LC_ALL=C
|
||||
echo __u_$(cat /dev/urandom | tr -dc 'A-Za-z0-9' | head -c 10)
|
||||
LC_ALL=$RESTORE_LC_ALL
|
||||
}
|
|
@ -12,7 +12,7 @@ LANG=en_US.UTF-8
|
|||
LANGUAGE=en_US.UTF-8
|
||||
|
||||
usage () {
|
||||
echo " Usage: $0 [-d] [-h] [-v] [-m metrics] [-r reporter] [-i interval]"
|
||||
echo " Usage: $0 [-d] [-h] [-v] [-c] [-m] [-r] [-i]"
|
||||
}
|
||||
|
||||
help () {
|
||||
|
@ -82,10 +82,11 @@ done
|
|||
# run
|
||||
. ./lib/main.sh
|
||||
|
||||
if [ $opt_verbose = "true" ]; then
|
||||
if [ $opt_verbose = true ]; then
|
||||
verbose_on
|
||||
verbose "Started in verbose mode"
|
||||
fi
|
||||
verbose "PID: $$"
|
||||
verbose "OS detected: $OS_TYPE"
|
||||
|
||||
main_load
|
||||
|
@ -105,8 +106,8 @@ if [ -n "$CONFIG_FILE" ]; then
|
|||
exit 1
|
||||
fi
|
||||
|
||||
if is_function global_config; then
|
||||
global_config
|
||||
if is_function main_config; then
|
||||
main_config
|
||||
fi
|
||||
|
||||
configured_reporters=$(get_configured_reporters)
|
||||
|
|
|
@ -8,7 +8,7 @@ init () {
|
|||
DISK_IO_MOUNTPOINT="/dev/vda"
|
||||
fi
|
||||
fi
|
||||
readonly __disk_io_fifo=$TEMP_DIR/disk_io
|
||||
readonly __disk_io_fifo=$TEMP_DIR/$(unique_id)
|
||||
mkfifo $__disk_io_fifo
|
||||
__disk_io_bgproc &
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue