mirror of
https://github.com/munin-monitoring/contrib.git
synced 2018-11-08 00:59:34 +01:00
315 lines
8.6 KiB
Bash
Executable File
315 lines
8.6 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
|
|
# Tested with ejabberd 2.1.x
|
|
#
|
|
# This plugin is capable to show:
|
|
# - ejabberd memory usage (RSS, VSZ, erlang internal)
|
|
# - ejabberd ports/processes usage
|
|
# - online/registered users by vhost
|
|
# - mnesia table sizes and location
|
|
#
|
|
# Required permissions:
|
|
# - read ejabberdctl configuration file
|
|
# - connect to a running ejabberd node
|
|
#
|
|
# OS: *NIX
|
|
# Requires lsof/fstat for open_files.
|
|
#
|
|
# Author: Artem Sheremet <dot.doom@gmail.com>
|
|
#
|
|
# Configuration:
|
|
# - set env.ejabberdctl_cfg to ejabberdctl.cfg path if not in /etc
|
|
# - or set env.ERLANG_NODE, env.EJABBERD_PID_PATH to proper values manually
|
|
# - set erl_call_path to unregular erl_call location
|
|
# - set env.ejabberdctl to ejabberdctl script path if not on PATH
|
|
|
|
#%# family=auto
|
|
#%# capabilities=autoconf suggest
|
|
|
|
EJABBERDCTL_CFG=${ejabberdctl_cfg:-/etc/ejabberd/ejabberdctl.cfg}
|
|
source $EJABBERDCTL_CFG 2>/dev/null
|
|
source $MUNIN_LIBDIR/plugins/plugin.sh
|
|
|
|
EJABBERDCTL=${ejabberdctl:-$(which ejabberdctl)}
|
|
|
|
ERLANG_HOST=${ERLANG_NODE/*@/}
|
|
ERLANG_MUNIN_NODE=munin
|
|
|
|
if [ -n "$erl_path" ] && [ -z "$erl_call_path" ]; then
|
|
erl_call_path="$erl_path"_call
|
|
fi
|
|
|
|
ERL_CALL=${erl_call_path:-$(which erl_call)}
|
|
|
|
function ejabberd_exec() {
|
|
echo "$1" | su - ejabberd -c "$ERL_CALL -e -n $ERLANG_NODE" | sed -re 's/^\{ok, (.*)\}$/\1/'
|
|
}
|
|
|
|
SCRIPT_NAME=$(basename $0)
|
|
RESOURCE_TYPE="${SCRIPT_NAME/ejabberd_resources_/}"
|
|
RESOURCE_BASE=1000
|
|
[ "$RESOURCE_TYPE" = "memory" ] && RESOURCE_BASE=1024
|
|
|
|
function hosts_list() {
|
|
ejabberd_exec 'ejabberd_config:get_global_option(hosts).' | tr '[]",' ' '
|
|
}
|
|
|
|
function ejabberd_report_online_users() {
|
|
[ "$1" = "config" ] && echo 'graph_vlabel users'
|
|
for host in $(hosts_list); do
|
|
local clean_host=$(clean_fieldname $host)
|
|
local ejabberd_command="length(ejabberd_sm:get_vh_session_list(\"$host\"))"
|
|
if [ "$1" = "config" ]; then
|
|
cat <<CONFIG
|
|
${clean_host}.draw AREASTACK
|
|
${clean_host}.label $host
|
|
${clean_host}.info $ejabberd_command
|
|
CONFIG
|
|
else
|
|
echo "$clean_host.value $(ejabberd_exec ${ejabberd_command}.)"
|
|
fi
|
|
done
|
|
}
|
|
|
|
function ejabberd_report_registered_users() {
|
|
[ "$1" = "config" ] && echo 'graph_vlabel users'
|
|
for host in $(hosts_list); do
|
|
local clean_host=$(clean_fieldname $host)
|
|
local ejabberd_command="ejabberd_auth:get_vh_registered_users_number(\"$host\")"
|
|
if [ "$1" = "config" ]; then
|
|
cat <<CONFIG
|
|
${clean_host}.draw AREASTACK
|
|
${clean_host}.label $host
|
|
${clean_host}.info $ejabberd_command
|
|
CONFIG
|
|
else
|
|
echo "$clean_host.value $(ejabberd_exec ${ejabberd_command}.)"
|
|
fi
|
|
done
|
|
}
|
|
|
|
|
|
function ejabberd_report_memory() {
|
|
if [ "$1" = "config" ]; then
|
|
cat <<CONFIG
|
|
graph_vlabel bytes
|
|
rss.draw LINE2
|
|
rss.label rss
|
|
rss.info Resident set size
|
|
vsz.draw LINE2
|
|
vsz.label vsz
|
|
vsz.info Virtual memory size
|
|
CONFIG
|
|
for memory_type in total processes system atom binary code ets; do
|
|
cat <<CONFIG
|
|
$memory_type.draw LINE2
|
|
$memory_type.label $memory_type
|
|
CONFIG
|
|
done
|
|
cat <<INFO_FROM_DOC
|
|
total.info The total amount of memory currently allocated, which is the same as the sum of memory size for processes and system.
|
|
processes.info The total amount of memory currently allocated by the Erlang processes.
|
|
system.info The total amount of memory currently allocated by the emulator that is not directly related to any Erlang process. Memory presented as processes is not included in this memory.
|
|
atom.info The total amount of memory currently allocated for atoms. This memory is part of the memory presented as system memory.
|
|
binary.info The total amount of memory currently allocated for binaries. This memory is part of the memory presented as system memory.
|
|
code.info The total amount of memory currently allocated for Erlang code. This memory is part of the memory presented as system memory.
|
|
ets.info The total amount of memory currently allocated for ets tables. This memory is part of the memory presented as system memory.
|
|
INFO_FROM_DOC
|
|
else
|
|
local pid=$(<$EJABBERD_PID_PATH)
|
|
for memory_type in rss vsz; do
|
|
memory_value=$(ps -p $pid -o $memory_type=)
|
|
let memory_value=$memory_value*1024
|
|
echo "$memory_type.value $memory_value"
|
|
done
|
|
ejabberd_exec 'io_lib:format("~p", [erlang:memory()]).' | grep -Eo '"[a-z_0-9]+"' |
|
|
sed -re 'N;s/"(.*)"\n"(.*)"/\1.value \2/' | grep -Fv _used
|
|
fi
|
|
}
|
|
|
|
function ejabberd_report_ports() {
|
|
local limit=$(ejabberd_exec 'os:getenv("ERL_MAX_PORTS").' | tr '"' ' ')
|
|
# string "false" indicates that this variable is not defined, thus a default of 1024
|
|
[ $limit = false ] && limit=1024
|
|
if [ "$1" = "config" ]; then
|
|
cat <<CONFIG
|
|
graph_vlabel ports
|
|
open.draw LINE
|
|
open.label open
|
|
open.info length(erlang:ports())
|
|
limit.draw LINE2
|
|
limit.label limit
|
|
limit.info ERL_MAX_PORTS environment variable inside ejabberd
|
|
CONFIG
|
|
warning='80%' critical='90%' print_adjusted_thresholds open $limit
|
|
[ -n "$ERL_MAX_PORTS" ] && cat <<CONFIG_CONFIGURED
|
|
configured.draw LINE
|
|
configured.label configured
|
|
configured.info Configuration file value ERL_MAX_PORTS
|
|
CONFIG_CONFIGURED
|
|
else
|
|
local open=$(ejabberd_exec 'length(erlang:ports()).')
|
|
cat <<DATA
|
|
open.value $open
|
|
limit.value $limit
|
|
DATA
|
|
[ -n "$ERL_MAX_PORTS" ] && echo "configured.value $ERL_MAX_PORTS"
|
|
fi
|
|
}
|
|
|
|
function ejabberd_report_mnesia() {
|
|
local draw sed_re long_bits
|
|
|
|
sed_re='([a-z_]+) *: with ([0-9]+) +records occupying ([0-9]+) +([a-z]+) o[fn] ([a-z]+)'
|
|
# 1 = table_name
|
|
# 2 = records number
|
|
# 3 = bytes/words number
|
|
# 4 = unit (bytes or words)
|
|
# 5 = storage (disc or mem)
|
|
|
|
if [ "$1" = config ]; then
|
|
echo "graph_vlabel $2"
|
|
draw=LINE2
|
|
[ "$2" = bytes ] && draw=AREASTACK
|
|
|
|
$EJABBERDCTL mnesia info | sed -re 's/'"$sed_re"'/\1 \5/;tx;d;:x' |
|
|
while read table_name table_storage; do
|
|
echo "${table_name}_${table_storage}.draw $draw"
|
|
echo "${table_name}_${table_storage}.label $table_name ($table_storage)"
|
|
done
|
|
else
|
|
if [ "$2" = recs ]; then
|
|
$EJABBERDCTL mnesia info | sed -re 's/'"$sed_re"'/\1_\5.value \2/;tx;d;:x'
|
|
else
|
|
long_bits=$(getconf LONG_BIT)
|
|
$EJABBERDCTL mnesia info |
|
|
sed -re 's/'"$sed_re"'/\1_\5.value \3 \4/;tx;d;:x' |
|
|
awk "
|
|
/ words\$/ {
|
|
print \$1, \$2 * $long_bits / 8
|
|
}
|
|
/ bytes\$/ {
|
|
print \$1, \$2
|
|
}
|
|
"
|
|
fi
|
|
fi
|
|
}
|
|
|
|
function ejabberd_report_mnesia_bytes() {
|
|
ejabberd_report_mnesia "$1" bytes
|
|
}
|
|
|
|
function ejabberd_report_mnesia_recs() {
|
|
ejabberd_report_mnesia "$1" recs
|
|
}
|
|
|
|
function ejabberd_report_process_links() {
|
|
ejabberd_exec "
|
|
lists:filtermap(
|
|
fun(Name) ->
|
|
case whereis(Name) of
|
|
Pid when is_pid(Pid) ->
|
|
{links, Links} = erlang:process_info(Pid, links),
|
|
{true, {Name, length(Links)}};
|
|
_ ->
|
|
false
|
|
end,
|
|
registered())"
|
|
}
|
|
|
|
function open_files_counter_util() {
|
|
if hash lsof &>/dev/null; then
|
|
echo lsof
|
|
return 0
|
|
elif hash fstat &>/dev/null; then
|
|
echo fstat
|
|
return 0
|
|
fi
|
|
return 1
|
|
}
|
|
|
|
function open_files_number() {
|
|
echo $[$($(open_files_counter_util) -np $(<$EJABBERD_PID_PATH) | wc -l)-1]
|
|
}
|
|
|
|
function ejabberd_report_open_files() {
|
|
# this spawns a child process, but in most cases the open files limit is inherited
|
|
local limit=$(ejabberd_exec 'os:cmd("ulimit -n").' | tr '"\\n' ' ')
|
|
if [ "$1" = "config" ]; then
|
|
cat <<CONFIG
|
|
graph_vlabel open files
|
|
open.draw LINE
|
|
open.label open
|
|
open.info number of open files as reported by $(open_files_counter_util)
|
|
limit.draw LINE2
|
|
limit.label limit
|
|
limit.info "ulimit -n" from inside of ejabberd
|
|
CONFIG
|
|
warning='80%' critical='90%' print_adjusted_thresholds open $limit
|
|
else
|
|
cat <<DATA
|
|
open.value $(open_files_number)
|
|
limit.value $limit
|
|
DATA
|
|
fi
|
|
}
|
|
|
|
function ejabberd_report_processes() {
|
|
local limit=$(ejabberd_exec 'erlang:system_info(process_limit).')
|
|
if [ "$1" = "config" ]; then
|
|
cat <<CONFIG
|
|
graph_vlabel processes
|
|
active.draw LINE
|
|
active.label active
|
|
active.info erlang:system_info(process_count)
|
|
limit.draw LINE2
|
|
limit.label limit
|
|
limit.info erlang:system_info(process_limit)
|
|
CONFIG
|
|
warning='80%' critical='90%' print_adjusted_thresholds active $limit
|
|
[ -n "$ERL_PROCESSES" ] && cat <<CONFIG_CONFIGURED
|
|
configured.draw LINE
|
|
configured.label configured
|
|
configured.info Configuration file value ERL_PROCESSES
|
|
CONFIG_CONFIGURED
|
|
else
|
|
local active=$(ejabberd_exec 'erlang:system_info(process_count).')
|
|
cat <<DATA
|
|
active.value $active
|
|
limit.value $limit
|
|
DATA
|
|
[ -n "$ERL_PROCESSES" ] && echo "configured.value $ERL_PROCESSES"
|
|
fi
|
|
}
|
|
|
|
case $1 in
|
|
autoconf)
|
|
[ -r "$EJABBERDCTL_CFG" ] && echo yes || echo no
|
|
exit 0
|
|
;;
|
|
suggest)
|
|
cat <<SUGGESTIONS
|
|
memory
|
|
processes
|
|
ports
|
|
process_links
|
|
online_users
|
|
registered_users
|
|
mnesia_recs
|
|
mnesia_bytes
|
|
SUGGESTIONS
|
|
open_files_counter_util &>/dev/null && echo open_files
|
|
exit 0
|
|
;;
|
|
config)
|
|
cat <<CONFIG
|
|
graph_title ejabberd resources - ${RESOURCE_TYPE//_/ }
|
|
graph_args --base $RESOURCE_BASE --lower-limit 0
|
|
graph_category chat
|
|
CONFIG
|
|
;;
|
|
esac
|
|
|
|
ejabberd_report_${RESOURCE_TYPE} $1
|