1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

アクセスログからAPIごとにカウント取ったり成形したり

Posted at

APIリクエストごとにカウント取ってみた

「ログ見てるけど情報量多すぎて嫌になる」

このような経験、ありませんか?

そんな苦い経験とは金輪際、おさらばしましょう。

本記事では、コマンドを駆使してログを見やすく加工したり、カウントする方法を紹介します。

使用するコマンド

## ファイルを標準出力
cat

## 行数を指定して出力
head

## テキスト処理コマンド
awk

## 繰り返し処理
for

## 特定文字列を除外
sed

## 文字列出力
printf

## 出力のソート
sort

## 出力を一意の結果にする
uniq

まずは普通に出力

cat コマンド使います

cat app.log
[2018-06-07 19:58:15] lumen.DEBUG: -- Startup {"method":"GET","uri":"/api/API/apipipipi/1"} []
[2018-06-07 19:58:15] lumen.DEBUG: -- Shutdown {"time":"234.990[ms]","memory":"10[mb]"} []
~~~100行くらい~~~
[2018-06-07 20:03:56] lumen.DEBUG: -- Shutdown {"time":"67.988[ms]","memory":"2048[kb]"} []

100行か。。。まだ大丈夫な範囲だけど本番のログだと篦棒にある気がする。
そんなの見てたら目が痛くなりますよね。
大量のログを凝視している方を見ていると僕は思わずニヤニャ...ゲフン。胸が痛くなります。

さて次は作業しやすいように数行だけ出力してみましょう。

先頭から数行だけ出力してみる

先頭から3行だけ出力してみましょうか。
catコマンドにパイプとheadコマンドを使いますが、オプションで-nをつけて行数をそのあとに指定しましょう。

$ cat app.log | head -n3
[2018-06-07 19:58:15] lumen.DEBUG: -- Startup {"method":"GET","uri":"/api/API/apipipipi/1"} []
[2018-06-07 19:58:15] lumen.DEBUG: -- Shutdown {"time":"234.990[ms]","memory":"10[mb]"} []
[2018-06-07 19:58:16] lumen.DEBUG: -- Startup {"method":"GET","uri":"/api/API/apipipipi/2"} []

先頭から3行だけ出力されました。

必要部分のみ抽出して出力

お次はカウントに必要な情報。すなわちAPI部分のみ抜き出してみましょう。

必要な情報 → {"method":"GET","uri":"/api/API/apipipipi/x"}

awk コマンド使います。様々な使い方あるので興味ある方は調べて見てください。

$ cat app.log | head -n3 | awk '{print $6}'
{"method":"GET","uri":"/api/API/apipipipi/1"}
{"time":"234.990[ms]","memory":"10[mb]"}
{"method":"GET","uri":"/api/API/apipipipi/2"}

これで「3行のログの中の”半角スペース(タブ)で区切られた6桁目”の文字列」を出力できました。
だいぶショートボディになりましたね。

あれ、でも今回のカウント作業で使わないデータが含まれてますね。

こいつ → {"time":"234.990[ms]","memory":"10[mb]"}

欲しい行だけ抽出しましょう。grepコマンドを使います。
やり方は2パターンありますのでどちらを使っても問題ないですが、一致する行を抽出した方がきっと楽でしょう。

## 条件に一致する行を削除する方法
$ cat app.log | grep -v "memory"| head -n3 | awk '{print $6}'
{"method":"GET","uri":"/api/API/apipipipi/1"}
{"method":"GET","uri":"/api/API/apipipipi/2"}
{"method":"POST","uri":"/api/API/apipipipi/3"} 
## 条件に一致する行を抽出する方法
$ cat app.log | grep "method"| head -n3 | awk '{print $6}'
{"method":"GET","uri":"/api/API/apipipipi/1"}
{"method":"GET","uri":"/api/API/apipipipi/2"}
{"method":"POST","uri":"/api/API/apipipipi/3"}

これで不要な行を除外できました。

さらに見やすいように成形

初期よりは見やすくなりましたが、まだ無駄な情報があったりしますよね。
ぶっちゃけこのままでもカウント取れるのですが、せっかくなので成形してみましょう。

またまたawkを利用しますが、今回は少し特殊です。
特殊なawk部分だけを見てみましょう。

awk -F '/' '{for(i=2;i<NF;i++){printf("%s%s",$i,OFS="/")}print $NF}'
  • -Fオプションで区切り文字を指定
  • for文で「◯桁目〜改行文字まで」を出力
  • printf("%s%s",$i,OFS="/")で対象の桁、”/”を繋げて出力
  • print $NFで改行文字を出力

組み合わせると結果がこうなります。確認のため1行だけ出力します。

$ cat app.log | grep method| head -n1 | awk '{print $6}' |\
    awk -F'/' '{for(i=2;i<NF;i++){printf("%s%s",$i,OFS="/")}print $NF}'

api/API/apipipipi/1"}

お、だんだん良い感じになってきましたね。
※ただfor文を利用する為負荷がかかります。ログが膨大な場合は注意が必要です。

いらない文字列を除外する

末尾の「"}」が邪魔ですね。消してしまいましょう。
sedを使います。

$ cat app.log | grep method| head -n1 | awk '{print $6}' |\
    awk -F'/' '{for(i=2;i<NF;i++){printf("%s%s",$i,OFS="/")}print $NF}' |\
    sed -e "s/\"}//g"

api/API/apipipipi/1

いい感じにソートしよう

sortを使います。また、全行出力するためにheadを除いて実行!

$ cat app.log | grep method| awk '{print $6}' |\
   awk -F'/' '{for(i=2;i<NF;i++){printf("%s%s",$i,OFS="/")}print $NF}' |\
   sed -e "s/\"}//g" | sort

api/API/apipipipi/1
api/API/apipipipi/2
~~100行くらい~~
api/API/apipipipi/1
api/API/apipipipi/3

いい感じいい感じ。

ラスト!ユニークな値ごとにカウントしよう

uniqを使います。
オプション-cでカウントできます。

$ cat app.log | grep method| awk '{print $6}' |\
    awk -F'/' '{for(i=2;i<NF;i++){printf("%s%s",$i,OFS="/")}print $NF}' |\
    sed -e "s/\"}//g" | sort | uniq -c

2 api/API/apipipipi/1
3 api/API/apipipipi/2
2 api/API/apipipipi/3
1 api/API/apipipipi/8
2 api/API/apipipipi/5
20 api/API/apipipipi/11
~~数十行くらい

これでAPIごとのカウントが取得できました。

まとめ

コマンド便利。
今回紹介したコマンドですが、コピペではおそらく期待している結果は出力されないと思います。
サービスによってログの形式が異なるので、ニーズに合わせてカスタマイズしてください。

おまけ

ちょっと見やすくしてみた

$ cat app.log \
    | grep method \
    | awk '{print $6}' \
    | awk -F'/' '{for(i=2;i<NF;i++){ \
        printf("%s%s",$i,OFS="/") \
    } print $NF}' \
    | sed -e "s/\"}//g" \
    | sort \
    | uniq -c
;

一部冗長な表現があると思いますが、わかりやすく見せるために簡単に書いてます。
利用される機会があればぜひ。

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?