docs: describe the pmdaroot process interfaces
[pcp.git] / src / pmlogsummary / pmdiff.sh
blobb9d35e7d03c7afee29586e777639fa95c3ba3cc2
1 #!/bin/sh
3 # Copyright (c) 2014 Red Hat.
4 # Copyright (c) 2008-2010 Aconex. All Rights Reserved.
5 #
6 # This program is free software; you can redistribute it and/or modify it
7 # under the terms of the GNU General Public License as published by the
8 # Free Software Foundation; either version 2 of the License, or (at your
9 # option) any later version.
11 # This program is distributed in the hope that it will be useful, but
12 # WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
13 # or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 # for more details.
16 # Compare two PCP archives and report significant differences
19 # Get standard environment
20 . $PCP_DIR/etc/pcp.env
22 tmp=`mktemp -d /var/tmp/pcp.XXXXXXXXX` || exit 1
23 status=1
24 trap "rm -rf $tmp; exit \$status" 0 1 2 3 15
25 prog=`basename $0`
27 cat > $tmp/usage << EOF
28 # Usage: [options] archive1 [archive2]
30 Options:
31 -d,--keep debug, keep intermediate files
32 -p=N,--precision=N number of digits to display after the decimal point
33 -q=N,--threshold=N change interesting threshold to be > N or < 1/N [N=2]
34 --skip-missing do not report metrics missing between the archives
35 --skip-excluded do not report the list of metrics being excluded
36 --start
37 --finish
38 -B=TIME,--begin=TIME start time for second archive (optional)
39 -E=TIME,--end=TIME end time for second archive (optional)
40 -x=REGEX egrep(1) pattern of metric(s) to be excluded
41 -X=FILE file containing egrep(1) patterns to exclude
42 --timezone
43 --hostzone
44 --help
45 EOF
47 _usage()
49 pmgetopt --usage --progname=$prog --config=$tmp/usage
50 exit $status
53 # filter the pmlogsummary output getting ready for join(1) ...
54 # - add | field separator between metric name and value
55 # - dodge chatter about metrics with insufficient data
56 # - dodge chatter from -z
57 # - exclude metrics we don't want
58 # - sort
60 _fix()
62 sed \
63 -e 's/ *\([0-9][0-9.]*\)\([^"]*\)$/|\1/' \
64 -e '/^\*.* - insufficient archive data.$/'d \
65 -e '/^Note: timezone set to local timezone of host/d' \
66 -e '/^[ ]*$/d' \
67 | egrep -v -f $tmp/exclude \
68 | sort -t\| -k 1,1 -k 2
71 cat <<'End-of-File' >$tmp/exclude
72 ^pmcd.pmlogger.port
73 End-of-File
75 thres=2
76 opts=""
77 start1=""
78 start2=""
79 finish1=""
80 finish2=""
81 precision=3
82 skip_missing=false
83 skip_excluded=false
85 ARGS=`pmgetopt --progname=$prog --config=$tmp/usage -- "$@"`
86 [ $? != 0 ] && exit 1
88 eval set -- "$ARGS"
89 while [ $# -gt 0 ]
91 case "$1"
93 -d) trap "exit \$status" 0 1 2 3 15
94 otmp="$tmp"
95 tmp=`pwd`/tmp
96 [ -d "$tmp" ] || mkdir "$tmp" || exit 1
97 mv $otmp/exclude $tmp/exclude
98 rmdir $otmp
100 -p) precision="$2"
101 shift
102 opts="$opts -p $precision"
104 -q) thres="$2"
105 shift
107 -S) start1="$2"
108 shift
110 -T) finish1="$2"
111 shift
113 -B) start2="$2"
114 shift
116 -E) finish2="$2"
117 shift
119 -x) echo "$2" >>$tmp/exclude
120 shift
122 -X) cat "$2" >>$tmp/exclude
123 shift
125 -z) opts="$opts -z"
127 -Z) opts="$opts -Z $2"
128 shift
130 --skip-missing)
131 skip_missing=true
133 --skip-excluded)
134 skip_excluded=true
136 --) shift
137 break
139 -\?) _usage
140 # NOTREACHED
142 esac
143 shift
144 done
146 if [ $# -lt 1 -o $# -gt 2 ]
147 then
148 _usage
149 # NOTREACHED
150 elif [ $# -eq 2 ]
151 then
152 arch1="$1"
153 arch2="$2"
154 else
155 arch1="$1"
156 arch2="$1"
159 [ $precision -lt 3 -o $precision -gt 15 ] && precision=3
160 colwidth=`expr 12 + $precision`
162 echo "Directory: `pwd`"
163 if ! $skip_excluded
164 then
165 echo "Excluded metrics:"
166 sed -e 's/^/ /' <$tmp/exclude
168 echo
170 options="$opts"
171 if [ "X$start1" != X ]; then
172 options="$options -S $start1"
174 if [ "X$finish1" != X ]; then
175 options="$options -T $finish1"
177 pmlogsummary -N $options $arch1 2>$tmp/err | _fix >$tmp/1
178 if [ -s $tmp/err ]
179 then
180 echo "Warnings from pmlogsummary ... $arch1"
181 cat $tmp/err
182 echo
185 options="$opts"
186 if [ "X$start2" != X ]; then
187 options="$options -S $start2"
188 elif [ "X$start1" != X ]; then
189 options="$options -S $start1"
191 if [ "X$finish2" != X ]; then
192 options="$options -T $finish2"
193 elif [ "X$finish1" != X ]; then
194 options="$options -T $finish1"
196 pmlogsummary -N $options $arch2 2>$tmp/err | _fix >$tmp/2
197 if [ -s $tmp/err ]
198 then
199 echo "Warnings from pmlogsummary ... $arch2"
200 cat $tmp/err
201 echo
204 if [ -z "$start1" ]
205 then
206 window1="start"
207 else
208 window1="$start1"
210 if [ -z "$finish1" ]
211 then
212 window1="$window1-end"
213 else
214 window1="$window1-$finish1"
216 if [ -z "$start2" ]
217 then
218 window2="start"
219 else
220 window2="$start2"
222 if [ -z "$finish2" ]
223 then
224 window2="$window2-end"
225 else
226 window2="$window2-$finish2"
229 if ! $skip_missing
230 then
231 join -t\| -v 2 $tmp/1 $tmp/2 >$tmp/tmp
232 if [ -s $tmp/tmp ]
233 then
234 echo "Missing from $arch1 $window1 (not compared) ..."
235 sed <$tmp/tmp -e 's/|.*//' -e 's/^/ /'
236 echo
239 join -t\| -v 1 $tmp/1 $tmp/2 >$tmp/tmp
240 if [ -s $tmp/tmp ]
241 then
242 echo "Missing from $arch2 $window2 (not compared) ..."
243 sed <$tmp/tmp -e 's/|.*//' -e 's/^/ /'
244 echo
248 a1=`basename "$arch1"`
249 a2=`basename "$arch2"`
250 echo "$thres" | awk '
251 { printf "Ratio Threshold: >= %.2f or <= %.3f\n",'"$thres"',1/'"$thres"'
252 printf "%*s %*s Ratio Metric-Instance\n",
253 '$colwidth', "'"$a1"'", '$colwidth', "'"$a2"'" }'
254 if [ -z "$start1" ]
255 then
256 window1="start"
257 else
258 window1="$start1"
260 if [ -z "$finish1" ]
261 then
262 window1="$window1-end"
263 else
264 window1="$window1-$finish1"
266 if [ -z "$start2" ]
267 then
268 window2="start"
269 else
270 window2="$start2"
272 if [ -z "$finish2" ]
273 then
274 window2="$window2-end"
275 else
276 window2="$window2-$finish2"
278 printf '%*s %*s\n' $colwidth "$window1" $colwidth "$window2"
279 join -t\| $tmp/1 $tmp/2 \
280 | awk -F\| '
281 function doval(v)
283 precision='"$precision"'
284 extra=precision-3
285 if (v > 99999999)
286 printf "%*.*f%*s",15+extra,0,v,1," "
287 else if (v > 999)
288 printf "%*.*f%*s",11,0,v,2+precision," "
289 else if (v > 99)
290 printf "%*.*f%*s",13+extra,1+extra,v,3," "
291 else if (v > 9)
292 printf "%*.*f%*s",14+extra,2+extra,v,2," "
293 else
294 printf "%*.*f%*s",15+extra,precision,v,1," "
296 $3+0 == 0 || $2+0 == 0 {
297 if ($3 == $2)
298 next
299 doval($2)
300 doval($3)
301 printf " "
302 if ($3+0 == 0)
303 printf "|-| %s\n",$1
304 else if ($2+0 == 0)
305 printf "|+| %s\n",$1
306 next
308 $2 / $3 >= '"$thres"' || $3 / $2 >= '"$thres"' {
309 doval($2)
310 doval($3)
311 printf " "
312 r = $3/$2
313 if (r < 0.001)
314 printf " 0.001-"
315 else if (r < 0.01)
316 printf "%6.3f ",r
317 else if (r > 100)
318 printf " 100+ "
319 else
320 printf "%5.2f ",r
321 printf " %s\n",$1
322 }' \
323 | LC_COLLATE=${LC_COLLATE:-POSIX} sort -k 3,3nr -k 4 \
324 | sed -e 's/100+/>100/' -e 's/ 0.001-/<0.001 /' >$tmp/out
326 # sort in ratio order
328 $PCP_AWK_PROG '$3 == "|+|" {print}' <$tmp/out
329 $PCP_AWK_PROG '$3 == ">100" {print}' <$tmp/out
330 $PCP_AWK_PROG '$3 ~/^[0-9]/ {print}' <$tmp/out
331 $PCP_AWK_PROG '$3 == "<0.001" {print}' <$tmp/out
332 $PCP_AWK_PROG '$3 == "|-|" {print}' <$tmp/out
334 status=0
335 exit