Є Asterisk, через який дзвонить купа клієнтів. Є задача — отримати від сервера Informix (не питайте, бо не знаю) кількість секунд, які певний клієнт може наговорити, дзвонячи на певний номер телефону. Тобто, для спрощення, на сервер іде запит [номерА, номерБ], сервер віддає число (>=0).
При цьому є підозра, що під кінець місяця сервер думатиме довше; є також підозра, що ті клієнти, що більше говорять, довше чекатимуть відповіді.
Хочеться це все якось бачити. Для цього у той скрипт, який бере дані з Informix’а, додаємо двійко рядків, щоб писати журнал, у приблизно такому вигляді:
# час, «номер клієнта», куди дзвонив, залишок секунд, час на отримання # звісно, всі номери <номерБ> різні: "2012-04-05 17:29:34.455199","01",<номерБ>",0,"0:00:00.078631" "2012-04-05 17:46:47.482675","02",<номерБ>",0,"0:00:00.895389" "2012-04-05 17:48:19.594244","02",<номерБ>",0,"0:00:00.029423" "2012-04-05 17:53:18.827345","02",<номерБ>",0,"0:00:00.033318" "2012-04-05 18:02:59.955417","02",<номерБ>",0,"0:00:00.042353" "2012-04-05 18:05:10.750765","02",<номерБ>",0,"0:00:00.031215" "2012-04-05 18:05:53.240702","02",<номерБ>",0,"0:00:00.029587" "2012-04-05 18:06:47.190297","03",<номерБ>",0,"0:00:00.063169" "2012-04-05 18:56:49.293827","02",<номерБ>",0,"0:00:01.110830" "2012-04-05 19:03:51.475956","02",<номерБ>",0,"0:00:00.032815" "2012-04-05 19:42:59.389716","02",<номерБ>",0,"0:00:00.034776"
Так, зараз на всі запити сервер віддає нуль, не зважайте .)
Зверніть також увагу, що у журнал падає, насправді, не 01, 02, 03 тощо, а номер телефону, з якого йшла спроба дзвонити, — але я ховаю номер телефону, ховатиму його й на графіку, і у скрипті нижче для цього буде вжито певних заходів (тобто, це робитиму не я, а awk
). Тобто, замість номеру телефону awk
підставлятиме «номер клієнта».
На графіку хочемо бачити щось таке (по координаті X буде час):
- червоними хрестиками — час відгуку;
- синіми колами — час від попереднього дзвінка;
- для відгуків > 0.5 секунди біля хрестика писатимемо клієнта;
- і ще якісь усереднення.
Я нижче поясню, чому це не надто ілюстративно для даної задачі, і що варто було б зробити натомість, але — нижче.
Щоб малювати час від попереднього запиту нам мало цих даних — до кожного рядка треба також додати це значення.
Отже, цей скрипт тягне журнал з іншого сервера, прибирає лапки, додає до кожного рядка різницю між часом запису цього рядка (перше поле у журналі) і часом запису попереднього, замість номерів телефонів клієнтів пише абстрактний «номер клієнта» (кожному наступному номеру телефону — який ще не траплявся — дає наступний порядковий номер) і записує «скрипт» для Gnuplot
’а.
# workdir=`/usr/bin/dirname $0` cd $workdir remote="getAvailSeconds.log" filein="getAvailSeconds-in.log" fileout="getAvailSeconds-out.log" plotfile="getAvailSeconds.plot" pdffile="getAvailSeconds.pdf" server="laip" /usr/bin/scp ${server}:"/tmp/${remote}" "${filein}" /bin/cat "$filein" \ | /usr/bin/awk ' BEGIN { # на вході маємо розділені комами поля: FS="," } { # видаляємо подвійні лапки: gsub(/\"/,"",$0); # видаляємо години і хвилини, лишаємо лише секунди: gsub(/^0:00:0*/,"",$5); # беремо час запису з $1 (ігноруємо долі секунди) # (при цьому, до речі, $1 не міняється ж!): time = mktime(gensub("[-:]", " ", "g", substr($1,0,19))); # для *най*першого рядка --- немає часу попереднього запису: if( !oldtime ) { oldtime = time; }; # якщо цього номеру телефону ще не було --- # додаємо у хеш рядок "<наступний_номер>": if ( ! ($2 in clients) ) { clients[$2] = sprintf("%02d", (length(clients) + 1)); } # друкуємо журнал, з якого малюватимемо gnuplot’ом: print $1, clients[$2], $3, $4, $5, (time - oldtime); # запам’ятовуємо час запису: oldtime = time; }' > "$fileout" |
Це лише перша частина — витягування і переформатовування журналу.
Далі створимо «скрипт» для gnuplot
’а — можна було б і без окремого файлу, але він нам може згодитися і як окремий файл. Можливо .)
## за останній місцяць? # start=`date +"%Y-%m-%d %H:%M" --date="1 month ago"` # ні, з моменту, коли почали збирати статистику ,) start="2012-04-05 00:00" end=`/bin/date +"%Y-%m-%d %H:%M" --date="6 hours"` now=`/bin/date +"%Y-%m-%d %H:%M"` /bin/cat <<PLOT > "$plotfile" set title "Time to get data from Informix" set grid set xdata time # це для визначення діапазону часу по X: set timefmt "%Y-%m-%d %H:%M" set xrange ["$start":"$end"] set yrange [0:] set ylabel "seconds" # ми будемо використовувати "enhanced" вихідний формат, # тому можемо масштабувати мітки ("/=4" --- коефіцієнт): set format x "{/=4 %d/%m/%y %H:%M}" set ytics out nomirror # повернемо і трохи опустимо мітки шкали часу: set xtics rotate by 90 out offset 0.3,-4.3 nomirror scale 1.5 # а це описуємо формат часу у файлі з даними: set timefmt "%Y-%m-%d %H:%M:%S" set term pdfcairo enhanced size 8in,5in set output "$pdffile" set tmargin 4; set bmargin 8; set lmargin 11; set rmargin 3 set key left ## for 8in,5in: # трохи опускаємо «номери клієнтів» для відгуків, коротших за 1 секунду, # і трохи піднімаємо для триваліших запитів (див. графік нижче): yoff(y) = (y<1.0) ? (y - 0.07) : (y + 0.02) # ставитимемо на графіку «номер клієнта» лише для запитів, # що чекали довше 0.5 секунди: get_label(y,numA) = (y>0.5)?sprintf("{/=%f client%02i}", 4, numA):"" set arrow from "$now", graph 0 to "$now", graph 1 nohead lc rgb "gray70" # намалюємо два «усереднення», з різними коефіцієнтами: w1 = 1e-13 w2 = 1e-15 plot "$fileout" \\ using 1:6:7 \\ with circles lc rgb "royalblue" title "", \\ "" using 1:6 lc rgb "red" title "", \\ "" using 1:6:(w1) smooth acsplines title sprintf("w: %1.0e", w1) \\ lc rgb "orange", \\ "" using 1:6:(w2) smooth acsplines title sprintf("w: %1.0e", w2) \\ lc rgb "dark-olivegreen", \\ "" using 1:(yoff(\$6)):(get_label(\$6,\$3)) \\ with labels title "" PLOT |
Тут забагато backslash’ів — це тому, що ми виводимо у файл.
От і все, малюємо:
/usr/bin/gnuplot "${plotfile}" |
І маємо отакий (на от зараз) результат! Маємо у PDF, але я сконвертував, щоб вставити у сторінку:
Це не ілюстративно? Чому?
Так, це не ілюстративно, бо ми не бачимо, чи характерні для цих певних клієнтів отакі певні «викиди». Тобто, якийсь клієнт може подзвонити (спробувати подзвонити) раз у житті, але на сервері було саме щось негаразд, він чекав три секунди.
Тому ці всі «усереднення» з різними ваговими коефіцієнтами — це «середня температура по лікарні» .)
Значно цікавіше було б малювати не всіх клієнтів червоними хрестиками, а кожного клієнта малювати окремо… Наприклад, час від попереднього запиту малювати горизонтальною рискою вліво, а середньоквадратичне відхилення для даного клієнта малювати колом (з радіусом, що дорівнює цьому СКВ)… Але що нам заважає?-)
Ми дуже просто можемо модифікувати наш awk’овий скрипт:
# ... # пишемо для кожного клієнта «його власний» файл із даними: print $1, clients[$2], $3, $4, $5, (time - oldtime) > sprintf("client%02s.data", clients[$2]); # запам’ятовуємо час запису: oldtime = time; } END { # після завершення роботи пишемо перелік клієнтів: for ( val in clients ) { print clients[val] > "clients.list"; } }' > "$fileout" |
Після цього gnuplot
’ом малюватимемо кожен набір даних окремим кольором, «іншими хрестиками», усереднюватимемо незалежно від решти тощо. Так, для цього треба трохи модифікувати «скрипт для gnuplot
’а», але ж ми це справді можемо :-)
Чи буде це ілюстративніше?-) Напевно, буде! Але я не пробував .)