読者です 読者をやめる 読者になる 読者になる

時間あたりの平均レスポンスとかを求めるのに便利なコマンドを書いてみた

シェル linux operation

どうも、最近、ログの解析ばかりしています。

で、わりと良くやるのが、1分あたりのアクセス数や平均時間を求めたりとかですね。

以前、こっちの記事とかでも書いた話ですね。

 

必要に応じて毎回書き下ろしてたのですが、さすがに面倒になってきたので、グルーピングして、その対象に対して任意の処理を適用する汎用シェルを書いてみました。

「grouping and map」ということでgmapとしてみたけど、もうちょっと良い概念名がありそうな。というか、mapというかreduceの気がする。目的的には。

 

それはそれとして、使い方は下記の通り。

time:14:00:01   req:/   response:100
time:14:00:02   req:/test1      response:1
time:14:01:03   req:/test2      response:2
time:14:02:04   req:/test1      response:10

 こんな感じのアクセスログがあるとして、1分辺りの平均レスポンスを求めたいなら

% ./gmap.sh /mnt/share/test.ltsv 'substr($1,6,5)' ./ltsv.sh '{sum += ltsv("response");cnt++}END{print sum/cnt}'
14:00   50.5
14:01   2
14:02   10

 こんな感じ。第一引数がファイル名、第二引数がフィルタ、第三引数がフィルタリングしたグループ毎に実行したいコマンド、第四引数、第五引数が実行したいコマンドの引数になります。

フィルタはawkのものをそのまま使ってるので、substrとかも使えて高機能。

 

URL毎のリクエスト数が求めたいならこう。

./gmap.sh /mnt/share/test.ltsv '$2' awk '{cnt++}END{print cnt}'
req:/   4
req:/test1      2
req:/test2      1

 これで集計処理が結構捗るはず。昨日書いたltsv.shと組み合わせて使うといい感じに強力。

コードは下記の通り

#!/bin/sh

file=$1
filter=$2
cmd=$3
arg1=$4
arg2=$5
arg3=$6

if [ "$cmd" = "" ];then
  echo "Usage: "
  echo "`basename $0` filename filter command [arg1] [arg2] [arg3]"
  exit
fi

for item in `cat $file| awk '{print '"${filter}"'}'|sort|uniq`
do
  echo -n "${item}\t"
  grep $item $file|${cmd} "${arg1}" "${arg2}" "${arg3}"
done

あとは、集約というかレポーティングかなー。Zabbixに集めるという手もあるが、目的外使用だろうしあんまり幸せになれないかも。growthforecast とかかな? OOoのベースも実は使えるんじゃないかと狙ってるけど。GoogleAppsのCalcも良さそう。まあ、いろいろ考えてみよ。

 

それではHappy Hacking!