Merge tag 'release_3_0_12' into branch moonshot-fr-3.0.12-upgrade.
[freeradius.git] / scripts / munin / radsniff
1 #!/bin/sh
2 : << =cut
3
4 =head1 NAME
5
6 radsniff - A plugin to consume statistics generated by radsniff via collectd RRD files
7
8 =head1 APPLICABLE SYSTEMS
9
10 radsniff 3.1.x or later
11
12 =head1 CONFIGURATION
13
14 This plugin uses the following configuration variables:
15
16  [radsniff]
17   env.host       - The host collectd thinks the radsniff data
18                    originated from (defaults to current host).
19   env.rrd_path   - Path to the directory containing rrd files.
20   env.type       - Either radius_rtx, radius_latency or radius_count
21   env.pkt_type   - The type of packet to graph.
22   env.instance   - radsniff instance name (passed to radsniff with -N).
23
24 =head1 AUTHOR
25
26 Copyright (C) 2014 Arran Cudbard-Bell <a.cudbardb@freeradius.org>
27
28 =head1 LICENSE
29
30  This program is free software; you can redistribute it and/or modify
31  it under the terms of the GNU General Public License as published by
32  the Free Software Foundation; either version 2 of the License, or
33  (at your option) any later version.
34
35  This program is distributed in the hope that it will be useful,
36  but WITHOUT ANY WARRANTY; without even the implied warranty of
37  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
38  GNU General Public License for more details.
39
40  You should have received a copy of the GNU General Public License
41  along with this program; if not, write to the Free Software
42  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
43
44 =head1 MAGIC MARKERS
45
46  #%# family=manual
47
48 =cut
49
50 if [ -z "$type" ]; then
51     echo "env.type must be set" >&2
52     exit -1
53 fi
54
55 if [ -z "$pkt_type" ]; then
56     echo "env.pkt_type must be set" >&2
57     exit -1
58 fi
59
60 if [ "$1" = "config" ]; then
61     pretty_pkt_type=`echo "$pkt_type" | sed -e 's/_/ /g' | sed 's/^./\U&\E/'`
62
63     case "$type" in
64         radius_rtx)
65             echo "graph_title ${pretty_pkt_type} rtx"
66             echo 'graph_args --base 1000 -l 0 '
67             echo 'graph_period second'
68             echo 'graph_vlabel Exchanged / ${graph_period}'
69             echo 'graph_category RADIUS'
70
71             echo 'none.label no loss'
72             echo 'none.info Responses received after first request'
73             echo 'none.type GAUGE'
74             echo 'none.min 0'
75
76             echo 'one.label 1'
77             echo 'one.info Responses received after one retransmission'
78             echo 'one.type GAUGE'
79             echo 'one.min 0'
80
81             echo 'two.label 2'
82             echo 'two.info Responses received after two retransmissions'
83             echo 'two.type GAUGE'
84             echo 'two.min 0'
85
86             echo 'three.label 3'
87             echo 'three.info Responses received after three retransmissions'
88             echo 'three.type GAUGE'
89             echo 'three.min 0'
90
91             echo 'four.label 4'
92             echo 'four.info Responses received after four retransmissions'
93             echo 'four.type GAUGE'
94             echo 'four.min 0'
95
96             echo 'more.label more'
97             echo 'more.info Responses received after more than four retransmissions'
98             echo 'more.type GAUGE'
99             echo 'more.min 0'
100
101             echo 'lost.label lost'
102             echo 'lost.info Requests to which no response was seen'
103             echo 'lost.type GAUGE'
104             echo 'lost.min 0'
105             ;;
106
107         radius_latency)
108             echo "graph_title ${pretty_pkt_type} latency"
109             echo 'graph_args --base 1000 -l 0 '
110             echo 'graph_vlabel Latency (ms)'
111             echo 'graph_category RADIUS'
112
113             echo 'smoothed.label smoothed avg'
114             echo 'smoothed.info Smoothed average'
115             echo 'smoothed.type GAUGE'
116             echo 'smoothed.min 0'
117
118             echo 'avg.label avg'
119             echo 'avg.info Average latency over the stats interval'
120             echo 'avg.type GAUGE'
121             echo 'avg.min 0'
122
123             echo 'high.label high'
124             echo 'high.info Highest latency over the stats interval'
125             echo 'high.type GAUGE'
126             echo 'high.min 0'
127
128             echo 'low.label low'
129             echo 'low.info Lowest latency over the stats interval'
130             echo 'low.type GAUGE'
131             echo 'low.min 0'
132             ;;
133
134         radius_count)
135             echo "graph_title $pretty_pkt_type counters"
136             echo 'graph_args --base 1000 -l 0 '
137             echo 'graph_period second'
138             echo 'graph_vlabel Packets / ${graph_period}'
139             echo 'graph_category RADIUS'
140
141             echo 'received.label received'
142             echo 'received.info Packets of this type received'
143             echo 'received.type GAUGE'
144             echo 'received.min 0'
145
146             echo 'linked.label linked'
147             echo 'linked.info Packets linked to another request or response'
148             echo 'linked.type GAUGE'
149             echo 'linked.min 0'
150
151             echo 'unlinked.label unlinked'
152             echo 'unlinked.info Packets not linked to another request or response'
153             echo 'unlinked.type GAUGE'
154             echo 'unlinked.min 0'
155
156             echo 'reused.label reused'
157             echo 'reused.info Request which (prematurely) re-used the same ID as a previous request'
158             echo 'reused.type GAUGE'
159             echo 'reused.min 0'
160             ;;
161         *)
162             echo "env.type ($type) is invalid must be radius_rtx, radius_latency, or radius_count" >&2
163             exit -1
164     esac
165     exit 0
166 fi
167
168 HOST=${host:-`hostname -f`}
169 INSTANCE=${instance:-'radsniff'}
170 RRD_PATH=${rrd_path:-"/var/lib/collectd/rrd/${HOST}/${INSTANCE}-exchanged"}
171 RRD_PATH="${RRD_PATH}/${type}-${pkt_type}.rrd"
172 RRD_RES=${rrd_res:-300}
173
174 if [ ! -e "$RRD_PATH" ]; then
175     echo "rrd file '$RRD_PATH' does not exist" >&2
176     exit -1
177 fi
178
179 fetch_data()
180 {
181     # RRD tool doesn't always select the correct period (seems
182     # to round up and give us -nan results) in the interest of
183     # gap free graphing, we attempt to get the last two periods
184     # worth of data, and then use the newest non -nan one.
185     # It's not perfect and should be fixed at some point...
186     rrd_last=`rrdtool fetch "$RRD_PATH" $1 -r $RRD_RES -e $(expr $(date +%s) / $RRD_RES \* $RRD_RES) -s end-$(expr $RRD_RES \* 2)`; ret=$?
187     if [ $ret -ne 0 ]; then
188         echo "$rrd_last" >&2
189         exit $ret
190     fi
191     echo "$rrd_last" | head -1
192     echo "$rrd_last" | grep '^[0-9]*:' | grep -v -E '^[0-9]*:( -nan)*$' | tail -1
193 }
194
195 fetch_data_column()
196 {
197     echo "$(fetch_data $1)" | tail -1 | cut -d ' ' -f $(expr $2 + 2)
198 }
199
200 case "$type" in
201     radius_rtx)
202         col=2
203         rrd_data=$(fetch_data 'AVERAGE')
204         for var in `echo "$rrd_data" | head -1`; do
205             case "$var" in
206                 1) printf "one.value ";;
207                 2) printf "two.value ";;
208                 3) printf "three.value ";;
209                 4) printf "four.value ";;
210                 *) printf "$var.value ";;
211             esac
212             echo "$rrd_data" | tail -1 | cut -d ' ' -f $col
213             col=`expr $col + 1`
214         done
215         ;;
216
217     radius_count)
218         col=2
219         rrd_data=$(fetch_data 'AVERAGE')
220         for var in `echo "$rrd_data" | head -1`; do
221             printf "$var.value "
222             echo "$rrd_data" | tail -1 | cut -d ' ' -f $col
223             col=`expr $col + 1`
224         done
225         ;;
226
227     radius_latency)
228         printf "smoothed.value "
229         fetch_data_column 'AVERAGE' 0
230
231         printf "avg.value "
232         fetch_data_column 'AVERAGE' 1
233
234         # Averages here are unacceptable because we use this to detect
235         # abnormally long delays in responses, and if we average all the highs
236         # over a five minute period, transient spikes in latency may be lost.
237         printf "high.value "
238         fetch_data_column 'MAX' 2
239
240         # Again we need the lowest value of the set here, as an abnormally
241         # quick response may indicate something is wrong.
242         printf "low.value "
243         fetch_data_column 'MIN' 3
244         ;;
245 esac
246 exit 0