TL;DR
log_format
ディレクティブでパラメータ escape=json
を指定する。
http {
:
log_format json escape=json '{"time": "$time_iso8601",'
'"host": "$remote_addr",'
'"vhost": "$host",'
'"user": "$remote_user",'
'"status": "$status",'
'"protocol": "$server_protocol",'
'"method": "$request_method",'
'"path": "$request_uri",'
'"req": "$request",'
'"size": "$body_bytes_sent",'
'"reqtime": "$request_time",'
'"apptime": "$upstream_response_time",'
'"ua": "$http_user_agent",'
'"forwardedfor": "$http_x_forwarded_for",'
'"forwardedproto": "$http_x_forwarded_proto",'
'"referrer": "$http_referer"}';
server {
:
access_log /path/to/access_log json; # 上で設定したjsonフォーマットを使う
:
}
:
}
解説
この escape
パラメータのデフォルト値は default
である。
この場合、 "
(0x22)や '
(0x27)はそれぞれ \x22
, \x27
のようにエスケープされる。1
json
オプションはNginx 1.11.8で導入された。
また、Nginx 1.13.10では escape=none
によって、エスケープしないというオプションが追加されるようだ。2
数値を数値型で扱わないのはなぜか?
$status
や $request_time
のような、本来JSONの数値型で扱うべき値も "$status"
のように文字列型で扱っていることが気になるという人がいるかもしれない。
これらのような値をクォートしない形式で設定するとどうなるだろうか。
実は、値が取得できないときに空文字になり、invalidなJSONになってしまう。
結果として、エラーによりログ出力ができなくなってしまう。
そこで、ここでは簡単のため文字列型で扱う例を示した。
参考
- logging - How to generate a JSON log from nginx? - Stack Overflow #42564710
- nginxのアクセスログをjson形式で出力する - Qiita #comment-44552e94bfe652f88560
脚注
-
0x00-0x1F, 0x7F-0xFFの範囲の文字も同様にエスケープされる。参考: http://nginx.org/en/CHANGES v0.7.0, v1.1.6の変更。 ↩
-
https://trac.nginx.org/nginx/ticket/1450 のパッチによるようだ。 ↩