How to Log Request and Response Body Sizes in Nginx Access Logs


2 views

When working with Nginx, many developers coming from Apache background miss the straightforward %I (bytes received) and %O (bytes sent) log format variables. Nginx handles this differently but provides equivalent capabilities through its log module variables.

Nginx provides these essential variables for request/response measurement:

  • $request_length - Total size of request (headers + body)
  • $bytes_sent - Number of bytes sent to client (headers + body)
  • $body_bytes_sent - Body bytes sent (excluding headers)

Here's how to configure your nginx.conf to log these values:

log_format detailed '$remote_addr - $remote_user [$time_local] '
                   '"$request" $status $body_bytes_sent '
                   '"$http_referer" "$http_user_agent" '
                   'req_size=$request_length resp_size=$bytes_sent';

access_log /var/log/nginx/access.log detailed;

For more comprehensive logging including response time and upstream data:

log_format full_tracking '$remote_addr - $remote_user [$time_local] '
                        '"$request" $status $body_bytes_sent '
                        '$request_time $upstream_response_time '
                        'req=$request_length resp=$bytes_sent '
                        'upstream=$upstream_bytes_received';

server {
    access_log /var/log/nginx/full_access.log full_tracking;
    # ... other server configuration
}

1. For accurate POST/PUT request body sizes, ensure client_body_buffer_size is properly configured
2. $bytes_sent includes both headers and body, while $body_bytes_sent shows body only
3. These variables won't show compressed sizes when gzip is enabled

After making changes, test with:

sudo nginx -t
sudo systemctl reload nginx

Sample log output will then show:
192.168.1.100 - - [01/Mar/2023:10:15:32 +0000] "GET /api/data HTTP/1.1" 200 1234 "https://example.com" "Mozilla/5.0" req_size=567 resp_size=2345


In web server administration, tracking the size of HTTP requests and responses is crucial for performance monitoring, debugging, and security analysis. While Apache uses %I and %O for this purpose, Nginx requires a different approach.

Nginx provides built-in variables that capture various aspects of request and response sizes:

$request_length - Total size of request (including headers and body)
$bytes_sent - Number of bytes sent to client (response size)
$body_bytes_sent - Response body size excluding headers
$upstream_response_length - Size of response from upstream server

To log these values, modify your nginx.conf or server block configuration:

log_format extended '$remote_addr - $remote_user [$time_local] '
                   '"$request" $status $body_bytes_sent '
                   '"$http_referer" "$http_user_agent" '
                   'req_size=$request_length resp_size=$bytes_sent';

server {
    access_log /var/log/nginx/access.log extended;
    # ... other server configurations
}

For more granular control with OpenResty or Nginx+Lua:

log_format lua_extended '$remote_addr - $remote_user [$time_local] '
                       '"$request" $status $body_bytes_sent '
                       '"$http_referer" "$http_user_agent" '
                       'req_hdr=$req_headers_size req_body=$req_body_size';

server {
    access_log /var/log/nginx/access.log lua_extended;
    
    set_by_lua_block $req_headers_size {
        return #ngx.req.raw_header()
    }
    
    set_by_lua_block $req_body_size {
        ngx.req.read_body()
        return #ngx.req.get_body_data() or 0
    }
}

Your logs will now show entries like:

192.168.1.100 - - [10/Oct/2023:14:30:45 +0000] "GET /api/data HTTP/1.1" 200 1423 "https://example.com" "Mozilla/5.0" req_size=583 resp_size=1624

While these logging options are useful, be aware that:

  • Logging additional variables increases disk I/O
  • For high-traffic sites, consider sampling or conditional logging
  • Reading request bodies with Lua may impact performance