nginx で UUID を生成して X-Request-Id ヘッダを追加する
Posted on
nginx で UUID を生成して X-Request-Id
ヘッダを追加する方法を調べてみました。 X-Request-Id
ヘッダをレスポンスに含めておけば、Web / App サーバのログをリクエスト毎に串刺し検索できるので、問題が起きたときにスムーズに調査できます。
X-Amzn-Trace-Id は検討したものの…
本題に入る前に。もともとは nginx で UUID を生成するのではなく、ALB が追加する X-Amzn-Trace-Id
ヘッダを使おうと思っていました。 X-Amzn-Trace-Id
は Field=version-time-id
というフォーマットになっています。
X-Amzn-Trace-Id: Self=1-67891234-12456789abcdef012345678;Root=1-67891233-abcdef012345678912345678
ALB が自動的に付与してくれるので UUID 生成のコストがかかりませんが、Rails の ActionDispatch::RequestId
は "max of 255 chars and alphanumeric and dashes only" という制約があり、そのままでは使えないことがわかりました。
ngx_txid で UUID を生成する
さて、ここからが本題です。 X-Request-Id
の値となる UUID を生成するために ngx_txid を使います。このモジュールを使うと $txid
という nginx の変数で UUID が取得できます。
ngx_txid
is a module that exposes$txid
: a cached, request scoped, 20 character, base32hex encoded, temporally and lexically sortable, case insensitive, 96 bit identifier.
ngx_txid を使うには nginx のコンパイル時に --add-module
で指定する必要があります。
--add-module=path/to/ngx_txid
nginx -V
でコンパイルオプションが確認できます。ワンライナーで確認するなら、こんな感じです。
nginx -V 2>&1 | tr " " "\n" | grep ngx_txid
--add-module=/usr/local/src/ngx_txid
問題なければ、あとは $txid
を HTTP ヘッダやログに設定するだけです。ログは log_format
に追加するだけですが、HTTP ヘッダはアプリケーションサーバによって設定が違います。
nginx + Rack の場合
nginx + Unicorn のように Rack サーバへリバースプロキシする場合は proxy_set_header
でプロキシサーバに渡します。
server {
listen 80;
server_name example.com;
location / {
remove_header X-Request-Id;
add_header X-Request-Id $txid;
proxy_set_header X-Request-Id $txid;
proxy_pass http://localhost:8080;
}
}
nginx + Passenger の場合
nginx + Passenger の場合はリバースプロキシするわけではないので proxy_set_header
は当然効きません。 Passenger の場合は passenger_set_header
を使います。
server {
listen 80;
server_name example.com;
location / {
remove_header X-Request-Id;
add_header X-Request-Id $txid;
passenger_enabled on;
passenger_set_header X-Request-Id $txid;
}
}
まとめ
ngx_txid を使えば、nginx で UUID を生成して X-Request-Id
ヘッダが追加できました。本番環境にも導入しましたが UUID 生成の CPU 負荷も気になりません。
本来は上流にあるロードバランサで追加するのが理想的なので、引き続き ALB の X-Amzn-Trace-Id
ヘッダを使う方法を考えてみようと思います。