Customize Gunicorn access logs
Choose Gunicorn access-log fields, include request duration, and understand why a JSON-shaped format string is not a JSON serializer.
Gunicorn's default access-log format resembles Apache's combined format:
%(h)s %(l)s %(u)s %(t)s "%(r)s" %(s)s %(b)s "%(f)s" "%(a)s"
Set --access-logformat on the command line or access_log_format in a Python configuration file. Access logging itself is disabled by default; --access-logfile - enables it on standard output.
Common format fields
| Field | Meaning |
|---|---|
%(h)s |
Remote address |
%(t)s |
Request timestamp |
%(r)s |
Request line: method, target, and protocol |
%(s)s |
HTTP status |
%(b)s |
Response length, or - if unavailable |
%(f)s / %(a)s |
Referer / User-Agent |
%(D)s |
Request duration in microseconds |
%(T)s |
Request duration in whole seconds |
%({x-forwarded-for}i)s |
A request header (header names are case-insensitive) |
A forwarded header is supplied by the request path. Trust it as a client address only when your proxy configuration establishes that trust.
Customize the output
For a compact text log:
gunicorn app:app \
--access-logfile - \
--access-logformat '%(h)s %(m)s %(U)s %(s)s %(D)s "%(a)s"'
A tempting alternative is a JSON-shaped template:
gunicorn app:app \
--access-logfile - \
--access-logformat '{"ip":"%(h)s","method":"%(m)s","path":"%(U)s","status":%(s)s,"duration_us":%(D)s,"ua":"%(a)s"}'
This is not a reliable JSON encoder. Gunicorn performs string interpolation, and its access-log escaping is not a general JSON serialization contract. Request-controlled values and control characters can produce invalid JSON. For production JSON logs, use a custom logger or logging formatter that passes a structured object to a JSON serializer, then test representative headers and paths. A JSON-aware collector can parse the resulting records without grok patterns.
Including %(D)s is especially useful when investigating slow requests. Keep its microsecond unit explicit in the destination field name.
FAQ
When does a format change take effect?
Restart Gunicorn, or use the master's supported HUP configuration reload when changing a configuration file. The development --reload option primarily watches application code; do not assume it reloads every configuration change.
Can I disable access logs while retaining error logs?
Yes. Leave accesslog unset and configure --error-logfile separately.
Gunicorn settings document the available fields and logging options.
Contact us
Join the community
to join the community
Try Guance
Start online and pay only for what you use.
Get startedChoose a Guance plan