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.

Best practices
Customize Gunicorn access logs

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.

Get a tailored plan

Contact us

Join the community

Scan with WeChat
to join the community

Try Guance

Start online and pay only for what you use.

Get started

Choose a Guance plan

Code hosting