kanban-app/backend/gunicorn.conf.py

59 lines
1.7 KiB
Python
Raw Normal View History

2026-08-09 12:49:45 +00:00
"""Gunicorn configuration.
All Gunicorn settings live here instead of the Dockerfile CMD so they can be
tweaked without rebuilding the image, and so the access-log format/timezone are
defined in one place.
"""
import os
import time
from datetime import datetime, timezone
from zoneinfo import ZoneInfo
from gunicorn.glogging import Logger
TIMEZONE = os.environ.get("TZ", "UTC")
class CustomLogger(Logger):
"""Gunicorn logger that emits timezone-aware ISO timestamps."""
def atoms(self, resp, req, environ, request_time):
"""Build the log atoms, overriding the time atom with a custom format."""
atoms = super().atoms(resp, req, environ, request_time)
try:
now = datetime.now(ZoneInfo(TIMEZONE))
except Exception:
now = datetime.now(timezone.utc)
# [09/Aug/2026:17:42:48 +0000] -> [2026-08-09 20:41:00 +0300]
atoms["t"] = now.strftime('%Y-%m-%d %H:%M:%S %z')
return atoms
# ---- Server ----
bind = "0.0.0.0:8000"
workers = 2
# ---- Logging ----
accesslog = "-"
errorlog = "-"
capture_output = True
loglevel = "info"
# %(h)s = real client IP. Gunicorn resolves X-Forwarded-For based on its built-in
# proxy trust logic (the same mechanism already validated behind Traefik).
# %(t)s = overridden by CustomLogger -> [2026-08-09 20:41:00 +0300]
access_log_format = '%(h)s - - [%(t)s] "%(r)s" %(s)s %(b)s "%(f)s" "%(a)s"'
# logger_class = "gunicorn.conf:CustomLogger"
logger_class = CustomLogger
# ---- Timezone for Python logging / error logs ----
# Default to UTC unless TZ is set (e.g. TZ=Africa/Nairobi at docker run time).
os.environ.setdefault("TZ", os.environ.get("TZ", "UTC"))
try:
time.tzset()
except AttributeError: # non-Unix
pass