2
0
mirror of https://github.com/munin-monitoring/contrib.git synced 2018-11-08 00:59:34 +01:00

Add Solaris io_disk plugin

- Merge io_* plugins into one multigraph plugin
- Change graph appearance like linux diskstats plugin
  RRD files generated by io_busy_, io_ios_, io_bytes_ can be taken over
- Add queue and latency functions
- Remove perl code and replace old Solaris::MapDev feature by
  using iostat
- Add POD style document
- Refactoring, using functions, replace variable names, check with
  shellcheck
This commit is contained in:
K.Cima 2017-03-24 23:14:47 +09:00
parent fb32a774c8
commit 2590132015

301
plugins/solaris/io_disk Executable file
View File

@ -0,0 +1,301 @@
#!/bin/bash
: << =cut
=head1 NAME
io_disk - Multigraph plugin to monitor disks for Solaris.
These functions are implemented:
ops : similar to iostat r/s, w/s
bytes : similar to iostat kr/s, kw/s
busy : similar to iostat %b, %w
queue : similar to iostat actv, wait
latency : similar to iostat asvc_t, wsvc_t
Any device found in /usr/bin/kstat can be monitored.
Tested with Solaris 10 and 11, and it should work with Solaris 8, 9.
=head1 CONFIGURATION
Make symlink:
cd /path/to/munin/etc/plugins
ln -s /path/to/munin/lib/plugins/io_disk .
The RRD files generated by io_busy_, io_ops_, io_bytes_ can be taken over
by this plugin.
Thus, please remove symlinks of those plugins before using this plugin.
By default, this plugin monitors disk devices. And also it can monitor
NFS and Tape devices as much as io_* plugins with setting environments.
=head1 ENVIRONMENT VARIABLES
env.class - kstat class. See man kstat -c option.
example: env.class /disk|nfs|tape/
default: disk
env.module - Module name. Only used in internal graph name. If you would not
to like to take over RRDs generated by io_*_sd plugins, please change it
to another name.
example: env.module something
default: sd
env.module_regex - kstat module. See man kstat -m option.
example: env.module_regex /^(s?sd|vdc|zvblk|dad|md|nfs|tape)$/
default: /^(s?sd|vdc|zvblk|dad|md)$/
env.title_type - Device type shown in graph title.
example: env.title_type Disk Device, NFS, Tape
default: Disk Device
env.exclude - Device instance name(s) to exclude seperated by white-space.
example: env.exclude sd0 ssd1
default: none
env.graph_width - Graph width in pixel
example: env.graph_width 450
default: none (usually 400)
=head1 AUTHOR
Unknown Author
Improved by K.Cima https://github.com/shakemid
=head1 LICENSE
GPLv2
=head1 MAGIC MARKERS
#%# family=auto
#%# capabilities=autoconf
=cut
# Include plugin.sh
. "${MUNIN_LIBDIR:-}/plugins/plugin.sh"
is_multigraph "$@"
# Shell options
set -o nounset
set -o pipefail
# Set environment variables
plugin_name=io
functions='ops bytes busy queue latency'
: "${class:=disk}"
: "${module:=sd}"
: "${module_regex:=/^(s?sd|vdc|zvblk|dad|md)\$/}"
: "${title_type:=Disk Device}"
: "${exclude:=}"
: "${graph_width:=}"
# Create map of instance name (e.g. sd0) and logical device name (e.g. c0t0d0)
# Example:
# name_sd1=c0t0d0
# name_ssd2=c0tAB_1234d0 (shorten long target)
# ...
declare $( paste -d= \
<( iostat -x | awk '{print $1}' | sed -e '1,2d' -e 's/^/name_/' ) \
<( iostat -xn | awk '{print $NF}' | sed -e '1,2d' -e 's/^\(c[0-9]*\)\(t.\{2\}\).*\(.\{4\}\)\(d[0-9]*\)$/\1\2_\3\4/' ) \
)
# Functions
preconfig() {
local func
func=$1
case "$func" in
ops)
conf_title='I/O Operations'
conf_in=reads
conf_out=writes
conf_cdef=
conf_gargs='--base 1000'
conf_vlabel='Ops per second write (-) / read (+)'
;;
bytes)
conf_title='I/O Throughput'
conf_in=nread
conf_out=nwritten
conf_cdef=
conf_gargs='--base 1024'
conf_vlabel='Bytes per second write (-) / read (+)'
;;
busy)
conf_title='Busy & Wait'
conf_in=rtime
conf_out=wtime
conf_cdef=',100,*'
conf_gargs='--base 1000 --lower-limit 0 --upper-limit 100'
conf_vlabel='% wait (-) / busy (+)'
;;
queue)
conf_title='Queue Length'
conf_in=rlentime
conf_out=wlentime
conf_cdef=
conf_gargs='--base 1000'
conf_vlabel='Queue length wait (-) / actv (+)'
;;
latency)
conf_title='Latency'
conf_in=rlentime
conf_out=wlentime
conf_cdef=
conf_gargs='--base 1000'
conf_vlabel='Seconds wsvc_t (-) / asvc_t (+)'
;;
*)
echo "Unknown function: $func"
exit 1
;;
esac
}
is_excluded() {
local dev i
dev=$1
for i in ${exclude}
do
if [ "$dev" = "$i" ]; then
return 0
fi
done
return 1
}
do_config() {
local func dev ref devname stat
func=$1
preconfig "$func"
echo "multigraph ${plugin_name}_${func}_${module}"
echo "graph_title $title_type $conf_title"
echo 'graph_category disk'
echo "graph_args $conf_gargs"
echo "graph_vlabel $conf_vlabel"
if [ -n "$graph_width" ]; then
echo "graph_width $graph_width"
fi
kstat -p -c "$class" -m "$module_regex" -s "/^${conf_in}\$/" | sed 's/:/ /g' | awk '{ print $3 }' | \
while read -r dev
do
if is_excluded "$dev" ; then
continue
fi
# replace instance name to logical device name if exists
ref="name_$dev"
devname=${!ref:-}
# reads and writes are necessary to calculate latency
if [ "$func" = 'latency' ]; then
for stat in reads writes
do
echo "${dev}_$stat.label dummy"
echo "${dev}_$stat.graph no"
echo "${dev}_$stat.type DERIVE"
echo "${dev}_$stat.min 0"
done
# rlentime / ( reads + writes )
conf_cdef=,${dev}_reads,${dev}_writes,+,/
fi
echo "${dev}_${conf_out}.label dummy"
echo "${dev}_${conf_out}.graph no"
echo "${dev}_${conf_out}.type DERIVE"
echo "${dev}_${conf_out}.min 0"
echo "${dev}_${conf_in}.label ${devname:-${dev}}"
echo "${dev}_${conf_in}.negative ${dev}_${conf_out}"
echo "${dev}_${conf_in}.type DERIVE"
echo "${dev}_${conf_in}.min 0"
if [ -n "$conf_cdef" ]; then
echo "${dev}_${conf_out}.cdef ${dev}_${conf_out}${conf_cdef}"
echo "${dev}_${conf_in}.cdef ${dev}_${conf_in}${conf_cdef}"
fi
done
echo
}
do_getvalue() {
local func stat_regex dev stat value
func=$1
preconfig "$func"
if [ "$func" = 'latency' ]; then
stat_regex="/^($conf_in|$conf_out|reads|writes)\$/"
else
stat_regex="/^($conf_in|$conf_out)\$/"
fi
echo "multigraph ${plugin_name}_${func}_${module}"
kstat -p -c "$class" -m "$module_regex" -s "$stat_regex" | sed 's/:/ /g' | awk '{ print $3,$4,$5 }' | \
while read -r dev stat value
do
if is_excluded "$dev" ; then
continue
fi
echo "${dev}_${stat}.value ${value%.*}"
done
echo
}
autoconf() {
if [ -x /usr/bin/kstat ]; then
echo yes
exit 0
else
echo "no (/usr/bin/kstat not found)"
exit 0
fi
}
config() {
local func
for func in $functions
do
do_config "$func"
done
}
getvalue() {
local func
for func in $functions
do
do_getvalue "$func"
done
}
# main
case ${1:-} in
autoconf)
autoconf
;;
config)
config
;;
*)
getvalue
;;
esac
exit 0