tkuchikiの日記

Linux やプログラミングについて書きます。

LTSV 形式の Web サーバのアクセスログを集計するツールを作りました

LTSV 形式の Web サーバのアクセスログを集計する、
tkuchiki/alp · GitHub を作成しました。

Install

https://github.com/tkuchiki/alp/releases から各 OS 用のバイナリを取得できます。
Linux 以外では動作確認していませんが、おそらく動作すると思います。

Usage

Labeled Tab-separated Values (LTSV) の Labels for Web server's Log みたいに log を出力すれば、

$ ./alp -f access.log
+-------+-------+-------+-------+-------+-----------+-----------+-----------+-----------+--------+----------+
| COUNT |  MIN  |  MAX  |  SUM  |  AVG  | MAX(BODY) | MIN(BODY) | SUM(BODY) | AVG(BODY) | METHOD |   URI    |
+-------+-------+-------+-------+-------+-----------+-----------+-----------+-----------+--------+----------+
| 1     | 0.123 | 0.123 | 0.123 | 0.123 |    56.000 |    56.000 |    56.000 |    56.000 | GET    | /foo/bar |
| 3     | 0.057 | 0.234 | 0.391 | 0.130 |    12.000 |    34.000 |    80.000 |    26.667 | POST   | /foo/bar |
+-------+-------+-------+-------+-------+-----------+-----------+-----------+-----------+--------+----------+

$ ./alp -f access.log -r
+-------+-------+-------+-------+-------+-----------+-----------+-----------+-----------+--------+----------+
| COUNT |  MIN  |  MAX  |  SUM  |  AVG  | MAX(BODY) | MIN(BODY) | SUM(BODY) | AVG(BODY) | METHOD |   URI    |
+-------+-------+-------+-------+-------+-----------+-----------+-----------+-----------+--------+----------+
| 3     | 0.057 | 0.234 | 0.391 | 0.130 |    12.000 |    34.000 |    80.000 |    26.667 | POST   | /foo/bar |
| 1     | 0.123 | 0.123 | 0.123 | 0.123 |    56.000 |    56.000 |    56.000 |    56.000 | GET    | /foo/bar |
+-------+-------+-------+-------+-------+-----------+-----------+-----------+-----------+--------+----------+

$ ./alp -f access.log -q
+-------+-------+-------+-------+-------+-----------+-----------+-----------+-----------+--------+-----------------------------+
| COUNT |  MIN  |  MAX  |  SUM  |  AVG  | MAX(BODY) | MIN(BODY) | SUM(BODY) | AVG(BODY) | METHOD |             URI             |
+-------+-------+-------+-------+-------+-----------+-----------+-----------+-----------+--------+-----------------------------+
| 1     | 0.057 | 0.057 | 0.057 | 0.057 |    12.000 |    12.000 |    12.000 |    12.000 | POST   | /foo/bar?token=xxx&uuid=xxx |
| 1     | 0.123 | 0.123 | 0.123 | 0.123 |    56.000 |    56.000 |    56.000 |    56.000 | GET    | /foo/bar?token=xxx          |
| 2     | 0.100 | 0.234 | 0.334 | 0.167 |    34.000 |    34.000 |    68.000 |    34.000 | POST   | /foo/bar?token=xxx          |
+-------+-------+-------+-------+-------+-----------+-----------+-----------+-----------+--------+-----------------------------+

$ ./alp -f access.log -q -r
+-------+-------+-------+-------+-------+-----------+-----------+-----------+-----------+--------+-----------------------------+
| COUNT |  MIN  |  MAX  |  SUM  |  AVG  | MAX(BODY) | MIN(BODY) | SUM(BODY) | AVG(BODY) | METHOD |             URI             |
+-------+-------+-------+-------+-------+-----------+-----------+-----------+-----------+--------+-----------------------------+
| 2     | 0.100 | 0.234 | 0.334 | 0.167 |    34.000 |    34.000 |    68.000 |    34.000 | POST   | /foo/bar?token=xxx          |
| 1     | 0.123 | 0.123 | 0.123 | 0.123 |    56.000 |    56.000 |    56.000 |    56.000 | GET    | /foo/bar?token=xxx          |
| 1     | 0.057 | 0.057 | 0.057 | 0.057 |    12.000 |    12.000 |    12.000 |    12.000 | POST   | /foo/bar?token=xxx&uuid=xxx |
+-------+-------+-------+-------+-------+-----------+-----------+-----------+-----------+--------+-----------------------------+

こんな感じに集計できます。
上記の例だと、-q をつけると、QueryString の key? も含めて集計、
つけなければ QueryString 抜きで集計します。
-r は逆順での出力です。

ltsv.org に書いてある通りの label を使っていない場合は、
--apptime-label--size-label--method-label--uri-label で、 label を変更することができます。
何を基準に sort するかは、すべての項目を指定するオプションがあるので、
それを指定すれば OK です。
table 形式で出力したくない場合は、--tsv をつければ TSV 形式で出力することができます。

追記(2015/09/25 14:42)

集計する uri に上限を設定しないと、
メモリを食い潰すことが考えられるので、
上限を設定した v0.0.2 をリリースしました。
--limit で変更でき、デフォルトは 5000 です。

https://github.com/tkuchiki/alp/releases/tag/v0.0.2

追記(2015/09/25 18:42)

--include--exclude オプション追加した v0.0.3 をリリースしました。
https://github.com/tkuchiki/alp/releases/tag/v0.0.3
オプションで指定した文字列を regexp.Match に渡しているだけですので、
Golang正規表現が使えます。
正規表現の syntax は syntax - The Go Programming Language を参照してください。

追記(2015/09/25 23:34)

stdin からも読み込めるようにした v0.0.4 をリリースしました。
https://github.com/tkuchiki/alp/releases/tag/v0.0.4
-f を使わなければ stdin から読み込みますので、
cat access.log | ./alp のような感じで動かせます。

追記(2015/09/28 08:41)

  • --tsv 出力時に header をつけない --noheaders
  • 正規表現にマッチした uri を同じものとして集計する --aggregates
  • --include--exclude--includes--excludes に変更し、カンマ区切りで複数指定可能に

を追加した v0.0.5 をリリースしました。
https://github.com/tkuchiki/alp/releases/tag/v0.0.5
--aggregates は、以下のような挙動になります。 

$ ./alp -f access.log
+-------+-------+-------+-------+-------+-----------+-----------+-----------+-----------+--------+-------------------+
| COUNT |  MIN  |  MAX  |  SUM  |  AVG  | MAX(BODY) | MIN(BODY) | SUM(BODY) | AVG(BODY) | METHOD |        URI        |
+-------+-------+-------+-------+-------+-----------+-----------+-----------+-----------+--------+-------------------+
| 2     | 0.123 | 0.123 | 0.246 | 0.123 |    56.000 |    56.000 |   112.000 |    56.000 | GET    | /foo/bar          |
| 1     | 0.135 | 0.135 | 0.135 | 0.135 |    15.000 |    15.000 |    15.000 |    15.000 | GET    | /diary/entry/1234 |
| 5     | 0.057 | 0.234 | 0.548 | 0.110 |    12.000 |    34.000 |   126.000 |    25.200 | POST   | /foo/bar          |
| 1     | 0.234 | 0.234 | 0.234 | 0.234 |    34.000 |    34.000 |    34.000 |    34.000 | POST   | /hoge/piyo        |
| 1     | 0.432 | 0.432 | 0.432 | 0.432 |    30.000 |    30.000 |    30.000 |    30.000 | GET    | /diary/entry/5678 |
+-------+-------+-------+-------+-------+-----------+-----------+-----------+-----------+--------+-------------------+

$ ./alp -f access.log --aggregates "/diary/entry/\d+"
+-------+-------+-------+-------+-------+-----------+-----------+-----------+-----------+--------+------------------+
| COUNT |  MIN  |  MAX  |  SUM  |  AVG  | MAX(BODY) | MIN(BODY) | SUM(BODY) | AVG(BODY) | METHOD |       URI        |
+-------+-------+-------+-------+-------+-----------+-----------+-----------+-----------+--------+------------------+
| 2     | 0.123 | 0.123 | 0.246 | 0.123 |    56.000 |    56.000 |   112.000 |    56.000 | GET    | /foo/bar         |
| 5     | 0.057 | 0.234 | 0.548 | 0.110 |    12.000 |    34.000 |   126.000 |    25.200 | POST   | /foo/bar         |
| 1     | 0.234 | 0.234 | 0.234 | 0.234 |    34.000 |    34.000 |    34.000 |    34.000 | POST   | /hoge/piyo       |
| 2     | 0.135 | 0.432 | 0.567 | 0.283 |    15.000 |    30.000 |    45.000 |    22.500 | GET    | /diary/entry/\d+ |
+-------+-------+-------+-------+-------+-----------+-----------+-----------+-----------+--------+------------------+

/diary/entry/1234/diary/entry/5678 をまとめて集計しているのがわかるかと思います。
例では一つしか指定していませんが、カンマ区切りで複数指定できます。

追記(2015/09/28 11:13)

ltsv.org の log format に apptime などがなかったようですので、
Apache と Nginx の設定を記載致します。
format が間違っていた場合はご連絡いただけると幸いです。

Apache

LogFormat "time:%t\tforwardedfor:%{X-Forwarded-For}i\thost:%h\treq:%r\tstatus:%>s\tmethod:%m\turi:%U%q\tsize:%B\treferer:%{Referer}i\tua:%{User-Agent}i\treqtime_microsec:%D\tapptime:%D\tcache:
%{X-Cache}o\truntime:%{X-Runtime}o\tvhost:%{Host}i" ltsv

Nginx

log_format ltsv "time:$time_local"
                "\thost:$remote_addr"
                "\tforwardedfor:$http_x_forwarded_for"
                "\treq:$request"
                "\tstatus:$status"
                "\tmethod:$request_method"
                "\turi:$request_uri"
                "\tsize:$body_bytes_sent"
                "\treferer:$http_referer"
                "\tua:$http_user_agent"
                "\treqtime:$request_time"
                "\tcache:$upstream_http_x_cache"
                "\truntime:$upstream_http_x_runtime"
                "\tapptime:$upstream_response_time"
                "\tvhost:$host";

追記(2015/10/28 12:20)

  • --time-label
  • --start-time--end-time
    • 集計するログの時間を指定する
  • --start-time-duration--end-time-duration
    • 集計するログの時間を指定する(現在時刻から golang の time.Duration で指定した時間を引いた時間)

を追加した v0.0.7 をリリースしました。
https://github.com/tkuchiki/alp/releases/tag/v0.0.7
v0.0.6 は、非効率な部分を最適化したもので、 追加機能はありません。

--start-time, --end-time の挙動は以下のとおりです。

$ ./alp -f access2.log --start-time "2015-10-28T11:54:39+09:00"
+-------+-------+-------+-------+-------+-----------+-----------+-----------+-----------+--------+-------------------+
| COUNT |  MIN  |  MAX  |  SUM  |  AVG  | MAX(BODY) | MIN(BODY) | SUM(BODY) | AVG(BODY) | METHOD |        URI        |
+-------+-------+-------+-------+-------+-----------+-----------+-----------+-----------+--------+-------------------+
| 1     | 0.135 | 0.135 | 0.135 | 0.135 |    15.000 |    15.000 |    15.000 |    15.000 | GET    | /diary/entry/1234 |
| 1     | 0.234 | 0.234 | 0.234 | 0.234 |    15.000 |    15.000 |    15.000 |    15.000 | GET    | /foo/bar          |
| 1     | 0.432 | 0.432 | 0.432 | 0.432 |    30.000 |    30.000 |    30.000 |    30.000 | GET    | /diary/entry/5678 |
+-------+-------+-------+-------+-------+-----------+-----------+-----------+-----------+--------+-------------------+

$ ./alp -f access2.log --end-time "2015-10-28 11:45:39+09:00"
+-------+-------+-------+-------+-------+-----------+-----------+-----------+-----------+--------+----------+
| COUNT |  MIN  |  MAX  |  SUM  |  AVG  | MAX(BODY) | MIN(BODY) | SUM(BODY) | AVG(BODY) | METHOD |   URI    |
+-------+-------+-------+-------+-------+-----------+-----------+-----------+-----------+--------+----------+
| 1     | 0.123 | 0.123 | 0.123 | 0.123 |    56.000 |    56.000 |    56.000 |    56.000 | GET    | /foo/bar |
| 3     | 0.057 | 0.234 | 0.391 | 0.130 |    12.000 |    34.000 |    80.000 |    26.667 | POST   | /foo/bar |
+-------+-------+-------+-------+-------+-----------+-----------+-----------+-----------+--------+----------+

$ ./alp -f access2.log --start-time "2015-10-28T11:45:39+09:00" --end-time "2015-10-28 11:55:39+09:00"
+-------+-------+-------+-------+-------+-----------+-----------+-----------+-----------+--------+------------+
| COUNT |  MIN  |  MAX  |  SUM  |  AVG  | MAX(BODY) | MIN(BODY) | SUM(BODY) | AVG(BODY) | METHOD |    URI     |
+-------+-------+-------+-------+-------+-----------+-----------+-----------+-----------+--------+------------+
| 2     | 0.057 | 0.100 | 0.157 | 0.079 |    12.000 |    34.000 |    46.000 |    23.000 | POST   | /foo/bar   |
| 1     | 0.123 | 0.123 | 0.123 | 0.123 |    56.000 |    56.000 |    56.000 |    56.000 | GET    | /foo/bar   |
| 1     | 0.234 | 0.234 | 0.234 | 0.234 |    34.000 |    34.000 |    34.000 |    34.000 | POST   | /hoge/piyo |
+-------+-------+-------+-------+-------+-----------+-----------+-----------+-----------+--------+------------+

--start-time-duration, --end-time-duration の挙動は以下のとおりです。

$ LANG=C date
Wed Oct 28 11:55:39 JST 2015

$ ./alp -f access2.log --start-time-duration 1m # from 2015-10-28T11:54:39+09:00
+-------+-------+-------+-------+-------+-----------+-----------+-----------+-----------+--------+-------------------+
| COUNT |  MIN  |  MAX  |  SUM  |  AVG  | MAX(BODY) | MIN(BODY) | SUM(BODY) | AVG(BODY) | METHOD |        URI        |
+-------+-------+-------+-------+-------+-----------+-----------+-----------+-----------+--------+-------------------+
| 1     | 0.135 | 0.135 | 0.135 | 0.135 |    15.000 |    15.000 |    15.000 |    15.000 | GET    | /diary/entry/1234 |
| 1     | 0.234 | 0.234 | 0.234 | 0.234 |    15.000 |    15.000 |    15.000 |    15.000 | GET    | /foo/bar          |
| 1     | 0.432 | 0.432 | 0.432 | 0.432 |    30.000 |    30.000 |    30.000 |    30.000 | GET    | /diary/entry/5678 |
+-------+-------+-------+-------+-------+-----------+-----------+-----------+-----------+--------+-------------------+

$ ./alp -f access2.log --end-time-duration 10m # to 2015-10-28T11:45:39+09:00
+-------+-------+-------+-------+-------+-----------+-----------+-----------+-----------+--------+----------+
| COUNT |  MIN  |  MAX  |  SUM  |  AVG  | MAX(BODY) | MIN(BODY) | SUM(BODY) | AVG(BODY) | METHOD |   URI    |
+-------+-------+-------+-------+-------+-----------+-----------+-----------+-----------+--------+----------+
| 1     | 0.123 | 0.123 | 0.123 | 0.123 |    56.000 |    56.000 |    56.000 |    56.000 | GET    | /foo/bar |
| 3     | 0.057 | 0.234 | 0.391 | 0.130 |    12.000 |    34.000 |    80.000 |    26.667 | POST   | /foo/bar |
+-------+-------+-------+-------+-------+-----------+-----------+-----------+-----------+--------+----------+

追記(2015/10/30 20:40)

-c|--config config.yml でオプションを設定ファイルで指定できるようにした、
v0.1.0 をリリースしました。
https://github.com/tkuchiki/alp/releases/tag/v0.1.0
優先順位は、コマンドラインオプション > 設定ファイル ですので、
設定ファイルで指定したオプションを上書きすることができます。
example/config.yml に設定ファイルの雛形を置いてあります。

設定ファイル指定かつ、コマンドラインオプションを指定した時に、
一部のオプションが上書きできない問題を修正した、
v0.1.1 をリリースしました。
https://github.com/tkuchiki/alp/releases/tag/v0.1.1

1, 50, 99 パーセンタイル、標準偏差を出力するようにしたv0.2.0 をリリースしました。
https://github.com/tkuchiki/alp/releases/tag/v0.2.0
それぞれ、ソートするオプションがあります。

追記(2015/10/31 00:15)

  • -d|--dump profile.dat で集計したデータをファイルに出力
  • -l|--load profile.dat で集計したデータファイルを読み込む

する、v0.2.1 をリリースしました。
https://github.com/tkuchiki/alp/releases/tag/v0.2.1

このオプションを使用すると、
一度集計して結果をファイルに dump しておけば、
ソートするためだけにログをすべて集計し直す必要がなくなります。