🌒

OpenResty(NGINX)で必要な時だけ任意のファイルにlogを出力する

に公開

これは何?

OpenResty(NGINX)を使用していて,特定のイベント発生時にerror.log以外のファイルにログを出力したい場面がありました。
これを実現するために,ngx_http_log_moduleのif機能がうまく使えたので防備録的に書いておきます。

  • 常時必要なログではない。特定のタイミングのみログを出力したい。
  • error.log以外のファイルに出力したい。

こういったケースでのテクニックです。


環境

OpenResty(NGINX + Lua)


やり方

nginx.confでlog_formatを定義する

以下の例ではlogs/auth_fail.logにログを出力する設定をします。
timeは定義済みの変数ですが,カスタム変数(user_id)も使用可能です。

 log_format auth_fail_log 'time: $time_iso8601\t'
                           'user_id: $user_id;

  map $status $loggable {
    default 0;
  }
  access_log logs/auth_fail.log auth_faile_log if=$loggable;

The if parameter (1.7.0) enables conditional logging. A request will not be logged if the condition evaluates to “0” or an empty string. [1]

とのことなのでif=0以外だとこのlogが出力される仕組みです。

:::note info
log_format内でsetを使って変数(loggable)を定義するとエラーになるので,mapを代わりに使っている。
:::

Lua Scriptでloggableの値を変えてやる

現状のままだと,ずっとif=0になってしまうので必要な時だけ値を0以外にしてやります。

以下のnginx.confの設定で/配下にアクセスした際にmain.luaが実行されるようにします。このmain.luaの中からnginx.confの変数を書き換えます。

        location / {
            root /usr/local/openresty/reverse_proxy/html;
            default_type 'text/html';
            set $user_id ""; # カスタム変数を定義
            access_by_lua_file /usr/local/openresty/reverse_proxy/src/main.lua;
        }

-- 認証するスクリプトは省略...
if err then
  --CASE=認証失敗
  ngx.var.loggable = 1
  ngx.var.user_id = user
end  

なぜこのやり方をするのか

  • Lua Scriptでファイルをopen closeして読み書きするよりもパフォーマンスが良いはず。
  • Lua Scriptのngx.log()で出力できるのは基本的にerror.logになるので出力先は変えられない。

Reference

脚注
  1. https://nginx.org/en/docs/http/ngx_http_log_module.html ↩︎

GitHubで編集を提案

Discussion