As of Nginx 1.11.8 you can use the parameter escape=json in your log_format definition to handle JSON encoding and escaping. Here’s a sample log format you can use.

http {
    ...
    log_format  json-log  escape=json '{'
        '"bytes_sent": $bytes_sent, '
        '"body_bytes_sent": $body_bytes_sent, '
        '"http_referer": "$http_referer", '
        '"http_user_agent": "$http_user_agent", '
        '"port": "$server_port", '
        '"remote_addr": "$remote_addr", '
        '"remote_user": "$remote_user", '
        '"request": "$request", '
        '"request_time": $request_time, '
        '"status": $status, '
        '"time_local": "$time_local", '
        '"http_host": "$host", '
        '"x_forwarded_for": "$http_x_forwarded_for", '
        '"x_request_id":"$http_x_request_id"'
    '}';
    ...
}

Configure server to use json-log definition.

server {
    ...
    access_log  logs/access.log  json-log;
    ...
}

Example log line.

{"bytes_sent": 1000, "body_bytes_sent": 700, "http_referer": "", "http_user_agent": "curl/7.47.0", "port": "80", "remote_addr": "127.0.0.1", "remote_user": "", "request": "GET / HTTP/1.1", "request_time": 0.100, "status": 200, "time_local": "01/Jan/2020:13:42:36 -0700", "http_host": "localhost", "x_forwarded_for": "", "x_request_id":""}

Passed through jq.

{
  "bytes_sent": 1000,
  "body_bytes_sent": 700,
  "http_referer": "",
  "http_user_agent": "curl/7.47.0",
  "port": "80",
  "remote_addr": "127.0.0.1",
  "remote_user": "",
  "request": "GET / HTTP/1.1",
  "request_time": 0.100,
  "status": 200,
  "time_local": "01/Jan/2020:13:42:36 -0700",
  "http_host": "localhost",
  "x_forwarded_for": "",
  "x_request_id": ""
}

This takes the load off of logstash and puts it on the web server. Depending on your system architecture, this may be desirable. See this post for a simple logstash filter to process the incoming log line.

Tagged on: