Quantcast
Channel: プログラミング
Viewing all articles
Browse latest Browse all 7831

nginxのアクセスログを解析してJSONを返すだけのCLIをRustで作成した - stefafafan の fa は3つです

$
0
0

最近RustでCLIを作るのに突然ハマってきたのと、ISUCONが近づいていることもあって、以下のCLIを作ってみました。

github.com

使い方

現状はnginxのlog_formatをJSONとした上で特定のキーを持っていることを想定しています。 (こういう感じの設定をしておく👇)

log_format json escape=json '{''"time":"$time_iso8601",''"host":"$remote_addr",''"method":"$request_method",''"uri":"$request_uri",''"status":"$status",''"body_bytes":"$body_bytes_sent",''"referer":"$http_referer",''"ua":"$http_user_agent",''"request_time":"$request_time",''"response_time":"$upstream_response_time"''}';

この状態で吐かれたアクセスログを、 sekiにパイプして食わせるのみです。以下のような形のJSONが返ってきます。*1

$ cat access.log | seki
[{"method": "GET",
    "uri": "/hello",
    "count": 1,
    "status_code": {"status_1xx": 0,
      "status_2xx": 0,
      "status_3xx": 1,
      "status_4xx": 0,
      "status_5xx": 0},
    "response_time": {"min": 0.0,
      "max": 0.113,
      "avg": 0.113,
      "sum": 0.113,
      "p50": 0.113,
      "p75": 0.113,
      "p90": 0.113,
      "p95": 0.113,
      "p99": 0.113}}]

このJSONをどう使うかはユーザに委ねる、という感じです。

思想

tkuchiki/alpmatsuu/kataribeなど便利ツールが世の中にあるので新たに作る必要は特にないですが*2、思想としてはJSONとして返しておけば色々と加工したり独自のスクリプトに組み込んであれこれしやすそうではないか?と思って作ってみています。

そのため、 seki自体が人間にみやすいフォーマットへの出力オプションを持つ予定はないです。

private-isu でちょっと使ってみた様子

実際に catatsuy/private-isuでも使ってみました。AMIを利用してEC2サーバを建てた上で実施しています。

まず sekiをインストールします。今回は Release v0.1.2 · stefafafan/seki · GitHubに載っている curlを使う手順を使います。

$ curl --proto'=https'--tlsv1.2-LsSf https://github.com/stefafafan/seki/releases/download/v0.1.2/seki-installer.sh | sh

PATHを通したかったら sourceしてねと言われるのでします。

$ source$HOME/.cargo/env

nginx.conf の log_formatを書き換えた上でベンチマークを回します。終わったら早速 sekiを使ってみます。

$ sudo cat /var/log/nginx/access.log | seki

これを何気なく実行すると結果が長すぎることがわかります。 /posts/12667みたいなエンドポイントが沢山個別にならんでいるのでグルーピングします。

一旦エンドポイントの一覧をざっとみてみましょう。 jqコマンドで .uriのみ抽出します。

$ sudo cat /var/log/nginx/access.log | seki | jq '.[] | .uri'"/posts/12667""/posts/2005""/image/6908.jpg""/image/9785.jpg""/image/9228.jpg""/posts/556""/posts/4366""/image/1149.jpg""/posts/7523""/posts/5208""/posts/1797""/posts/3376""/@lindsay""/@violet""/image/1855.jpg""/image/6059.jpg""/posts/7627"
...

/posts/\d+/images/.+/@[a-zA-Z0-9]+みたいなのが沢山ありそうですね。 config.tomlにグルーピングの設定を書きましょう。 リポジトリにもサンプルがあります。*3
github.com

$ vim config.toml
$ cat config.toml
[[grouping]]regexp='^/posts/\d+$'[[grouping]]regexp='^/@[a-zA-Z0-9]+$'name='/@:username'[[grouping]]regexp='^/image/.+'

regexp正規表現を書きます。 nameの指定はオプショナルですが、名前をつけたいときに書いておくとURLが並んだ時に見やすくなります。

今一度先ほどのコマンドを実行してみます。 sekiは同じ階層にある config.tomlをデフォルトで読み込みますが、 --configで明示的にパスを指定することもできます。

$ sudo cat /var/log/nginx/access.log | seki | jq '.[] | .uri'"/login""/posts""/""/@:username""/admin/banned""/image/.+""/comment""/initialize""/js/main.js""/register""/""/css/style.css""^/posts/\\d+$""/favicon.ico""/login""/js/timeago.min.js""/logout"

いい感じにグルーピングができたので、あとは好きな形に加工してベンチの結果を確認してみましょう。今回は response_time.sum順にしつつ、 columnコマンドで整形して出力してみます。

$ sudo cat /var/log/nginx/access.log | seki | \
    jq -r"sort_by(-.response_time.sum) | \        .[] | \        [.method, \        .uri, \        .status_code.status_2xx, \        .status_code.status_3xx, \        .status_code.status_4xx, \        .status_code.status_5xx, \        .response_time.sum] | \        @tsv" | column -t
GET   /                   3939000198.79800000000128
GET   /posts              159000095.20300000000013
GET   ^/posts/\\d+$       282900093.72100000000103
POST  /login              018720078.4420000000002
GET   /@:username         48200040.025
GET   /login              69400019.445999999999984
POST  /                   0162162017.529000000000003
GET   /image/.+           2977906910016.31000000000001
POST  /register           02630012.548999999999992
GET   /logout             0347009.674999999999988
POST  /comment            0244007.659999999999998
GET   /admin/banned       0026307.20899999999999
GET   /initialize         10000.369
GET   /css/style.css      55040000.0
GET   /js/timeago.min.js  55040000.0
GET   /favicon.ico        55040000.0
GET   /js/main.js         55040000.0

GET /が遅そうなので、ここの改善をしていきましょう。

作ってみての感想

当初思っていたよりもサクッとCLIが作れてよかった、 閉包テーブルによる階層構造をPlantUMLやMermaid形式で可視化するツールを作った - stefafafan の fa は3つですの時と同様に clap-rs/clapがやっぱり便利なのと、それ以外にも各種バイナリの用意やリリースのためのツール群 (crate-ci/cargo-releaseaxodotdev/cargo-dist) もとても助かりました。

そして実装の際に alp のこと改めて調べていましたが、めちゃくちゃ機能充実していてすごいなと思ったりしました。実装にあたってalpとkataribeのインターフェースはとても参考にしました、ありがとうございます🙏 複雑なjqのクエリを書くのは大変なのでこれら既存のツールを使うのが一番手っ取り早いなと改めて思いました(が自分でも作るのは楽しかったです)。

次は pt-query-digest代わりのCLIも作りたいです (?)。

*1:もっとこういうJSONのインターフェースにしてほしいみたいなのがあったらいつでもissueなりでコメントお待ちしています!

*2:自分でも作ってみたかったので作ったのが大きい

*3:設定ファイルのフォーマットは kataribe と同じような形式を採用しています🙏


Viewing all articles
Browse latest Browse all 7831

Trending Articles