mirror of
https://github.com/munin-monitoring/contrib.git
synced 2025-07-21 18:41:03 +00:00
[internode_usage] New plugin for Australian ISP Internode
* Add BUGS and SPDX license * Add dirtyconfig support * Use ideal usage as warning
This commit is contained in:
parent
92db831bc3
commit
691e52b868
4 changed files with 224 additions and 0 deletions
BIN
plugins/isp/example-graphs/internode_current-day.png
Normal file
BIN
plugins/isp/example-graphs/internode_current-day.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 31 KiB |
BIN
plugins/isp/example-graphs/internode_daily-week.png
Normal file
BIN
plugins/isp/example-graphs/internode_daily-week.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 25 KiB |
BIN
plugins/isp/example-graphs/internode_usage-month.png
Normal file
BIN
plugins/isp/example-graphs/internode_usage-month.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 27 KiB |
224
plugins/isp/internode_usage
Executable file
224
plugins/isp/internode_usage
Executable file
|
@ -0,0 +1,224 @@
|
||||||
|
#!/bin/sh -u
|
||||||
|
# -*- sh -*-
|
||||||
|
|
||||||
|
: << =cut
|
||||||
|
|
||||||
|
=head1 NAME
|
||||||
|
|
||||||
|
internode_usage - Plugin to monitor quota usage of an Internode service
|
||||||
|
|
||||||
|
The ideal usage is also used as an updated warning limit.
|
||||||
|
|
||||||
|
=head1 CONFIGURATION
|
||||||
|
|
||||||
|
[internode_usage]
|
||||||
|
env.internode_api_login LOGIN
|
||||||
|
env.internode_api_password PASSWORD
|
||||||
|
|
||||||
|
An optional 'env.internode_api_url' can be used, but should not be needed. It
|
||||||
|
will default to https://customer-webtools-api.internode.on.net/api/v1.5.
|
||||||
|
|
||||||
|
If multiple services are available, the plugin will automatically pick the first
|
||||||
|
service from the list. To monitor other services, the plugin can be used
|
||||||
|
multiple times, by symlinking it as 'internode_usage_SERVICEID'.
|
||||||
|
|
||||||
|
=head1 CAVEATS
|
||||||
|
|
||||||
|
* The hourly rate are a bit spikey in the -day view, as the API seems to update
|
||||||
|
every 20 to 30 minutes; it is fine in the -month and more aggregated views
|
||||||
|
* The daily rate is the _previous_ day, and does always lag by 24h
|
||||||
|
* Due to the way the API seems to update the data, values for the daily rate
|
||||||
|
are missing for a short period every day
|
||||||
|
|
||||||
|
=head1 AUTHOR
|
||||||
|
|
||||||
|
Olivier Mehani
|
||||||
|
|
||||||
|
Copyright (C) 2019 Olivier Mehani <shtrom+munin@ssji.net>
|
||||||
|
|
||||||
|
=head1 LICENSE
|
||||||
|
|
||||||
|
SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
|
||||||
|
=cut
|
||||||
|
|
||||||
|
# shellcheck disable=SC1090
|
||||||
|
. "${MUNIN_LIBDIR:-.}/plugins/plugin.sh"
|
||||||
|
|
||||||
|
if [ "${MUNIN_DEBUG:-0}" = 1 ]; then
|
||||||
|
set -x
|
||||||
|
fi
|
||||||
|
|
||||||
|
if ! command -v curl >/dev/null; then
|
||||||
|
echo "curl not found" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
if ! command -v xpath >/dev/null; then
|
||||||
|
echo "xpath (Perl XML::LibXML) not found" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
if ! command -v bc >/dev/null; then
|
||||||
|
echo "bc not found" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -z "${internode_api_url:-}" ]; then
|
||||||
|
internode_api_url="https://customer-webtools-api.internode.on.net/api/v1.5"
|
||||||
|
fi
|
||||||
|
|
||||||
|
xpath_extract() {
|
||||||
|
xpath="$1"
|
||||||
|
xpath -q -n -e "${xpath}" | \
|
||||||
|
sed 's/<\([^>]*\)>\([^<]*\)<[^>]*>/\2/'
|
||||||
|
}
|
||||||
|
|
||||||
|
xpath_extract_attribute() {
|
||||||
|
xpath="$1"
|
||||||
|
xpath -q -n -e "${xpath}" | \
|
||||||
|
sed 's/.*="\([^"]\+\)".*/\1/'
|
||||||
|
}
|
||||||
|
|
||||||
|
fetch() {
|
||||||
|
# shellcheck disable=SC2154
|
||||||
|
curl -u "${internode_api_login}:${internode_api_password}" -s "$@"
|
||||||
|
}
|
||||||
|
|
||||||
|
get_data() {
|
||||||
|
SERVICE_XML="$(fetch "${internode_api_url}/${SERVICE_ID}/service")"
|
||||||
|
SERVICE_USERNAME="$(echo "${SERVICE_XML}" | xpath_extract "internode/api/service/username")"
|
||||||
|
SERVICE_QUOTA="$(echo "${SERVICE_XML}" | xpath_extract "internode/api/service/quota")"
|
||||||
|
SERVICE_PLAN="$(echo "${SERVICE_XML}" | xpath_extract "internode/api/service/plan")"
|
||||||
|
SERVICE_ROLLOVER="$(echo "${SERVICE_XML}" | xpath_extract "internode/api/service/rollover")"
|
||||||
|
SERVICE_INTERVAL="$(echo "${SERVICE_XML}" | xpath_extract "internode/api/service/plan-interval" | sed 's/ly$//')"
|
||||||
|
|
||||||
|
HISTORY_XML="$(fetch "${internode_api_url}/${SERVICE_ID}/history")"
|
||||||
|
TODAY_TIMESTAMP="$(date +%s)"
|
||||||
|
DAILY_DATE="$(date +%Y-%m-%d -d yesterday)"
|
||||||
|
DAILY_TIMESTAMP="$(date -d "${DAILY_DATE} $(date +%H:%M:%S)" +%s)"
|
||||||
|
DAILY_USAGE="$(echo "${HISTORY_XML}" | xpath_extract "internode/api/usagelist/usage[@day=\"${DAILY_DATE}\"]/traffic")"
|
||||||
|
|
||||||
|
USAGE_XML="$(fetch "${internode_api_url}/${SERVICE_ID}/usage")"
|
||||||
|
SERVICE_USAGE="$(echo "${USAGE_XML}" | xpath_extract "internode/api/traffic")"
|
||||||
|
|
||||||
|
USAGE_CRITICAL="${SERVICE_QUOTA}"
|
||||||
|
USAGE_WARNING="$(echo "${SERVICE_QUOTA}*.75" | bc -ql)"
|
||||||
|
|
||||||
|
TODAY="$(date +%s)"
|
||||||
|
FIRST_DAY="$(date +%s --date "${SERVICE_ROLLOVER} -1 ${SERVICE_INTERVAL}")"
|
||||||
|
LAST_DAY="$(date +%s --date "${SERVICE_ROLLOVER}")"
|
||||||
|
BILLING_PERIOD="(${LAST_DAY}-${FIRST_DAY})"
|
||||||
|
IDEAL_USAGE="$(echo "${SERVICE_QUOTA}-(${SERVICE_QUOTA}*(${LAST_DAY}-${TODAY})/${BILLING_PERIOD})" | bc -ql)"
|
||||||
|
}
|
||||||
|
|
||||||
|
graph_config() {
|
||||||
|
graph=""
|
||||||
|
if [ -n "${1:-}" ]; then
|
||||||
|
graph=".$1"
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "multigraph internode_usage_${SERVICE_ID}${graph}"
|
||||||
|
|
||||||
|
case "$graph" in
|
||||||
|
.current)
|
||||||
|
echo "graph_title Hourly rate for ${SERVICE_USERNAME}"
|
||||||
|
echo 'graph_category network'
|
||||||
|
# ${graph_period} is not a shell variable
|
||||||
|
# shellcheck disable=SC2016
|
||||||
|
echo 'graph_vlabel bytes per ${graph_period}'
|
||||||
|
# XXX: this seems to be updated twice per hour;
|
||||||
|
# the data from this graph may be nonsense
|
||||||
|
echo 'graph_period hour'
|
||||||
|
|
||||||
|
echo "hourly_rate.label Hourly usage"
|
||||||
|
echo "hourly_rate.type DERIVE"
|
||||||
|
echo "hourly_rate.min 0"
|
||||||
|
|
||||||
|
;;
|
||||||
|
.daily)
|
||||||
|
echo "graph_title Previous-day usage for ${SERVICE_USERNAME}"
|
||||||
|
echo 'graph_category network'
|
||||||
|
# ${graph_period} is not a shell variable
|
||||||
|
# shellcheck disable=SC2016
|
||||||
|
echo 'graph_vlabel bytes per ${graph_period}'
|
||||||
|
echo 'graph_period day'
|
||||||
|
|
||||||
|
echo "daily_rate.label Previous-day usage"
|
||||||
|
echo "daily_rate.type GAUGE"
|
||||||
|
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
#.usage)
|
||||||
|
echo "graph_title Uplink usage for ${SERVICE_USERNAME}"
|
||||||
|
echo 'graph_category network'
|
||||||
|
echo 'graph_vlabel bytes'
|
||||||
|
echo 'graph_period hour'
|
||||||
|
|
||||||
|
echo "usage.label Total usage"
|
||||||
|
echo "usage.draw AREA"
|
||||||
|
echo "usage.extinfo ${SERVICE_PLAN}; rollover: ${SERVICE_ROLLOVER}"
|
||||||
|
echo "ideal.label Ideal usage"
|
||||||
|
echo "ideal.draw LINE"
|
||||||
|
echo "ideal.colour FFA500"
|
||||||
|
|
||||||
|
echo "usage.critical ${USAGE_CRITICAL}"
|
||||||
|
echo "usage.warning ${IDEAL_USAGE}"
|
||||||
|
echo "ideal.critical 0:"
|
||||||
|
echo "ideal.warning 0:"
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
echo
|
||||||
|
}
|
||||||
|
|
||||||
|
graph_data() {
|
||||||
|
graph=""
|
||||||
|
if [ -n "${1:-}" ]; then
|
||||||
|
graph=".${1}"
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "multigraph internode_usage_${SERVICE_ID}${graph}"
|
||||||
|
case "${graph}" in
|
||||||
|
.current)
|
||||||
|
echo "hourly_rate.value ${TODAY_TIMESTAMP}:${SERVICE_USAGE:-U}"
|
||||||
|
;;
|
||||||
|
.daily)
|
||||||
|
echo "daily_rate.value ${DAILY_TIMESTAMP}:${DAILY_USAGE:-U}"
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
echo "usage.value ${TODAY_TIMESTAMP}:${SERVICE_USAGE:-U}"
|
||||||
|
echo "ideal.value ${TODAY_TIMESTAMP}:${IDEAL_USAGE:-U}"
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
echo
|
||||||
|
}
|
||||||
|
|
||||||
|
main() {
|
||||||
|
case ${1:-} in
|
||||||
|
config)
|
||||||
|
graph_config
|
||||||
|
graph_config usage
|
||||||
|
graph_config current
|
||||||
|
graph_config daily
|
||||||
|
if [ "${MUNIN_CAP_DIRTYCONFIG:-0}" = "1" ]; then
|
||||||
|
main
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
graph_data
|
||||||
|
graph_data usage
|
||||||
|
graph_data current
|
||||||
|
graph_data daily
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
}
|
||||||
|
|
||||||
|
# Determine the service ID from the name of the symlink
|
||||||
|
SERVICE_ID="$(echo "${0}" | sed -n 's/^.*internode_usage_//p')"
|
||||||
|
if [ -z "${SERVICE_ID}" ]; then
|
||||||
|
API_XML="$(fetch "${internode_api_url}")"
|
||||||
|
# Otherwise, get the first service in the list
|
||||||
|
SERVICE_ID="$(echo "${API_XML}" | xpath_extract "internode/api/services/service")"
|
||||||
|
fi
|
||||||
|
|
||||||
|
get_data
|
||||||
|
|
||||||
|
main ${1:-}
|
Loading…
Add table
Add a link
Reference in a new issue