kanban-app/backend/gunicorn.conf.py
2026-08-09 21:17:53 +03:00

59 lines
No EOL
1.7 KiB
Python

"""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